python.aws-lambda.security.dangerous-subprocess-use.dangerous-subprocess-use

profile photo of semgrepsemgrep
Author
unknown
Download Count*

Detected subprocess function with argument tainted by an event object. If this data can be controlled by a malicious actor, it may be an instance of command injection. The default option for shell is False, and this is secure by default. Consider removing the shell=True or setting it to False explicitely. Using shell=False means you have to split the command string into an array of strings for the command and its arguments. You may consider using 'shlex.split()' for this purpose.

Run Locally

Run in CI

Defintion

rules:
  - id: dangerous-subprocess-use
    mode: taint
    message: Detected subprocess function with argument tainted by an `event`
      object.  If this data can be controlled by a malicious actor, it may be an
      instance of command injection. The default option for `shell` is False,
      and this is secure by default. Consider removing the `shell=True` or
      setting it to False explicitely. Using `shell=False` means you have to
      split the command string into an array of strings for the command and its
      arguments. You may consider using 'shlex.split()' for this purpose.
    metadata:
      owasp:
        - A01:2017 - Injection
        - A03:2021 - Injection
      cwe:
        - "CWE-78: Improper Neutralization of Special Elements used in an OS
          Command ('OS Command Injection')"
      asvs:
        section: "V5: Validation, Sanitization and Encoding Verification Requirements"
        control_id: 5.3.8 OS Command Injection
        control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v53-output-encoding-and-injection-prevention-requirements
        version: "4"
      references:
        - https://docs.python.org/3/library/subprocess.html
        - https://docs.python.org/3/library/shlex.html
      category: security
      technology:
        - python
        - aws-lambda
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      cwe2022-top25: true
      cwe2021-top25: true
      subcategory:
        - vuln
      likelihood: HIGH
      impact: MEDIUM
      confidence: MEDIUM
      vulnerability_class:
        - Command Injection
    languages:
      - python
    severity: ERROR
    pattern-sources:
      - patterns:
          - pattern: event
          - pattern-inside: |
              def $HANDLER(event, context):
                ...
    pattern-sinks:
      - patterns:
          - pattern: subprocess.$FUNC(..., shell=True, ...)
    pattern-sanitizers:
      - pattern: shlex.split(...)
      - pattern: pipes.quote(...)
      - pattern: shlex.quote(...)

Examples

dangerous-subprocess-use.py

import subprocess
import sys
import shlex

def handler(event, context):
  # ok:dangerous-subprocess-use
  subprocess.call("echo 'hello'")

  # ok:dangerous-subprocess-use
  subprocess.call(["echo", "a", ";", "rm", "-rf", "/"])

  # ruleid:dangerous-subprocess-use
  subprocess.call("grep -R {} .".format(event['id']), shell=True)

  # ok:dangerous-subprocess-use
  subprocess.call("grep -R {} .".format(event['id']))

  cmd = event['id'].split()
  # ok:dangerous-subprocess-use
  subprocess.call([cmd[0], cmd[1], "some", "args"])

  # ruleid:dangerous-subprocess-use
  subprocess.call([cmd[0], cmd[1], "some", "args"], shell=True)

  # ruleid:dangerous-subprocess-use
  subprocess.call("grep -R {} .".format(event['id']), shell=True)

  # ruleid:dangerous-subprocess-use
  subprocess.call("grep -R {} .".format(event['id']), shell=True, cwd="/home/user")

  python_file = f"""
      print("What is your name?")
      name = input()
      print("Hello " + {event['id']})
  """
  # ok:dangerous-subprocess-use
  program = subprocess.Popen(['python2', python_file], stdin=subprocess.PIPE, text=True)

  # ruleid:dangerous-subprocess-use
  program = subprocess.Popen(['python2', python_file], stdin=subprocess.PIPE, text=True, shell=True)

  # ruleid:dangerous-subprocess-use
  program = subprocess.Popen(['python2', python_file], stdin=subprocess.PIPE, shell=True, text=True)

  # ok:dangerous-subprocess-use
  program = subprocess.Popen(['python2', shlex.quote(python_file)], stdin=subprocess.PIPE, shell=True, text=True)

  program.communicate(input=payload, timeout=1)