Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

As you read these, you'll find a number common themes. I particularly like how the SAFECode lays things out into separate practices for Design, Coding, and Testing & Validation. Under Design, they discuss: Secure Design Principles, Threat modeling, Encryption Strategy, Standardize Identity and Access, and Establish Log and Audit Practices. Under Coding, they discuss: Coding Standards, Using safe functions only, Using code analysis tools, Handling data safely, and Error Handling. And under Testing, they discuss both Automated and Manual Testing. OWASP concentrates on coding practices, with checklists in these categories:

OWASP Coding Practice Checklists
Input ValidationError Handling and Logging
Output EncodingData Protection
Authentication and Password ManagementCommunication Security
Session ManagementSystem Configuration
Access ControlDatabase Security
Cryptographic Practices
Error Handling and Logging
Data Protection
Communication Security
System Configuration
Database SecurityFile Management
Memory ManagementGeneral Coding Practices

Invoking  External Processes

The SECCOM was recently asked to make specific recommendations about how to safely invoke external programs from a language such as Python. In general, the problem boils down to:

...

The following examples use shell and python for exposition, but the issue exists in all languages that provide mechanisms to execute subprocesses, including Java, C and C++.

  • Use full paths for the programs you are executing. For example,
    • shell: /bin/ls -l file
    • python: subprocess.Popen(["/bin/ls", "-l", "file"])
  • If your external programs can be found in a variety of locations depending on the system on which they are run, use exact control over the PATH used to find your program, or prepend known locations to the beginning of the PATHprograms. For example, you can add a line to the beginning of your program such as:
    • shell: export PATH=/bin:/usr/bin or : export PATH="/sbin:/usr/sbin:/bin:/usr/bin:$PATH"
    • python: os.environ['PATH'] = '/bin:/usr/bin' or os.environ['PATH'or] = '/sbin:/usr/sbin:/bin:/usr/bin'
  • If you must depend on an externally-provided path, combine prepending known locations to the beginning of the PATH, and sanitize the rest of it. For example, you can add a line to the beginning of your program such as:
    • bash shell: export PATH="/bin:/usr/bin:$(sanitize "$PATH")"
    • python: os.environ['PATH'] = f"/bin:/usr/bin:{sanitize(os.environ['PATH'])}"
    • The purpose of the sanitize() invocation is to remove the current directory from the PATH. For example, TBA


  • Use exact control over the command line arguments. For example, in Python avoid using "shell=True" with the subprocess module's methods, which can allow unexpected parsing or expansion of the values being passed.

...

  • Use exact control over the current directory before invoking a program using a relative path. For example, invoking "../somewhere/something" will act differently depending on where it is invoked.
    • If your program does a cd/chdir, ALWAYS check that it succeeded before proceeding. For example,
      • shell: cd somewhere || { echo "Cannot cd somewhere: $!" 1>&2; exit 99; }   

      • python: if not os.chdir(somewhere): sys.exit("Cannot chdir(somewhere)")


  • Use a "lint" finding program. For example,
    • shell: use "shellcheck", which can be installed using "apt install -y shellcheck"
    • python: there are a number lint-finding programs, such as "pylint" and "flakes8".

...