Skip to content

Commit

Permalink
Moving CWE-426 from confluence for ossf#531
Browse files Browse the repository at this point in the history
Signed-off-by: emcdtho <[email protected]>
  • Loading branch information
tommcd committed Jul 29, 2024
1 parent 6fd7d30 commit 4e201bf
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 3 deletions.
94 changes: 94 additions & 0 deletions docs/Secure-Coding-Guide-for-Python/CWE-664/CWE-426/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# CWE-426: Untrusted Search Path

In an environment where an untrusted or less trusted entity can modify the environment variables, consider validating hash-based byte code [Python 2023 Command line and environment].

Python source code `.py` files need to be converted into "byte code" `.pyc` or `.pyo` in memory or in a filesystem `__pycache__` before running on the Python Virtual Machine (PVM) [Dec 2009 PEP 3147].
Python 3.8 [Dec 2009 PEP 3147] also has a backward compatibility mode supporting delivering only byte code.

Python 3.8 introduced the option to customize the `__pychache__` folder via `-X pycache_prefix=PATH`, or the `PYTHONPYCACHEPREFIX` environment variable. An attacker may manipulate the `PYTHONPYCACHEPREFIX` or `PYTHONPATH` to inject their code that can go unnoticed without hash-based verification. Without `--check-hash-based-pycs` Python only compares the byte code against the source code via time-stamp [Python 2023 The import system] potentially allowing an attack.

Python 2.6 also introduced the ability to stop Python from writing "byte code" files via `-B` flag or `PYTHONDONTWRITEBYTECODE=1` environment variable is another possibility that does not guarantee full protection.

Byte code files contain a 32-bit 'magic number' to identify the byte code format to find out if the PVM matches. Byte code also uses a naming convention to match up the CPython interpreter down to its minor version such as `sessions.cpython-39.pyc` for the sessions module complied with CPython 3.9.

## Non-Compliant Code Example

Setting the `--check-hash-based-pycs` to default or never skips integrity verification of the byte code against its source code and only compares timestamp and size.

*[noncompliant01.bash](noncompliant01.bash):*

```bash
# Non-compliant Code Example
python3 -m http.server -b 127.0.0.42 8080
```

*[example01.bash](example01.bash)*

```bash
cd
CWD=$(pwd)
mkdir -p temp/http
touch temp/http/__init__.py
echo "print('hello there')" > temp/http/server.py
export PYTHONPATH=$CWD/temp/

# and now launch again
python3 -m http.server -b 127.0.0.42 8080
```

The http.server module is now launched from the `PYTHONPATH` and only printing "hello there" instead of launching the webserver.

## Compliant Solution

Most Python interpreters have `--check-hash-based-pycs` set to default and are skipping integrity validation of byte code against their source code files. Using `--check-hash-based-pycs` always enforces hash-based integrity verification of byte code files against their source code files. A user custom `PYTHONPATH` is suppressed with the `-I` isolation flag.

*[compliant01.bash](compliant01.bash):*

```bash
# Compliant Code Example
python3 -I --check-hash-based-pycs always -m http.server -b 127.0.0.42 8080
```

## Exceptions

**ENV-4P-EX0:** Untrusted entities are not able to change environmental variables or any Python files.

## Risk Assessment

An attacker with access to the environment and filesystem can allow full control over what a Python script can run.

| Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
|:---------|:---------|:-----------|:-----------------|:---------|:------|
| ENV04-P3 | High | Likely | Low | P27 | L1 |

## Automated Detection

Currently None.

## Related Vulnerabilities

| Component | CVE | Description | CVSS rating | Comment |
|:----------|:----|:-------------|:------------|:--------|
| python-dbusmock <=0.15.1 | [CVE-2015-1326](https://nvd.nist.gov/vuln/detail/CVE-2015-1326) | AddTemplate() D-Bus method call or DBusTestCase.spawn_server_template() method could be tricked into executing malicious code if an attacker supplies a .pyc file. | 3.x: 8.8 High | |
| catfish <= 0.6 | [CVE-2014-2095](https://nvd.nist.gov/vuln/detail/CVE-2014-2095) | Fedora package such as 0.8.2-1 is not used, allowing local users to gain privileges via a Trojan horse bin/catfish.pyc under the current working directory. | 2.0: 4.6 Med | |
| catfish <= 0.4.0.3 | [CVE-2014-2094](https://nvd.nist.gov/vuln/detail/CVE-2014-2094) | Local users can gain privileges via a Trojan horse catfish.pyc in the current working directory. | 2.0: 4.6 Med | |

## Related Guidelines

|||
|:---|:---|
|[SEI CERT JAVA](https://wiki.sei.cmu.edu/confluence/display/java/SEI+CERT+Oracle+Coding+Standard+for+Java)|[ENV04-J. Do not disable bytecode verification - SEI CERT Oracle Coding Standard for Java - Confluence (cmu.edu)](https://wiki.sei.cmu.edu/confluence/display/java/ENV04-J.+Do+not+disable+bytecode+verification)|
| [SEI CERT C Coding Standard](https://wiki.sei.cmu.edu/confluence/display/c/SEI+CERT+C+Coding+Standard) | [STR02-C. Sanitize data passed to complex subsystems](https://wiki.sei.cmu.edu/confluence/display/c/STR02-C.+Sanitize+data+passed+to+complex+subsystems) |
| [SEI CERT C++ Coding Standard](https://wiki.sei.cmu.edu/confluence/pages/viewpage.action?pageId=88046682) | [VOID STR02-CPP. Sanitize data passed to complex subsystems](https://wiki.sei.cmu.edu/confluence/pages/viewpage.action?pageId=88046726) |
| [SEI CERT Perl Coding Standard](https://wiki.sei.cmu.edu/confluence/display/perl/SEI+CERT+Perl+Coding+Standard) | [IDS33-PL. Sanitize untrusted data passed across a trust boundary](https://wiki.sei.cmu.edu/confluence/display/perl/IDS33-PL.+Sanitize+untrusted+data+passed+across+a+trust+boundary) |
| MITRE | Pillar: [CWE-664: Improper Control of a Resource Through its Lifetime](https://cwe.mitre.org/data/definitions/664.html)<br>Base: [CWE-426: Untrusted Search Path](https://cwe.mitre.org/data/definitions/426.html)|
|[OWASP 2005](https://wiki.sei.cmu.edu/confluence/display/java/Rule+AA.+References#RuleAA.References-OWASP05)|[A Guide to Building Secure Web Applications and Web Services](http://sourceforge.net/projects/owasp/files/Guide/2.0.1/OWASPGuide2.0.1.pdf/download) |

## Biblography

|||
|:---|:---|
|Dec 2009 PEP 3147|[PEP 3147 – PYC Repository Directories \| peps.python.org](https://peps.python.org/pep-3147/)|
|[Python 2023 Command line and environment](https://docs.python.org/3.9/using/cmdline.html#cmdoption-check-hash-based-pycs)|<https://docs.python.org/3.9/using/cmdline.html#cmdoption-check-hash-based-pycs>|
|[Python 2023 The import system](https://docs.python.org/3.9/reference/import.html#pyc-invalidation)|<https://docs.python.org/3.9/reference/import.html#pyc-invalidation>|
|CPython 2023|<https://github.com/python/cpython/blob/main/Lib/importlib/_bootstrap_external.py>|
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: OpenSSF project contributors
# SPDX-License-Identifier: MIT
""" Compliant Code Example """
# Compliant Code Example
python3 -I --check-hash-based-pycs always -m http.server -b 127.0.0.42 8080
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ mkdir -p temp/http
touch temp/http/__init__.py
echo "print('hello there')" > temp/http/server.py
export PYTHONPATH=$CWD/temp/

# and now launch again
python3 -m http.server -b 127.0.0.42 8080
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: OpenSSF project contributors
# SPDX-License-Identifier: MIT
""" Non-compliant Code Example """
# Non-compliant Code Example
python3 -m http.server -b 127.0.0.42 8080

0 comments on commit 4e201bf

Please sign in to comment.