Code injection during object deserialization

ID

python.code_injection_deserialization

Severity

critical

Resource

Injection

Language

Python

Tags

CWE:502, NIST.SP.800-53, OWASP:2021:A8, PCI-DSS:6.5.1

Description

Improper deserialization of untrusted data, possibly allowing code injection attacks.

Deserialization vulnerabilities arise when an application deserializes user-controlled data without proper validation, potentially allowing attackers to instantiate unexpected objects or execute crafted functions leading to arbitrary code execution or system exploits.

Rationale

After detecting the vulnerable site, attackers typically craft a payload that is serialized and sent to the application. If the application deserializes this payload without validation, attackers can modify the expected data structure to escalate privileges or perform unwanted actions.

In the worst case, the attackers inject an object of an unexpected type, triggering chosen code execution. This could be used to exfiltrate internal server’s data, install malware e.g. to install and persist crypto-miners, or run a reverse shell.

Consider the following Python example:

import pickle
from flask import Flask, request

app = Flask(__name__)

@app.route('/deserialize')
def unsafe_deserialize():
    # Directly deserializing user input
    serialized_data = request.data
    data = pickle.loads(serialized_data)
    return 'Deserialization successful!'

In this example, the application directly deserializes data received in a request. With Python’s pickle, this could allow an attacker to craft data that executes arbitrary code on the server, leading to severe security implications.

Remediation

If possible, do not deserialize content to objects when the source is not fully trusted.

Mitigating deserialization vulnerabilities involves several key practices:

  1. Avoid Deserialization of Untrusted Input: The most secure approach is to avoid deserializing any untrusted data outright. If deserialization is necessary, consider other safe data formats such as JSON or XML with strict schema validation.

  2. Use Secure Libraries: Employ libraries or frameworks that provide secure deserialization mechanisms.

  3. Validation and Whitelisting: Implement strict validation. Use a whitelist approach where only the expected, permitted, and safe classes are allowed to be deserialized.

import json
from flask import Flask, request

app = Flask(__name__)

@app.route('/deserialize')
def safe_deserialize():
    # Use safer methods like JSON for serialization
    try:
        serialized_data = request.data
        data = json.loads(serialized_data)
    except json.JSONDecodeError:
        return 'Invalid data!', 400

    return 'Deserialization successful!'

In this improved example, json.loads() is used instead of pickle.loads(). JSON serialization does not allow arbitrary code execution, making it a safer option for handling untrusted data. Additionally, input validation is employed to ensure robustness against malformed input.

Configuration

The detector has the following configurable parameters:

  • sources, that indicates the source kinds to check.

  • neutralizations, that indicates the neutralization kinds to check.

Unless you need to change the default behavior, you typically do not need to configure this detector.

References