Improper Control of Generation of Code ('Code Injection')
Description
Code Injection is a vulnerability that occurs when software constructs all or part of a code segment using externally-influenced input from an upstream component, but does not neutralize or incorrectly neutralizes special elements that could modify the syntax or behavior of the intended code segment. Unlike command injection which targets operating system shells, code injection targets the programming language interpreter itself (e.g., Python's eval(), PHP's eval(), JavaScript's eval(), or compiled code generation). Successful exploitation allows attackers to execute arbitrary code within the application's context, potentially leading to complete system compromise with the full privileges of the application process.
Risk
Code injection represents one of the most severe vulnerability classes, enabling attackers to execute arbitrary code with application privileges. Modern web applications using server-side scripting languages are particularly vulnerable when they dynamically generate or interpret code from user input. Attackers can steal sensitive data, modify application behavior, establish persistent backdoors, pivot to internal systems, or use the compromised application for further attacks. Template injection in server-side template engines (Jinja2, Twig, Freemarker) is an increasingly common code injection variant. The impact is typically full application compromise, equivalent to remote code execution.
Solution
Never use eval(), exec(), or similar code execution functions with user-supplied input. Redesign application logic to avoid dynamic code generation. If dynamic functionality is required, use safe alternatives: for mathematical expressions use dedicated parser libraries, for template rendering use sandboxed template engines with auto-escaping, for configuration use structured data formats (JSON, YAML) with proper parsing. Implement strict input validation using allowlists. Apply the principle of least privilege to application processes. Deploy runtime application self-protection (RASP) as defense in depth. For template engines, disable dangerous features and ensure auto-escaping is enabled.
Common Consequences
| Impact | Details |
|---|---|
| Confidentiality | Scope: Confidentiality Injected code can access all data available to the application including database contents, configuration files, environment variables, and user data. |
| Integrity | Scope: Integrity Arbitrary code execution enables modification of application logic, data corruption, malware installation, and persistent backdoor creation. |
| Availability | Scope: Availability Attackers can crash applications, consume resources, delete data, or deploy ransomware affecting system availability. |
| Access Control | Scope: Full System Compromise Code injection typically results in complete compromise with ability to perform any action the application process can perform. |
Example Code + Solution Code
Vulnerable Code
from flask import Flask, request
import subprocess
app = Flask(__name__)
@app.route('/calculate')
def calculator():
# VULNERABLE: eval() with user input
# Attack: expression=__import__('os').system('cat /etc/passwd')
expression = request.args.get('expression')
result = eval(expression) # Arbitrary code execution!
return f"Result: {result}"
@app.route('/template')
def render_template():
# VULNERABLE: Template injection (Python f-string abuse)
# Attack: name={self.__init__.__globals__['os'].popen('id').read()}
name = request.args.get('name')
template = f"Hello, {name}!"
return eval(f'f"{template}"')
# VULNERABLE: PHP example
# <?php
# $code = $_GET['code'];
# eval($code); // Direct code execution
# ?>
Fixed Code
from flask import Flask, request, abort, render_template_string
import ast
import operator
app = Flask(__name__)
# Safe mathematical expression evaluator
ALLOWED_OPERATORS = {
ast.Add: operator.add,
ast.Sub: operator.sub,
ast.Mult: operator.mul,
ast.Div: operator.truediv,
ast.Pow: operator.pow,
ast.USub: operator.neg,
}
def safe_eval_math(expression):
"""Safely evaluate mathematical expressions only"""
try:
tree = ast.parse(expression, mode='eval')
except SyntaxError:
raise ValueError("Invalid expression syntax")
def _eval(node):
if isinstance(node, ast.Expression):
return _eval(node.body)
elif isinstance(node, ast.Constant):
if isinstance(node.value, (int, float)):
return node.value
raise ValueError("Only numeric constants allowed")
elif isinstance(node, ast.BinOp):
op_type = type(node.op)
if op_type not in ALLOWED_OPERATORS:
raise ValueError(f"Operator not allowed")
return ALLOWED_OPERATORS[op_type](_eval(node.left), _eval(node.right))
elif isinstance(node, ast.UnaryOp):
if isinstance(node.op, ast.USub):
return -_eval(node.operand)
raise ValueError("Unary operator not allowed")
else:
raise ValueError(f"Expression type not allowed: {type(node)}")
return _eval(tree)
@app.route('/calculate')
def calculator():
expression = request.args.get('expression', '')
# Validate input length
if len(expression) > 100:
abort(400, 'Expression too long')
# Only allow safe characters
if not all(c in '0123456789+-*/().^ ' for c in expression):
abort(400, 'Invalid characters in expression')
try:
result = safe_eval_math(expression)
return f"Result: {result}"
except ValueError as e:
abort(400, str(e))
@app.route('/template')
def render_template():
name = request.args.get('name', 'Guest')
# Validate input
if len(name) > 50:
name = name[:50]
# Use safe template rendering with auto-escaping
# Jinja2's render_template_string with autoescape prevents injection
return render_template_string(
"Hello, {{ name }}!",
name=name
)
Exploited in the Wild
Server-Side Template Injection Attacks (Various, 2015-Present)
Template injection vulnerabilities in popular frameworks (Jinja2, Freemarker, Velocity, Smarty) have been exploited to achieve remote code execution. Notable incidents include RCE in Uber's Jinja2 templates and multiple enterprise applications using Java template engines.
Log4Shell (Apache Log4j, 2021)
CVE-2021-44228 (Log4Shell) demonstrated code injection through JNDI lookup functionality in logging messages. While technically a deserialization/JNDI issue, it enabled code injection through log message formatting, affecting millions of applications worldwide.
Tools to test/exploit
-
Tplmap — automated server-side template injection detection and exploitation tool supporting multiple template engines.
-
Burp Suite — web security testing platform with active scanning for code injection vulnerabilities.
CVE Examples
-
CVE-2021-44228 — Log4j JNDI code injection (Log4Shell) enabling remote code execution.
-
CVE-2022-22965 — Spring Framework code injection (Spring4Shell) through data binding.
-
CVE-2019-11581 — Atlassian Jira template injection enabling server-side code execution.
References
-
MITRE. "CWE-94: Improper Control of Generation of Code." https://cwe.mitre.org/data/definitions/94.html
-
PortSwigger. "Server-side template injection." https://portswigger.net/web-security/server-side-template-injection
-
OWASP. "Code Injection." https://owasp.org/www-community/attacks/Code_Injection