# PYTHON-LANG-SEC-014: Python Reverse Shell Pattern Detected

> **Severity:** CRITICAL | **CWE:** CWE-506 | **OWASP:** A03:2021

- **Language:** Python
- **Category:** Python Core
- **URL:** https://codepathfinder.dev/registry/python/lang/PYTHON-LANG-SEC-014
- **Detection:** `pathfinder scan --ruleset python/PYTHON-LANG-SEC-014 --project .`

## Description

A reverse shell is a type of backdoor in which the compromised host initiates an outbound
network connection to an attacker-controlled server and then redirects its stdin, stdout,
and stderr over that connection, giving the attacker an interactive shell session on the host.

Common Python reverse shell patterns include creating a socket connection to a remote IP
and port, then either passing the socket file descriptor to subprocess (subprocess.call(["/bin/sh", "-i"]),
or duplicating the file descriptor over stdin/stdout/stderr using os.dup2(), or executing
the socket through exec()/eval() with __builtins__ access.

Finding this pattern in production code is a critical security incident indicator. It may
represent active compromise of the codebase, a supply chain attack through a dependency,
a malicious insider contribution, or a legitimate security testing tool that was accidentally
included in production code.


## Vulnerable Code

```python
import os
import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
```

## Secure Code

```python
# There is no legitimate use of reverse shell code in production application code.
# If network connectivity testing is required, use purpose-built tools:

import socket
import ssl

# SECURE: Legitimate network connectivity check using a controlled connection
def check_service_connectivity(host: str, port: int, timeout: int = 5) -> bool:
    """
    Test TCP connectivity to a known, trusted service endpoint.
    This is NOT a reverse shell: it connects, checks, and disconnects.
    """
    try:
        with socket.create_connection((host, port), timeout=timeout) as sock:
            return True
    except (socket.timeout, ConnectionRefusedError, OSError):
        return False

# For security testing environments, use dedicated penetration testing
# frameworks in isolated, authorized test environments — never in production code.

```

## Detection Rule (Python SDK)

```python
from rules.python_decorators import python_rule
from codepathfinder import calls, flows, QueryType
from codepathfinder.presets import PropagationPresets

class SocketModule(QueryType):
    fqns = ["socket"]


@python_rule(
    id="PYTHON-LANG-SEC-014",
    name="Python Reverse Shell Detected",
    severity="CRITICAL",
    category="lang",
    cwe="CWE-506",
    tags="python,reverse-shell,backdoor,CWE-506",
    message="Reverse shell pattern detected. This may be a backdoor.",
    owasp="A03:2021",
)
def detect_reverse_shell():
    """Detects socket-based reverse shell patterns."""
    return SocketModule.method("socket")
```

## How to Fix

- Immediately quarantine and investigate any codebase containing a reverse shell pattern; treat it as an active security incident.
- Audit git history and dependency lockfiles to determine when the reverse shell code was introduced and trace the source.
- Scan all deployed instances for active outbound connections to unexpected IP addresses and ports.
- Implement code review policies that flag any use of socket combined with subprocess or os.dup2() for review by the security team.
- Use software composition analysis (SCA) tools to scan third-party dependencies for malicious code patterns before installation.

## Security Implications

- **Complete Host Compromise:** A reverse shell gives the attacker an interactive command line on the host with the
privileges of the Python process. All data, credentials, certificates, and capabilities
of the process are immediately accessible to the attacker.

- **Persistent Access:** Unlike a one-shot command injection, a reverse shell provides an ongoing interactive
session. The attacker can install additional backdoors, lateral movement tools, and
persistence mechanisms during the session.

- **Firewall Bypass via Outbound Connection:** Reverse shells initiate outbound connections from the compromised host to the attacker.
Most network perimeters allow outbound connections, so this technique bypasses inbound
firewall rules that would block a traditional bind shell.

- **Supply Chain Compromise Indicator:** Reverse shell code found in a third-party dependency or unexpected location in the
codebase may indicate a supply chain attack. This requires forensic analysis to determine
when and how the code was introduced and which systems may have executed it.


## FAQ

**Q: Is there any legitimate use of reverse shell code in production applications?**

Almost never. Reverse shell patterns combining socket connections with stdin/stdout
redirection to a subprocess have no legitimate use in production web services, APIs,
data processing pipelines, or any normal application. If found in production code,
treat it as a security incident until proven otherwise through forensic analysis.


**Q: Could this be a false positive from a legitimate network library?**

Legitimate network libraries do not combine socket file descriptor duplication with
subprocess stdin/stdout redirection. The specific combination of socket.connect(),
os.dup2(), and subprocess/exec that characterizes a reverse shell is not present in
well-known libraries. Investigate any flagged code regardless of its apparent context.


**Q: What should I do immediately when this rule fires?**

First, do not dismiss or suppress the finding. Quarantine the affected codebase,
notify your security incident response team, audit git history for unauthorized commits,
check running processes for active outbound connections, and rotate all credentials
the compromised process had access to. Treat it as a potential breach until investigation
concludes otherwise.


**Q: How could reverse shell code end up in a Python project?**

Common paths include: malicious commits from compromised developer accounts, supply
chain attacks through third-party packages (typosquatting, dependency confusion,
compromised maintainer accounts), malicious pull requests that slipped through code
review, and attackers who achieved code execution and wrote a persistence mechanism.


**Q: What forensic steps should I take after finding this pattern?**

Preserve logs and process state before taking remediation actions. Check outbound
network connections for the time period since the code was deployed. Review git blame
and commit signatures. Check package integrity hashes against known-good versions.
Rotate all secrets that were accessible to the compromised process.


**Q: Should this rule fire in test/security research code?**

Security research and penetration testing code may contain reverse shell implementations,
but this code should never be in the same repository as production application code.
Maintain strict separation between security tooling and application code, and ensure
security tools are never deployed to production environments.


## References

- [CWE-506: Embedded Malicious Code](https://cwe.mitre.org/data/definitions/506.html)
- [OWASP Top 10 A03:2021 Injection](https://owasp.org/Top10/A03_2021-Injection/)
- [NIST SP 800-53 SI-3: Malicious Code Protection](https://csrc.nist.gov/publications/detail/sp/800-53/rev-5/final)
- [Python Reverse Shell Techniques Reference](https://www.revshells.com/)
- [OWASP Software Component Verification Standard](https://owasp.org/www-project-software-component-verification-standard/)

---

Source: https://codepathfinder.dev/registry/python/lang/PYTHON-LANG-SEC-014
Code Pathfinder — Open source, type-aware SAST with cross-file dataflow analysis
