FlawOpen

flawopen.com/SSTI/FreeMarker und Velocity

Sind FreeMarker- und Velocity-Vorlagen mit Benutzereingaben sicher?

CWE-1336: Server-Side Template InjectionReferenzseite
Kurzantwort

Benutzerwerte bleiben Daten, wenn sie in eine vertrauenswürdige Vorlage eingesetzt werden. Vom Benutzer kontrollierter Vorlagencode ist etwas anderes: Er erlaubt Ausdrücke in der Vorlagensprache. Die erreichbaren Fähigkeiten hängen von Version, Wrapper oder Uberspector, Modellobjekten und Anwendungsrechten ab. Gehen Sie nicht davon aus, dass jede Template Injection Betriebssystembefehle ausführt. Behandeln Sie nicht vertrauenswürdigen Vorlagencode als ausführbare Logik und rendern Sie ihn außerhalb des Anwendungsprozesses.

VERWUNDBAR
// Risiko: Anfragewerte als Vorlagenquelltext parsen
String src = "Hello " + userSuppliedName;
Template t = new Template("t", src, cfg);
t.process(model, writer);

// Risiko: benutzergesteuerte VTL-Zeichenfolge auswerten
Velocity.evaluate(context, writer,
                  "log", userTemplate);
GEPATCHT
// Vertrauenswürdige Classpath-Vorlage; Modell nur mit Skalaren
Configuration cfg = new Configuration(
    Configuration.VERSION_2_3_34);
cfg.setTemplateLoader(new ClassTemplateLoader(
    App.class, "/templates"));
cfg.setNewBuiltinClassResolver(
    TemplateClassResolver.ALLOWS_NOTHING_RESOLVER);
cfg.setObjectWrapper(new SimpleObjectWrapper(
    Configuration.VERSION_2_3_34));
Template t = cfg.getTemplate("hello.ftl");
Map<String,Object> model = Map.of(
    "name", userSuppliedName);
t.process(model, writer);

// Velocity: vertrauenswürdige Vorlage und begrenzte Introspektion (Tiefenverteidigung)
Properties p = new Properties();
p.setProperty("resource.loaders", "class");
p.setProperty("resource.loader.class.class",
    ClasspathResourceLoader.class.getName());
p.setProperty("runtime.introspector.uberspect",
    SecureUberspector.class.getName());
VelocityEngine engine = new VelocityEngine();
engine.init(p);
Template vt = engine.getTemplate("hello.vm", "UTF-8");
VelocityContext vc = new VelocityContext();
vc.put("name", userSuppliedName);
vt.merge(vc, writer);

Warum Java-Vorlagen gefährliche Fähigkeiten offenlegen können

Vorlagen werten Ausdrücke anhand eines Datenmodells aus; welche Java-Funktionen erreichbar sind, hängt aber von der Konfiguration ab. FreeMarkers Standard-Wrapper kann JavaBean-Eigenschaften und -Methoden beliebiger POJOs offenlegen; die verfügbaren Mitglieder richten sich nach Wrapper und Zugriffsrichtlinie. Velocitys Standard-Uberspect ordnet VTL-Eigenschaften öffentlichen Java-Methoden zu. Das bedeutet nicht, dass jedes Modell uneingeschränkte Reflection ermöglicht: Das Risiko steigt, wenn Dienste, ClassLoader, Request-Objekte oder andere mächtige Fähigkeiten im Modell liegen. Verwenden Sie bevorzugt Maps mit Strings und einfachen Werten und geben Sie nur benötigte Felder frei.

FreeMarkers Built-in ?new kann Klassen instanziieren, die TemplateModel implementieren. Apache empfiehlt eine eingeschränkte Klassenauflösung für hochgeladene Vorlagen; SAFER_RESOLVER erlaubt weiterhin bestimmte Klassen, während ALLOWS_NOTHING_RESOLVER jede Auflösung verweigert. Das ersetzt weder einen eingeschränkten Wrapper noch ein minimales Datenmodell.

Risiko senken und Grenzen kennen

Verstehen Sie Motoreinschränkungen als Tiefenverteidigung, nicht als Prozessisolation. Verwenden Sie unterstützte Versionen, prüfen Sie die genaue Konfiguration anhand aktueller Herstellerhinweise und halten Sie Geheimnisse sowie privilegierte Objekte vom Renderer fern.

Häufige Fragen

Ist Thymeleaf ebenfalls betroffen?

Das ist ein verwandtes, aber eigenständiges Risiko. Ein benutzergesteuerter View-Name ist nicht automatisch eine Expression-Injection. Prüfen Sie den konkreten Datenfluss in die Thymeleaf- oder Spring-Expression-Language-Auswertung und erzeugen Sie keine Ausdrucksfragmente aus nicht vertrauenswürdigen Eingaben. Halten Sie Integrationen aktuell und wählen Sie Views über vertrauenswürdige Anwendungslogik.

Nur Administratoren dürfen Vorlagen bearbeiten. Ist das vertretbar?

Vorlagenautoren können die Fähigkeiten des Motors und Datenmodells nutzen; das bedeutet nicht immer Betriebssystembefehle ausführen zu können. Behandeln Sie das Bearbeitungsrecht als sensibles Code-Autorenprivileg, beschränken Sie es auf vertrauenswürdige Maintainer und protokollieren Sie Änderungen.

Welcher Motor ist für von Benutzern bereitgestellte Vorlagen am sichersten?

Ein logikloser Motor wie Mustache kann die Oberfläche für Ausdrücke und Methodenaufrufe verkleinern. Ausgabekodierung, Kontrolle der Vorlagenquelle und Fähigkeiten von Helfern bleiben trotzdem wichtig. Wählen Sie einen Motor für dieses Vertrauensmodell und isolieren Sie das Rendering, statt einen allgemeinen JVM-Motor als Sandbox zu verwenden.

Offizielle Quellen und Referenzen

Siehe auch SSTI: Ursache und Schutz vor Template Injection Ist Jinja2s render_template_string() sicher? Was ist serverseitige Template-Injection?