flawopen.com/Incidents/equifax-struts-ognl-rce-july-2017
Equifax: Daten von fast 150 Millionen offengelegt
CVE-2017-5638 ermöglichte OGNL-Injection über den Content-Type-Header im ungepatchten Struts-Portal von Equifax. Der Angriff dauerte etwa 76 Tage und legte Daten von fast 150 Millionen Menschen offen.[1], [4]
Stellen Sie sich eine Versandsoftware vor, die ein abgelehntes Paketetikett in eine Fehlermeldung übernimmt. Behandelt die Meldung das Etikett als ausführbare Vorlage, kann der Absender die Software Anweisungen ausführen lassen, statt nur eine ungültige Adresse zu melden. Für Struts gab es bereits einen Patch, doch Equifax versandte den Hinweis an eine veraltete Administratorenliste und ein Netzwerkscan erkannte die Schwachstelle im Portal nicht.[1], [4]
Kernkonzepte & Begriffe
OGNL- Object-Graph Navigation Language, die Ausdruckssprache, mit der Struts Eigenschaften von Java-Objekten liest und setzt. Angreifertext als OGNL auszuwerten heißt, den Code des Angreifers auszuführen.[1], [6]
Jakarta-Multipart-Parser- Die Struts-Komponente für Datei-Uploads. Lehnte sie einen fehlerhaften Content-Type ab, baute sie eine Fehlermeldung, die anschließend ausgewertet wurde.[1], [3], [2]
Ausdrucks-Injection (CWE-917)- Nicht vertrauenswürdige Eingaben landen in einem Ausdruck, den ein Interpreter auswertet – Daten werden zu Anweisungen.[6]
Asset-Inventar- Eine Aufstellung, welche Software in welcher Version auf welchem System läuft. Ohne sie lässt sich ein Patch-Hinweis nicht den betroffenen Maschinen zuordnen.[4]
Framework-Zuordnungen
- CWE-Referenz für die in diesem Leitfaden beschriebene Schwachstelle: CWE-20 CWE-917
- CISA KEV — aufgenommen am 2021-11-03 — CVE-2017-5638
Vorfall-Zeitstrahl
Apache veröffentlicht das Sicherheitsbulletin S2-045 und die korrigierten Struts-Versionen 2.3.32 und 2.5.10.1.[1]
Equifax teilte dem GAO später mit, dass am 13. Mai ein separater Einbruch begann und die Angreifer ab dann personenbezogene Daten extrahierten; ein früherer unbefugter Zugriff war bereits erfolgt, ohne Daten zu stehlen.[4]
Equifax bemerkt verdächtigen Datenverkehr, nachdem ein abgelaufenes Zertifikat auf einem Gerät zur Verkehrsprüfung erneuert wurde.[4]
Equifax macht den Vorfall öffentlich. Das GAO berichtet später, dass Daten von mindestens 145,5 Millionen Menschen in den USA und knapp einer Million außerhalb der USA betroffen waren.[4]
Schritt-für-Schritt Angriffsablauf
Ein präparierter Content-Type-Header
Der Angreifer sendet eine Upload-Anfrage, deren Content-Type-Header statt eines Medientyps einen OGNL-Ausdruck enthält.[1]
Leiser, langer Datenabfluss
Die Angreifer nutzten in einem Datenspeicher gefundene Zugangsdaten, um von den drei Portal-Datenbanken auf 48 weitere, vom Portal unabhängige Datenbanken zuzugreifen. Das GAO berichtet von etwa 9.000 Abfragen und einem rund 76 Tage dauernden Angriff; ein abgelaufenes Zertifikat verhinderte die Prüfung verschlüsselten Datenverkehrs.[4]
Quellcode: Verwundbar vs. Sicher
Illustratives Java, kein Struts-Quellcode; die echte Korrektur in 2.3.32 und 2.5.10.1 änderte, wie der Multipart-Fehler gebaut wird. Die gehärtete Version nutzt einen festen Meldungsschlüssel und übergibt den Header nur als Positionsargument, sodass er als Text formatiert und nie Teil eines Ausdrucks wird. Außerdem ersetzt sie alles, was nicht wie ein Medientyp aussieht, durch einen Platzhalter – selbst eine spätere Änderung der Meldung kann den Header so nicht wieder in eine ausgewertete Zeichenkette bringen.[3], [2], [6]
import com.opensymphony.xwork2.TextProvider;
import javax.servlet.http.HttpServletRequest;
public final class UploadErrors {
private final TextProvider text; // resolves messages and evaluates expressions in them
public UploadErrors(TextProvider text) {
this.text = text;
}
public String describe(HttpServletRequest request) {
String contentType = request.getHeader("Content-Type");
// Der unverarbeitete Header wird Teil der ausgewerteten Nachricht.
return text.getText("Invalid content type: " + contentType);
}
}import com.opensymphony.xwork2.TextProvider;
import java.util.Locale;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
public final class UploadErrors {
private static final Pattern MEDIA_TYPE = Pattern.compile(
"^[a-z]+/[a-z0-9.+-]+(;\\s*[a-z0-9-]+=[a-z0-9._-]+)*$");
private final TextProvider text;
public UploadErrors(TextProvider text) {
this.text = text;
}
public String describe(HttpServletRequest request) {
String contentType = request.getHeader("Content-Type");
boolean wellFormed = contentType != null && contentType.length() <= 256
&& MEDIA_TYPE.matcher(contentType.toLowerCase(Locale.ROOT)).matches();
// Einen festen Nachrichtenschlüssel verwenden; der Header ist nur ein Positionsargument,
// und nur, wenn er die Form eines Medientyps hat.
return text.getText("upload.invalid.content.type",
new String[] { wellFormed ? contentType : "(malformed)" });
}
}Checkliste für Engineering & Systemsicherheit
- ✓Führen Sie für jede ausgerollte Anwendung eine SBOM und beantworten Sie „Wo läuft bei uns Struts 2.3.x?“ innerhalb weniger Stunden nach einem Hinweis wie S2-045.[4]
- ✓Gleichen Sie die Ziele des Schwachstellenscanners mit dem Asset-Inventar ab; ein sauberer Scan eines Hosts, der nie im Scope war, belegt keinen Patch.[4]
- ✓Alarmieren Sie mindestens 30 Tage vor dem Ablauf von Zertifikaten auf TLS-Inspektions- und Überwachungsgeräten; hier verbarg ein abgelaufenes Zertifikat monatelangen Datenabfluss.[4]
- ✓Lehnen Sie im Code-Review jeden Aufruf ab, der verketteten nicht vertrauenswürdigen Text an einen Meldungs-Resolver, eine Template-Engine oder einen Ausdrucksauswerter übergibt; übergeben Sie ihn als Argument.[6]
- ✓Trennen Sie Datenbanken von aus dem Internet erreichbaren Anwendungen, halten Sie Zugangsdaten aus Anwendungsdateien heraus und alarmieren Sie bei ungewöhnlichem Abfragevolumen von Anwendungskonten.[4]
Quellen
- Apache Struts — Sicherheitsbulletin S2-045 (CVE-2017-5638)
- Apache Struts — multipart parser error-message fix (commit 3523064)
- Apache Struts — upstream multipart error-handling fix (commit 6b8272c)
- US-GAO — Datenschutz: Maßnahmen von Equifax und Bundesbehörden nach dem Einbruch von 2017 (GAO-18-559)
- CVE-2017-5638 — CVE-Eintrag
- MITRE CWE-917 — Injection in Ausdruckssprachen
- Log4Shell: als das Schreiben in eine Logdatei zu Remote-Code-Ausführung wurde
- Command Injection — vollständige Referenz der Klasse