Dev News Daily ENDE

Ihre Abhängigkeitsliste enthält nicht den meistangegriffenen Code

Jedes Team, mit dem ich gearbeitet habe, kann in vier Sekunden eine Abhängigkeitsliste erzeugen. npm ls, mvn dependency:tree, pip freeze, die SBOM aus dem Build. Das ist ein echtes Artefakt und beantwortet eine echte Frage: worauf haben wir uns bewusst gestützt?

Es beantwortet nicht die Frage, die Angreifer stellen: welcher Code läuft, wenn ich Ihnen diese Datei schicke?

Die beiden Listen sind nicht dieselbe

Ein Dienst, der Bild-Uploads annimmt und ein Vorschaubild erzeugt, erreicht der Reihe nach: ein Web-Rahmenwerk, einen Bild-Wrapper wie ImageMagick, libvips oder Sharp — und dann einen nativen C- oder C++-Decoder, gewählt anhand der Bytes. Nicht anhand der Endung, nicht anhand des Content-Type-Headers und schon gar nicht anhand des Manifests. Für HEIC und AVIF ist dieser Decoder meist libheif, aufsetzend auf libde265.

Niemand in dieser Kette hat sich zwangsläufig für HEIC entschieden. Der Wrapper kann, wogegen er übersetzt wurde; das Container-Basisabbild bringt mit, was die Distribution paketiert hat; und die Distribution paketiert, was das Format-Ökosystem hervorbringt. Im Manifest der Anwendung steht der Wrapper. Der Decoder liegt zwei Schichten unter der untersten Zeile darin.

Die HEIF-Heist-Offenlegung dieser Woche ist das aktuelle Beispiel, aber das Muster ist nicht neu: ImageTragick, ForcedEntry und die libwebp-Lücke hatten dieselbe Gestalt. Eine kleine native Bibliothek, fast überall eingebettet, erreichbar durch fremde Bytes, laufend im selben Prozess wie Ihre Sitzungstoken.

Ihre Abhängigkeitsliste enthält nicht den meistangegriffenen Code
Ihre Abhängigkeitsliste enthält nicht den meistangegriffenen Code — Dev News Daily

Vier Fragen, die das aufdecken

1. Was erreicht einen Parser, und welchen? Benennen Sie für jede Stelle, an der Ihr System fremde Bytes annimmt — Uploads, Profilbilder, E-Mail-Anhänge, importierte Dokumente, gelesene Webseiten, QR-Codes, hochgeladene Schriften —, welche Bibliothek sie tatsächlich dekodiert. Lautet die Antwort „was ImageMagick eben wählt", ist das der Befund.

2. Wogegen ist der Container wirklich gelinkt? Nicht, was das Dockerfile installiert, sondern was im fertigen Abbild liegt: ldd auf den Binärdateien, die Paketliste im Abbild, das Manifest des Basisabbilds. Die meisten Teams haben nie nachgesehen — und die Antwort enthält in der Regel Decoder für Formate, die das Produkt gar nicht unterstützt.

3. Kann ein Außenstehender Ihre Version erkennen? Formate zu sondieren, um die Decoder-Version zu bestimmen, verwandelt einen Speicherfehler in einen gezielten Angriff: Der Angreifer weiß vorher, welche Nutzlast passt. Unterschiede in Fehlermeldungen, Laufzeiten und akzeptierten Grenzfällen verraten das. Ganz verhindern lässt es sich nicht — aber Decoder-Fehler unverändert zurückzugeben, kann man lassen.

4. Wie groß ist der Radius einer Dekodierung? Nur diese Frage hat eine haltbare Antwort. Ein Decoder, der im Anfrageprozess läuft, als Dienstnutzer, mit Netz und Geheimnissen in Reichweite, macht aus einem Speicherfehler die vollständige Übernahme. Derselbe Fehler in einem separaten Prozess ohne Netz, mit abgegebenen Rechten, Speicherdeckel und Zeitlimit ist ein Absturz und ein 500er.

Der unangenehme Teil

Die wirksamen Gegenmittel sind genau die, die in keinem Abhängigkeitsbericht auftauchen und sich nicht kaufen lassen: außerhalb des Prozesses dekodieren, Maße und Speicher vor der Allokation begrenzen, ein Zeitlimit setzen, Rechte abgeben — und an der Grenze in ein einziges kanonisches Format umkodieren, damit alles dahinter nur noch Bytes verarbeitet, die Sie selbst erzeugt haben.

Nichts davon erscheint als grüner Haken in einem Scanner. Der Scanner liest das Manifest — und das Manifest beschreibt, was Sie gewählt haben, in einem Teil des Stapels, in dem die Wahl für Sie getroffen wurde.