Server-Side Template Injection (SSTI)
CWE-1336OWASP A03:2021Aktualisiert 31. August 20265 Min. Lesezeit
Server-Side Template Injection (SSTI) ist eine Schwachstelle, bei der Angreifer-Eingaben von der Template-Engine des Servers ausgewertet werden, weil die Eingabe in den Vorlagenquelltext eingebaut statt als Daten übergeben wird. Auf Engines wie Jinja2, Twig oder Freemarker führt das meist zu Remote Code Execution. Die Lösung ist, Eingaben als Kontextvariable zu übergeben.
Template-Engines machen aus einer Vorlage und einigen Daten eine fertige Seite, E-Mail oder Konfiguration. Server-Side Template Injection verwandelt diesen Komfort in eine der gefährlichsten Injektionsschwachstellen überhaupt, denn dieselbe Engine, die eine Seite formatiert, kann auch Code ausführen. Im Folgenden erfahren Sie, was dahintersteckt, wie ein Angriff abläuft und wie Sie Benutzereingaben aus der Vorlage selbst heraushalten.
Was ist Server-Side Template Injection?
Server-Side Template Injection, meist zu SSTI abgekürzt, ist eine Schwachstelle, bei der ein Angreifer eigene Vorlagenausdrücke von der Template-Engine des Servers auswerten lässt. Das geschieht, sobald Benutzereingaben in den Quelltext der Vorlage eingefügt werden, statt sie der Vorlage als Daten zu übergeben. Engines wie Jinja2 (Python), Twig (PHP) und Freemarker (Java) sind gerade dafür gebaut, Ausdrücke auszuwerten, daher wird jede Eingabe, die den Quelltext erreicht, als Logik behandelt und nicht als Text.
Ein Vergleich aus dem Alltag: Eine Vorlage ist ein Serienbrief mit Platzhaltern. Normalerweise schreiben Sie den Brief, und nur der Name des Lesers kommt in die Lücke. SSTI ist das, was passiert, wenn Sie den Leser einen Teil des Briefes selbst schreiben lassen: Er kann Anweisungen einfügen, die der Drucker brav ausführt. Die Engine kann Ihre Formulierung nicht von seiner unterscheiden, also wird alles, was er schreibt, Teil des Programms.
Der Fehler liegt nicht in der Engine, sondern darin, die Vorlage aus nicht vertrauenswürdigen Eingaben zusammenzubauen. Genau dieser eine Fehler trennt eine harmlose Begrüßung von einer vollständigen Serverübernahme.
Wie funktioniert ein SSTI-Angriff?
Die Grundursache ist dieselbe wie bei jeder Injektion: Eingabe und Code werden zu einer Zeichenkette zusammengefügt. Ein Begrüßungs-Endpunkt, der die Vorlage aus dem Parameter name aufbaut, sieht so aus.
Verwundbar:
from flask import request
from jinja2 import Template
@app.route("/greet")
def greet():
name = request.args.get("name", "")
# Die Eingabe des Benutzers wird Teil des Vorlagen-QUELLTEXTS
source = "<h1>Hallo " + name + "</h1>"
return Template(source).render()
Bei einem normalen Namen funktioniert das einwandfrei. Doch der Angreifer sendet keinen Namen, sondern einen Vorlagenausdruck. Die klassische Probe multipliziert zwei Zahlen innerhalb der Ausdruckszeichen von Jinja2:
GET /greet?name={{7*7}} HTTP/1.1
Host: example.com
Liest die Antwort “Hallo 49”, statt die Payload wörtlich zurückzugeben, wurde die Eingabe ausgewertet, und der Endpunkt ist injizierbar. Von diesem Brückenkopf aus wandert ein Angreifer über die Objekte, die die Engine offenlegt, bis er das os-Modul von Python erreicht, und führt dann Befehle aus:
GET /greet?name={{cycler.__init__.__globals__.os.popen('id').read()}} HTTP/1.1
Host: example.com
Die Antwort enthält nun die Ausgabe von id, und das bedeutet die Ausführung beliebiger Befehle auf dem Server. Twig und Freemarker haben eine andere Syntax (Twig nutzt dieselben doppelten geschweiften Klammern, Freemarker einen Ausdruck mit Dollarzeichen), doch die Eskalation verläuft gleich: ein Laufzeitobjekt erreichen und von dort einen Systemaufruf.
Die Lösung besteht darin, Benutzereingaben vollständig aus dem Vorlagenquelltext herauszuhalten. Laden Sie die Vorlage aus einer Datei oder einer festen Zeichenkette und übergeben Sie die Eingabe als Kontextvariable. Die Engine behandelt sie dann als Daten zum Ausgeben, niemals als Logik zum Ausführen.
Sicher:
from flask import request
from jinja2 import Environment, FileSystemLoader
env = Environment(
loader=FileSystemLoader("templates"),
autoescape=True,
)
@app.route("/greet")
def greet():
name = request.args.get("name", "")
# Die Eingabe kommt als Daten mit, die Vorlage steht fest
template = env.get_template("greet.html")
return template.render(name=name)
Mit einer festen Vorlage greet.html, die nur die Variable name ausgibt, wird dieselbe Payload jetzt wörtlich als Text angezeigt. Die Ausdruckszeichen wurden einmalig aus einer Datei kompiliert, die Sie kontrollieren; die geschweiften Klammern des Angreifers kommen zu spät, um noch als Ausdruck gelesen zu werden.
Welche Auswirkungen hat SSTI?
Die Auswirkung reicht von Informationsabfluss bis zur vollständigen Remote Code Execution, weshalb der Schweregrad zwischen hoch und kritisch liegt. Auf Engines mit einer reichhaltigen Laufzeit wie Jinja2 oder Freemarker erreicht eine funktionierende Payload meist Betriebssystembefehle, sodass der Angreifer Dateien lesen, Geheimnisse und Umgebungsvariablen abgreifen, ins interne Netz vordringen oder eine dauerhafte Hintertür einrichten kann. Das ist eine komplette Serverübernahme aus einer einzigen Anfrage.
Selbst wo die Engine stärker eingeschränkt ist, kann ein Angreifer oft beliebige Anwendungsdaten auslesen, etwa Vorlagen-Globals, Konfiguration und Verbindungszeichenketten, oder durch das Auswerten eines aufwendigen Ausdrucks einen Denial of Service auslösen. Weil die Payload über einen gewöhnlichen Parameter hereinkommt und die Antwort normal aussehen kann, ist der Einbruch in den Protokollen leicht zu übersehen. In der Praxis verdient eine SSTI an einem öffentlichen Endpunkt die Behandlung als kritischer Befund, für den Sie alles stehen und liegen lassen.
Wie erkennen Sie SSTI?
Der übliche erste Test ist eine Rechen-Probe innerhalb der Ausdruckszeichen der Engine, gesendet an jedes Feld, das in einer Vorlage landen könnte: ein URL-Parameter, ein Formularwert, ein Profilfeld, ein E-Mail-Betreff. Kommt ein Wert, der eine Rechnung auswertet, berechnet zurück statt wörtlich, dann erreicht die Eingabe die Engine. Da jede Engine ihre eigene Syntax hat, verwenden Tester eine kleine Reihe von Proben, um zunächst zu bestimmen, welche Engine läuft, bevor sie eskalieren.
Scanner wie Burp Suite und vorlagenspezifische Werkzeuge wie tplmap finden die offensichtlichen, direkt gespiegelten Fälle, doch SSTI versteckt sich oft in Sinks zweiter Ordnung: ein Wert, der jetzt gespeichert und erst später in einem Bericht, einer Rechnung oder einer Benachrichtigungs-E-Mail dargestellt wird. Diesen Pfad nachzuverfolgen erfordert Handarbeit und ist fester Bestandteil eines Penetrationstests von AssistSec, bei dem wir feststellen, ob eine Probe die Engine wirklich erreicht, und mit Genehmigung die tatsächliche Auswirkung nachweisen.
Wie verhindern Sie SSTI?
- Bauen Sie Vorlagenquelltext niemals aus Benutzereingaben. Laden Sie Vorlagen ausschließlich aus Dateien oder festen Zeichenketten; das beseitigt die Schwachstelle an der Wurzel.
- Übergeben Sie Benutzereingaben als Kontextvariablen, damit die Engine sie als Daten darstellt, statt sie als Logik auszuwerten.
- Bevorzugen Sie eine logiklose Engine wie Mustache oder Handlebars, wo es der Anwendungsfall erlaubt, damit eine Vorlage überhaupt keine Laufzeitlogik ausdrücken kann.
- Aktivieren Sie den Sandbox- oder eingeschränkten Modus der Engine als zusätzliche Schicht und halten Sie ihn gepatcht, verlassen Sie sich aber nicht als einzige Maßnahme darauf.
- Trennen Sie Content-Autoren von Vorlagen. Müssen Benutzer Formatierung liefern, verwenden Sie eine schmale, per Positivliste erlaubte Auszeichnungssprache wie Markdown, niemals eine vollständige Vorlagensprache.
- Betreiben Sie den Renderer mit minimalen Rechten, in einem Container ohne Shell und mit minimalem Netzzugriff, damit eine erfolgreiche Payload so wenig wie möglich erreicht.
- Lassen Sie den Code regelmäßig testen. Ein gezielter Penetrationstest und ein Code-Review fangen die injizierbaren Sinks ab, die Scanner überspringen.
Quellen
Häufige Fragen
Ist SSTI dasselbe wie Cross-Site-Scripting?
Nein. XSS läuft im Browser des Opfers, während SSTI auf dem Server innerhalb der Template-Engine ausgeführt wird. SSTI ist meist deutlich schwerwiegender, weil es oft direkt zur Remote Code Execution führt. Eine Payload, die nur HTML einschleust, ist XSS; eine, die als Vorlagenlogik ausgewertet wird, ist SSTI.
Welche Template-Engines sind von SSTI betroffen?
Jede Engine, die Ausdrücke auswertet, kann betroffen sein, darunter Jinja2, Twig, Freemarker, Velocity und Thymeleaf. Das Risiko ist bei Engines mit reichhaltiger Laufzeit am größten, wo die Eskalation zur Befehlsausführung einfach ist. Logiklose Engines wie Mustache verringern das Risiko erheblich.
Verhindert das Escapen der Ausgabe SSTI?
Nein. Output-Escaping verhindert Cross-Site-Scripting, doch SSTI wird während der Auswertung der Vorlage ausgeführt, noch bevor die Ausgabe escaped wird. Die einzige verlässliche Lösung ist, Benutzereingaben aus dem Vorlagenquelltext herauszuhalten und als Kontextvariable zu übergeben.
Wie teste ich schnell auf SSTI?
Senden Sie einen einfachen Rechenausdruck in den Trennzeichen der Engine an jedes Feld, das eine Vorlage erreichen könnte. Kommt das berechnete Ergebnis statt des wörtlichen Texts zurück, wird die Eingabe ausgewertet. Bestimmen Sie zuerst die Engine, bevor Sie eskalieren, und testen Sie nur Systeme, für die Sie eine Genehmigung haben.
Verwandte Artikel
- SchwachstellenCWE-78A03:2021OS Command InjectionOS Command Injection erklärt: wie Shell-Sonderzeichen in einen Systemaufruf gelangen, was ein Angreifer erreicht und wie Argumentlisten das verhindern.
- SchwachstellenCWE-79A03:2021Cross-Site-Scripting (XSS)Cross-Site-Scripting (XSS) schleust schädliche Skripte in Webseiten ein, die im Browser der Besucher laufen. So funktioniert XSS und so verhindern Sie es.
- SchwachstellenCWE-94A03:2021Remote Code Execution (RCE)Remote Code Execution (RCE) erklärt: wie Angreifer über ungefilterte Eingaben eigene Befehle oder Code auf Ihrem Server ausführen und wie Sie es verhindern.
- SchwachstellenCWE-89A03:2021SQL InjectionSQL Injection erklärt: wie Angreifer über ungefilterte Eingaben Ihre Datenbank auslesen oder verändern und wie Sie es mit Prepared Statements verhindern.
- SchwachstellenCWE-918A10:2021Server-Side Request Forgery (SSRF)Server-Side Request Forgery (SSRF): Wie Angreifer Ihren Server missbrauchen, um interne Systeme und Cloud-Dienste zu erreichen, und wie Sie es verhindern.