Unsachgemäße Neutralisierung von Direktiven in dynamisch ausgewertetem Code ('Eval Injection')
Beschreibung
Eval Injection ist eine spezifische Variante der Code-Injection, die auftritt, wenn Software Eingaben von einer vorgelagerten Komponente erhält und diese als Code mit Funktionen wie eval(), exec(), Function() oder äquivalenten Konstrukten auswertet, ohne Code-Direktiven ordnungsgemäß zu neutralisieren. Die Schwachstelle existiert in vielen Programmiersprachen: Pythons eval()/exec(), PHPs eval(), JavaScripts eval()/Function(), Rubys eval() und Perls eval(). Wenn benutzerkontrollierte Daten diese Funktionen erreichen, können Angreifer beliebigen Code im Kontext des Interpreters ausführen und erhalten vollen Zugriff auf die Fähigkeiten der Anwendung und können potenziell das zugrundeliegende System kompromittieren.
Risiko
Eval-Injection bietet Angreifern direkte Code-Ausführungsfähigkeiten und stellt ein kritisches Sicherheitsrisiko dar. Da ausgewerteter Code mit denselben Privilegien wie die Anwendung läuft, können Angreifer auf sensible Daten zugreifen, Anwendungsverhalten modifizieren, Dateien lesen und schreiben, Netzwerkverbindungen herstellen und potenziell Systembefehle ausführen. In Webanwendungen führt dies typischerweise zu vollständiger Server-Kompromittierung. JavaScript-Eval-Injection in clientseitigem Code kann zu XSS-Angriffen führen, während serverseitige Eval-Injection in Node.js-Anwendungen Remote Code Execution ermöglicht. Die Schwachstelle ist besonders heimtückisch, weil Entwickler manchmal eval für scheinbar harmlose Zwecke wie dynamische Konfiguration oder mathematische Berechnungen verwenden, ohne die Sicherheitsimplikationen zu realisieren.
Lösung
Eliminieren Sie die Verwendung von eval() und ähnlichen Funktionen vollständig. Für mathematische Ausdrücke verwenden Sie dedizierte sichere Expression-Parser (z.B. ast.literal_eval() in Python für Literale oder spezialisierte Mathe-Parsing-Bibliotheken). Für JSON-Parsing verwenden Sie native JSON-Parser (JSON.parse(), json.loads()). Für dynamische Funktionalität verwenden Sie sichere Alternativen wie Lookup-Tabellen, Factory-Patterns oder Konfigurationsdateien. Wenn eval nicht vermieden werden kann, implementieren Sie strikte Allowlist-Validierung, die nur bekannt sichere Werte erlaubt. Erwägen Sie die Verwendung von sandboxed Ausführungsumgebungen für wirklich dynamische Code-Anforderungen. In JavaScript vermeiden Sie eval(), Function(), setTimeout() mit Strings und setInterval() mit Strings.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Vertraulichkeit | Bereich: Vertraulichkeit Beliebige Code-Ausführung ermöglicht Zugriff auf alle Anwendungsdaten, Umgebungsvariablen, Dateisysteminhalte und Netzwerkressourcen. |
| Integrität | Bereich: Integrität Angreifer können Daten modifizieren, Anwendungslogik ändern, Backdoors einschleusen und Systemzustand durch ausgeführten Code manipulieren. |
| Verfügbarkeit | Bereich: Verfügbarkeit Bösartiger Code kann Anwendungen zum Absturz bringen, Ressourcen verbrauchen, Dateien löschen oder Systeme unbrauchbar machen. |
| Zugriffskontrolle | Bereich: Vollständige Kompromittierung Eval-Injection führt typischerweise zu vollständiger Anwendungskompromittierung mit allen Privilegien des laufenden Prozesses. |
Beispielcode + Lösungscode
Anfälliger Code
// ANFÄLLIG: JavaScript eval() mit Benutzereingabe
app.get('/calc', (req, res) => {
const expression = req.query.expr;
// Angriff: expr=require('child_process').execSync('cat /etc/passwd')
const result = eval(expression);
res.send(`Ergebnis: ${result}`);
});
// ANFÄLLIG: Function-Konstruktor
const userFunc = req.query.func;
const dynamicFunc = new Function(userFunc); // Entspricht eval
dynamicFunc();
// ANFÄLLIG: setTimeout mit String
setTimeout("alert(" + userInput + ")", 1000);
# ANFÄLLIG: Python eval()
user_input = request.args.get('calc')
# Angriff: __import__('os').system('id')
result = eval(user_input)
# ANFÄLLIG: exec()
code = request.form.get('code')
exec(code) # Beliebige Code-Ausführung
Korrigierter Code
// SICHER: Mathe-Expression-Parser anstelle von eval verwenden
const mathjs = require('mathjs');
app.get('/calc', (req, res) => {
const expression = req.query.expr || '';
// Erlaubte Zeichen validieren
if (!/^[\d\s+\-*/().]+$/.test(expression)) {
return res.status(400).send('Ungültiger Ausdruck');
}
try {
// mathjs parst mathematische Ausdrücke sicher
const result = mathjs.evaluate(expression);
res.send(`Ergebnis: ${result}`);
} catch (e) {
res.status(400).send('Ungültiger Ausdruck');
}
});
// SICHER: Lookup-Tabellen anstelle von dynamischer Funktionserstellung verwenden
const allowedOperations = {
'add': (a, b) => a + b,
'subtract': (a, b) => a - b,
'multiply': (a, b) => a * b,
'divide': (a, b) => b !== 0 ? a / b : null
};
app.get('/operation', (req, res) => {
const op = req.query.op;
const a = parseFloat(req.query.a);
const b = parseFloat(req.query.b);
if (!(op in allowedOperations) || isNaN(a) || isNaN(b)) {
return res.status(400).send('Ungültige Parameter');
}
const result = allowedOperations[op](a, b);
res.send(`Ergebnis: ${result}`);
});
# SICHER: ast.literal_eval für sichere Literal-Auswertung verwenden
import ast
def safe_literal_eval(expression):
"""Wertet nur Python-Literale aus (Strings, Zahlen, Tupel, Listen, Dicts)"""
try:
return ast.literal_eval(expression)
except (ValueError, SyntaxError):
raise ValueError("Ungültiger Literal-Ausdruck")
# Für Mathe-Ausdrücke sicheren Parser verwenden
def safe_math_eval(expression):
allowed_chars = set('0123456789+-*/().e ')
if not all(c in allowed_chars for c in expression):
raise ValueError("Ungültige Zeichen")
# AST parsen und nur sichere Operationen erlauben
tree = ast.parse(expression, mode='eval')
# ... sichere Auswertung implementieren wie im CWE-94 Beispiel
Ausgenutzt in der Praxis
Serverseitige JavaScript-Injection (Node.js-Anwendungen, fortlaufend)
Eval-Injection-Schwachstellen in Node.js-Anwendungen wurden ausgenutzt, um Remote Code Execution auf Serversystemen zu erreichen. Taschenrechner-Widgets, Expression-Evaluatoren und dynamische Konfigurations-Handler sind häufige Angriffsvektoren.
MongoDB NoSQL-Injection via $where (Datenbankanwendungen, fortlaufend)
MongoDBs $where-Operator erlaubt JavaScript-Ausführung in Abfragen, was in Kombination mit Benutzereingaben eval-artige Injection-Angriffe gegen Datenbanksysteme ermöglicht.
Tools zum Testen/Ausnutzen
-
Burp Suite — Web-Sicherheitstestplattform mit Fähigkeiten zur Erkennung von Eval-Injection-Schwachstellen.
-
NoSQLMap — Automatisiertes Testtool für NoSQL-Injection einschließlich JavaScript-Eval-Injection.
CVE-Beispiele
-
CVE-2023-26136 — tough-cookie Eval-Injection durch Prototype Pollution.
-
CVE-2022-21824 — Node.js Prototype Pollution ermöglicht Eval-Injection.
Referenzen
-
MITRE. "CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code." https://cwe.mitre.org/data/definitions/95.html
-
OWASP. "Code Injection." https://owasp.org/www-community/attacks/Code_Injection