Über eine Schwachstelle in…

Über eine Schwachstelle in…

Vor einem Jahr, 21. März 2019, in Bug-Bounty-Programm Mail.Ru ein sehr gutes kam zu HackerOne Fehlerbericht aus maxarr. Beim Einfügen eines Nullbytes (ASCII 0) in den POST-Parameter einer der Webmail-API-Anfragen, die eine HTTP-Umleitung zurückgaben, waren in den Umleitungsdaten Teile nicht initialisierten Speichers sichtbar, in denen Fragmente von GET-Parametern und Headern anderer Anfragen an die gleichen Server.

Dies ist eine kritische Sicherheitslücke, weil... Anfragen enthalten auch Sitzungscookies. Ein paar Stunden später wurde eine vorübergehende Korrektur vorgenommen, die das Null-Byte herausfilterte (wie sich später herausstellte, reichte dies nicht aus, da noch die Möglichkeit bestand, CRLF/ASCII 13, 10 einzuschleusen, wodurch man die Header und manipulieren konnte Daten der HTTP-Antwort, das ist weniger kritisch, aber dennoch unangenehm). Gleichzeitig wurde das Problem an Sicherheitsanalysten und Entwickler übergeben, um die Fehlerursachen zu finden und zu beseitigen.

Mail.ru Mail ist eine sehr komplexe Anwendung; eine große Anzahl verschiedener Front-End-/Back-End-Komponenten, sowohl Open Source (vielen Dank an alle Entwickler freier Software) als auch selbst entwickelte, können an der Generierung der Antwort beteiligt sein. Es ist uns gelungen, alle Komponenten außer Nginx und Openresty auszuschließen und das Problem vor dem Anruf zu lokalisieren ngx.req.set_uri() in einem OpenResty-Skript, das sich nicht wie erwartet verhielt (Einfügen eines Nullbytes oder Zeilenvorschubs über GET-Parameter mit Rewrite in ngx_http_rewrite_module, das laut Dokumentation verwendet wird und anscheinend genauso funktionieren sollte). nicht arbeiten). Mögliche Konsequenzen wurden eliminiert, die Filterung wurde so streng wie möglich hinzugefügt und die Filterung wurde überprüft, um alle möglichen Vektoren zu eliminieren. Doch der Mechanismus, der zum Durchsickern von Speicherinhalten führte, blieb ein Rätsel. Einen Monat später wurde der Fehlerbericht als behoben geschlossen und die Analyse der Fehlerursachen auf bessere Zeiten verschoben.

OpenResty ist ein sehr beliebtes Plugin, mit dem Sie Lua-Skripte in Nginx schreiben können. Es wird in mehreren Mail.ru-Projekten verwendet, sodass das Problem nicht als gelöst angesehen wurde. Und nach einiger Zeit kehrten sie endlich darauf zurück, um die wahren Gründe und möglichen Konsequenzen zu verstehen und Empfehlungen für Entwickler zu geben. Beteiligt an der Ausgrabung des Quellcodes Denis Denisov и Nikolay Ermishkin. Es stellte sich heraus, dass:

  • In Nginx besteht bei der Verwendung von Rewrite mit Benutzerdaten in einigen Konfigurationen die Möglichkeit einer Verzeichnisdurchquerung (und wahrscheinlich von SSRF). Dies ist jedoch eine bekannte Tatsache und sollte von statischen Konfigurationsanalysatoren in erkannt werden Nginx verstärken и geil von Yandex (ja, das nutzen wir auch, danke). Bei Verwendung von OpenResty ist diese Funktion leicht zu übersehen, hatte jedoch keine Auswirkungen auf unsere Konfiguration.

    Konfigurationsbeispiel:

    location ~ /rewrite {
        rewrite ^.*$ $arg_x;
    }
    
    location / {
        root html;
        index index.html index.htm;
    }

    führen

    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
    ...

  • Nginx weist einen Fehler auf, der zu Speicherlecks führt, wenn die Rewrite-Zeile ein Null-Byte enthält. Wenn eine Umleitung ausgegeben wird, weist nginx einen neuen Speicherpuffer zu, der der vollen Länge der Zeile entspricht, kopiert die Zeile dort jedoch über eine Zeilenfunktion, bei der das Nullbyte ein Zeilenabschlusszeichen ist, sodass die Zeile nur bis zur Null kopiert wird Byte; der Rest des Puffers enthält nicht initialisierte Daten. Eine ausführliche Analyse finden Sie hier hier.

    Konfigurationsbeispiel (^@ null Byte)

    
    location ~ /memleak {
        rewrite ^.*$ "^@asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdasdf";
    }
    
    location / {
        root html;
        index index.html index.htm;
    }

    führen
    curl localhost:8337/secret -vv
    ...
    curl localhost:8337/memleak -vv
    ...
    Location: http://localhost:8337/secret
    ...

  • Nginx schützt GET-Parameter vor der Injektion von Dienstzeichen und ermöglicht die Verwendung nur von GET-Parametern beim Umschreiben. Daher ist es nicht möglich, die Injektion durch benutzergesteuerte Parameter in Nginx auszunutzen. POST-Parameter sind nicht geschützt. Mit OpenResty können Sie sowohl mit GET- als auch mit POST-Parametern arbeiten. Wenn Sie also POST-Parameter über OpenResty verwenden, ist es möglich, Sonderzeichen einzufügen.

    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=%00asdfasdfasdfasdfasdfasdfasdfasdf" -vv
    ...
    Location: http://localhost:8337/{...может содержать secret...}
    ...

Weitere Reaktion

Das Problem wurde den Entwicklern von Nginx und OpenResty gemeldet, die Entwickler betrachten das Problem nicht als Sicherheitslücke in Nginx, weil In Nginx selbst gibt es keine Möglichkeit, den Fehler durch das Einfügen von Sonderzeichen auszunutzen, beheben Offenlegung der Erinnerung wurde am 16. Dezember veröffentlicht. In den vier Monaten seit dem Bericht wurden keine Änderungen an OpenResty vorgenommen, obwohl man sich darüber im Klaren war, dass eine sichere Version der Funktion ngx.req.set_uri() benötigt wird. Am 4. März 18 haben wir Informationen veröffentlicht, am 2020. März wurde OpenResty veröffentlicht Version 1.15.8.3, wodurch eine URI-Validierung hinzugefügt wird.

Portswigger написал guter Artikel und habe Kommentare von OpenResty und Nginx übernommen (obwohl der Kommentar, dass nur ein kleines Fragment des Speichers offengelegt wird, falsch und irreführend ist, wird dies durch die Länge der Zeile nach dem Nullbyte bestimmt und, sofern keine expliziten Einschränkungen dafür vorliegen Länge, kann vom Angreifer kontrolliert werden).

Was war also der Fehler und was kann man tun, um ihn zu verhindern?

Gab es einen Fehler in Nginx? Ja, das war es, denn das Auslaufen von Speicherinhalten ist in jedem Fall ein Fehler.

Gab es einen Fehler in OpenResty? Ja, zumindest die Frage der Sicherheit der von OpenResty angebotenen Funktionalität wurde nicht untersucht und dokumentiert.

Gab es einen Konfigurations-/Nutzungsfehler bei OpenResty? Ja, denn mangels expliziter Aussage wurde eine unbestätigte Annahme über die Sicherheit der genutzten Funktionalität getroffen.

Bei welchem ​​dieser Fehler handelt es sich um eine Sicherheitslücke mit einer Prämie von 10000 US-Dollar? Für uns ist das grundsätzlich nicht wichtig. In jeder Software, insbesondere an der Schnittstelle mehrerer Komponenten, insbesondere solcher, die von verschiedenen Projekten und Entwicklern bereitgestellt werden, kann niemand garantieren, dass alle Merkmale ihrer Arbeit bekannt und dokumentiert sind und dass keine Fehler vorliegen. Daher tritt jede Sicherheitslücke genau dort auf, wo sie die Sicherheit beeinträchtigt.

In jedem Fall empfiehlt es sich, die Eingabedaten, die in ein externes Modul/eine externe API gehen, so weit wie möglich zu normalisieren oder zu begrenzen/zu filtern, es sei denn, es liegen explizite Anweisungen vor und es besteht ein klares Verständnis dafür, dass dies nicht erforderlich ist.

Errata

Aus Erfahrung Vorheriger Artikel, um die Reinheit der Sprache zu wahren:

Bug-Bounty — Wettbewerb zur Insektenjagd
Fehlerbericht - Fehlermeldung
umleiten - Umleitung
Open Source - Open Source
Errata - an Fehlern arbeiten

Source: habr.com

Kommentar hinzufügen