flawopen.com/Vulnerabilities/Server-Side Template Injection (SSTI)
Server-Side Template Injection (SSTI): Ursache und Schutz
Stellen Sie sich ein Versandunternehmen vor, das Briefe mit der Vorlage „Hallo, {{ name }}“ druckt. Sicher ist: Der Drucker erhält die feste Vorlage und den Kundennamen als Daten. Unsicher ist: Der Kundentext wird vor dem Druck in die Vorlagenanweisungen eingefügt. Interpretiert die Template-Engine diesen Text als Template-Syntax, liegt Server-Side Template Injection vor. Die möglichen Folgen hängen von Engine, Konfiguration, verfügbaren Objekten und Prozessrechten ab; die Auswertung eines Ausdrucks bedeutet nicht automatisch, dass Systembefehle ausgeführt werden.
Grundbegriffe und Subsystem-Terminologie
- Template-Engine
- Serverkomponente wie Jinja oder Twig, die Template-Syntax parst und aus Vorlage und Kontextdaten eine Ausgabe erzeugt.
- Template-Quelltext-Injection
- Fehler, bei dem externer Text vor dem Parsen in den Quelltext eingefügt und deshalb als Template-Syntax statt als Daten interpretiert wird.
- Kontextdaten
- Werte, die getrennt an ein festes, vertrauenswürdiges Template übergeben werden. Diese Trennung verhindert, dass ein Wert wie
{{ 7 * 7 }}erneut als Quelltext geparst wird. - CWE-1336
- Unzureichende Neutralisierung spezieller Elemente in einer Template-Engine. Beschreibt die unsichere Verarbeitung externer Eingaben als Template-Syntax.
Schrittweiser Angriffsablauf
Angreiferkontrollierte Eingabe erreicht einen Template-Sink
Ein Formularfeld, gespeicherter Profilwert oder anderer extern beeinflusster Text erreicht Code, der ein Template erstellt oder kompiliert. Verwundbar ist die Quelltexterstellung, nicht das bloße Rendern eines Werts.
Die Anwendung vermischt Daten und Template-Anweisungen
Die Anwendung interpoliert den nicht vertrauenswürdigen Text in den Template-Quelltext (etwa als f-String für render_template_string), statt eine statische Vorlage mit separatem Kontextwert zu verwenden.
Die Engine parst den kombinierten Quelltext
Die Engine interpretiert Ausdrücke gemäß ihrer Sprache und Konfiguration. Ein harmloser Rechenausdruck kann die Auswertung zeigen; er beweist allein keinen Zugriff auf Dateien, Geheimnisse oder Systembefehle.
Die Auswirkung hängt von Engine und Bereitstellung ab
Weitere Folgen hängen von zugänglichen Objekten und Funktionen, Sandbox-Verhalten, Engine-Beschränkungen und den Rechten des Webprozesses ab. RCE ist in manchen Konfigurationen möglich, aber keine automatische Folge jeder SSTI.
Mechanismus und Ursache
SSTI entsteht, wenn extern beeinflusster Text vor dem Parsen Teil des Template-Programms wird. Bei Flask/Jinja besteht das verwundbare Muster darin, aus Request-Daten neuen Quelltext zu erzeugen und an render_template_string() zu übergeben. HTML-Escaping schützt die Ausgabe und macht nicht vertrauenswürdigen Template-Quelltext nicht zu Daten. Die Abhilfe lädt eine feste Vorlage und übergibt den Wert separat als Kontext. Wenn Nutzer Templates erstellen dürfen, stellen Sie nur ein minimales Datenmodell bereit und rendern Sie in einem isolierten Worker mit Ressourcenlimits. Eine Sandbox ist zusätzliche Verteidigung, kein Grund, Geheimnisse oder mächtige Anwendungsobjekte offenzulegen.
# VULNERABLE: request data becomes template source before parsing.
from flask import Flask, request, render_template_string
app = Flask(__name__)
@app.route("/greet")
def greet():
name = request.args.get("name", "Guest")
# A value such as {{ 7 * 7 }} is interpreted by the template engine.
source = f"<h1>Welcome, {name}!</h1>"
return render_template_string(source)
# HARDENED: fixed template source; request data stays a context value.
from flask import Flask, request, render_template
app = Flask(__name__)
@app.route("/greet")
def greet():
name = request.args.get("name", "Guest")
return render_template("greet.html", name=name)
# templates/greet.html is trusted, static source:
# <h1>Welcome, {{ name }}!</h1>
Angriffssequenz und konzeptionelles Beispiel
- 1Quelle: Ein extern beeinflusster Wert erreicht einen Pfad, der Templates erstellt.
- 2Unsichere Zusammensetzung: Die Anwendung setzt den Wert in den Quelltext ein, statt ihn separat als Kontextdaten zu übergeben.
- 3Interpretation: Die Engine parst den kombinierten Quelltext. In einem autorisierten Test kann ein harmloser Rechenausdruck die Auswertung bestätigen.
- 4Bedingte Auswirkung: Weitere Zugriffe hängen von Engine, exponierten Objekten, Konfiguration und Prozessrechten ab; aus der Auswertung allein folgt keine RCE.
Technische Regeln für Prävention und Schutz
- ✓Quelltext statisch halten: Vertrauenswürdige Templates aus Dateien oder einem kontrollierten Loader laden; Benutzereingaben nur als Kontextwerte übergeben. Request-Daten nicht in den Quelltext konkatenieren.
- ✓SSTI von HTML-Injection unterscheiden: HTML-Escaping schützt Ausgabekontexte; es behebt keinen Ablauf, bei dem nicht vertrauenswürdige Eingaben als Template-Quelltext geparst werden.
- ✓Nutzer-Templates begrenzen: Falls nötig, die Sandbox der Engine für diesen Zweck einsetzen, nur ein minimales Datenmodell bereitstellen und in einem isolierten Worker mit Ressourcenlimits rendern. Sicherheitshinweise der Engine beachten.
- ✓Auswirkungen begrenzen: Den Renderer ohne Root-Rechte und mit minimalem Datei-, Netzwerk- und Geheimniszugriff betreiben. Das begrenzt den Schaden, ist aber nicht die primäre Korrektur.
- ✓Regressionstests ergänzen: Eine harmlose Markierung wie
{{ 7 * 7 }}als Daten übergeben und prüfen, dass sie Daten bleibt; außerdem sicherstellen, dass Vorlagen ausschließlich aus dem vertrauenswürdigen Loader stammen.