
Vor einem Jahr, am 21. März 2019, kam auf HackerOne ein sehr guter ab . Bei der Einführung eines Null-Bytes (ASCII 0) in das POST-Parameter eines der API-Anfragen der Webmail, die einen HTTP-Redirect zurückgab, waren in den Redirect-Daten Teile uninitialisierter Speicher sichtbar, in denen häufig Fragmente aus GET-Parametern und Headern anderer Anfragen an denselben Server enthalten waren.
Dies ist eine kritische Schwachstelle, da die Anfragen unter anderem Sitzungscookies enthalten. Nach ein paar Stunden wurde ein temporärer Fix implementiert, der das Null-Byte filterte (wie sich später herausstellte, war das nicht ausreichend, da die Möglichkeit einer CRLF-/ASCII 13, 10-Injektion blieb, was es ermöglicht, die Header und Daten der HTTP-Antwort zu manipulieren; das ist weniger kritisch, aber dennoch unangenehm). Gleichzeitig wurde das Problem an Sicherheitsanalysten und Entwickler übergeben, um die Ursachen des Bugs zu finden und zu beseitigen.
Mail.ru Mail ist eine sehr komplexe Anwendung, an der eine Vielzahl von verschiedenen Frontend-/Backend-Komponenten beteiligt sein kann, sowohl Open-Source- (ein großer Dank an alle Entwickler von freier Software) als auch Eigenentwicklungen. Es gelang, alle Komponenten außer Nginx und OpenResty auszuschließen und das Problem bis zum Aufruf im OpenResty-Skript einzugrenzen, das sich nicht wie erwartet verhielt (das Einfügen eines Null-Bytes oder eines Zeilenumbruchs über GET-Parameter mit Rewrite im ngx_http_rewrite_module, der laut Dokumentation verwendet wird und eigentlich absolut ähnlich funktionieren sollte, ist nicht möglich). Mögliche Konsequenzen wurden beseitigt, eine maximal strenge Filterung hinzugefügt und überprüft, dass die Filterung alle möglichen Vektoren ausschaltet. Aber der Mechanismus, der zu einem Leck des Speicherinhalts führte, blieb ein Rätsel. Einen Monat später wurde der Bug-Report als behoben geschlossen, aber die Analyse der Ursachen wurde auf spätere Zeiten verschoben.
OpenResty ist ein sehr beliebtes Plugin, das es ermöglicht, Lua-Skripte innerhalb von Nginx zu schreiben, und es wird in mehreren Mail.ru-Projekten verwendet, weshalb das Problem nicht als behoben angesehen wurde. Nach einiger Zeit kam man jedoch darauf zurück, um die wahren Ursachen, mögliche Konsequenzen zu verstehen und Empfehlungen für Entwickler zu geben. An der Untersuchung des Quellcodes wirkten mit und . Es stellte sich heraus, dass:
- Bei der Verwendung von rewrite in nginx mit Benutzerdaten besteht in einigen Konfigurationen die Möglichkeit zur Directory Traversal (und wahrscheinlich SSRF), aber das ist ein bekanntes Problem und sollte von statischen Konfigurationsanalysatoren erkannt werden in und von Yandex (ja, das nutzen wir auch, danke). Bei der Verwendung von OpenResty kann diese Möglichkeit leicht übersehen werden, betrifft jedoch nicht unsere Konfiguration.
Konfigurationsbeispiel:
location ~ /rewrite { rewrite ^.*$ $arg_x; } location / { root html; index index.html index.htm; }Ergebnis
curl localhost:8337/rewrite?x=/..../..../..../..../..../..../etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
... - In nginx gibt es einen Fehler, der zu einer Speicherleckage führt, wenn die rewrite-Zeichenfolge ein Nullbyte enthält. Bei der Rückgabe einer Umleitung reserviert nginx einen neuen Speicherpuffer, der der vollständigen Länge der Zeichenfolge entspricht, kopiert die Zeichenfolge jedoch über eine Zeichenfolgenfunktion, bei der das Nullbyte ein Terminator ist, sodass die Zeichenfolge nur bis zum Nullbyte kopiert wird und der Rest des Puffers nicht initialisierte Daten enthält. Eine detaillierte Analyse finden Sie .
Konfigurationsbeispiel (^@ Nullbyte)
location ~ /memleak { rewrite ^.*$ "^@asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdasdf"; } location / { root html; index index.html index.htm; }Ergebnis
curl localhost:8337/secret -vv
...
curl localhost:8337/memleak -vv
...
Standort: http://localhost:8337/secret
...
- Nginx schützt GET-Parameter vor der Injektion von Steuerzeichen und ermöglicht die Verwendung von GET-Parametern nur in der rewrite. Daher ist es nicht möglich, die Injektion über benutzerkontrollierte Parameter in nginx auszunutzen. POST-Parameter sind dabei jedoch nicht geschützt. OpenResty ermöglicht die Arbeit sowohl mit GET- als auch mit POST-Parametern, daher besteht bei der Verwendung von POST-Parametern über OpenResty die Möglichkeit zur Injektion von Sonderzeichen.
Konfigurationsbeispiel:
location ~ /memleak { rewrite_by_lua_block { ngx.req.read_body(); local args, err = ngx.req.get_post_args(); ngx.req.set_uri( args["url"], true ); } } location / { root html; index index.html index.htm; }Ergebnis:
curl localhost:8337 -d "url=secret" -vv
...
curl localhost:8337 -d "url=asdfasdfasdfasdfasdfasdfasdfasdf" -vv
...
Standort: http://localhost:8337/{...kann secret enthalten...}
...
Weitere Maßnahmen
Das Problem wurde den Entwicklern von nginx und OpenResty gemeldet, die Entwickler betrachten das Problem nicht als Sicherheitsfehler in nginx, da es in nginx selbst keine Möglichkeit gibt, den Fehler über die Injektion von Sonderzeichen auszunutzen, der Fix wurde am 16. Dezember veröffentlicht. Nach 4 Monaten seit der Meldung wurden auch bei OpenResty keine Änderungen vorgenommen, obwohl das Verständnis besteht, dass eine sichere Variante der Funktion ngx.req.set_uri() erforderlich ist. Am 18. März 2020 veröffentlichten wir Informationen, am 21. März veröffentlichte OpenResty , die eine URI-Überprüfung hinzufügt.
Portswigger Ich habe einen guten Artikel gelesen und Kommentare von OpenResty und Nginx erhalten (tatsächlich ist der Kommentar, dass nur ein kleiner Speicherbereich offenbart wird, falsch und irreführend; dies hängt von der Länge der Zeile nach dem Nullbyte ab und kann ohne explizite Längeneinschränkungen vom Angreifer kontrolliert werden).
Was war also der Fehler und was kann getan werden, um ihn zu verhindern?
Lag der Fehler bei nginx? Ja, das war er, denn ein Speicherleck ist in jedem Fall ein Fehler.
Gab es einen Fehler bei OpenResty? Ja, mindestens die Sicherheitsfrage bezüglich der von OpenResty angebotenen Funktionalität wurde nicht untersucht und dokumentiert.
Wurde ein Konfigurations- / Nutzungfehler bei OpenResty gemacht? Ja, denn in Ermangelung einer klaren Angabe wurde eine unüberprüfte Annahme über die Sicherheit der verwendeten Funktionalität getroffen.
Welcher dieser Fehler stellt eine Sicherheitsanfälligkeit mit einem Bounty von $10000 dar? Für uns ist das eigentlich nicht wichtig. Bei jeder Software, insbesondere am Schnittpunkt mehrerer Komponenten, die von verschiedenen Projekten und Entwicklern bereitgestellt werden, kann niemand garantieren, dass alle Eigenheiten ihrer Funktionsweise bekannt und dokumentiert sind und dass keine Fehler vorhanden sind. Daher tritt jede Sicherheitsanfälligkeit genau dort auf, wo sie die Sicherheit beeinflusst.
In jedem Fall wäre es eine gute Praxis, die Eingabedaten, die an ein externes Modul / API gesendet werden, zu normalisieren oder so weit wie möglich zu beschränken / zu filtern, wenn es keine klaren Anweisungen und kein eindeutiges Verständnis gibt, dass dies nicht erforderlich ist.
Errata
Nach Erfahrung , um die Sprachreinheit zu wahren:
Bug Bounty — Wettbewerb zur Fehlerjagd
Fehlerbericht — Fehlermeldung
Redirect — Weiterleitung
Open Source — mit offenem Code
Errata — Arbeit an Fehlern
Quelle: habr.com
