Über eine Schwachstelle in…

Über eine Schwachstelle in…

Vor einem Jahr, am 21. März 2019, in das Bug Bounty-Programm von Mail.Ru auf HackerOne kam ein sehr guter Fehlerbericht ab maxarr. Bei der Implementierung eines Nullbytes (ASCII 0) in einen POST-Parameter einer der API-Anfragen der Webmail, die einen HTTP-Redirect zurückgab, waren in den Redirect-Daten Ausschnitte uninitialisierter Speicherbereiche sichtbar, in denen häufig Fragmente aus GET-Parametern und Headern anderer Anfragen an denselben Server offenbart wurden.

Dies ist eine kritische Schwachstelle, da die Anfragen unter anderem Sitzungscookies enthalten. Einige Stunden später wurde ein temporärer Fix erstellt, der das Nullbyte filterte (wie sich später herausstellte, war das nicht ausreichend, da weiterhin eine Möglichkeit zur Injektion von CRLF / ASCII 13, 10 bestand, was die Manipulation von Headern und HTTP-Antwortdaten ermöglicht, weniger kritisch, aber dennoch unangenehm). Zeitgleich wurde das Problem an die Sicherheitsanalysten und Entwickler weitergeleitet, um die Ursachen des Bugs zu untersuchen und zu beheben.

Mail.ru ist eine sehr komplexe Anwendung, bei der eine Vielzahl verschiedener Frontend-/Backend-Komponenten beteiligt sein kann, sowohl Open-Source (ein großes Dankeschön an alle Entwickler von Open-Source-Software) als auch eigenentwickelte. Es gelang, alle Komponenten außer nginx und openresty auszuschließen und das Problem bis zum Aufruf ngx.req.set_uri() im OpenResty-Skript zu lokalisieren, das sich nicht wie erwartet verhielt (es ist nicht möglich, ein Null-Byte oder einen Zeilenumbruch über GET-Parameter mit rewrite im ngx_http_rewrite_module einzufügen, das laut Dokumentation verwendet wird und angeblich absolut gleichartig funktionieren sollte). Mögliche Folgen wurden ausgeschlossen, eine so strenge Filterung wie möglich hinzugefügt und überprüft, dass die Filterung alle möglichen Vektoren ausschließt. Der Mechanismus, der zu einem Speicherleck führte, blieb jedoch ein Rätsel. Nach einem Monat wurde der Fehlerbericht als gelöst geschlossen, und die Untersuchung der Ursachen des Fehlers wurde auf unbestimmte Zeit verschoben.

OpenResty ist ein sehr beliebtes Plugin, das das Schreiben von Lua-Skripten innerhalb von nginx ermöglicht und in mehreren Projekten von Mail.ru verwendet wird. Daher galt das Problem nicht als gelöst. Nach einiger Zeit kehrten sie jedoch zurück, um die wahren Ursachen, mögliche Konsequenzen zu verstehen und Empfehlungen für die Entwickler zu erstellen. An den Analysen des Quellcodes waren beteiligt Denis Denisov und Nikolai Ermischkin. Es stellte sich heraus, dass:

  • Es gibt beim Einsatz von rewrite mit benutzerdefinierten Daten in nginx die Möglichkeit des Directory Traversal (und wahrscheinlich SSRF) in einigen Konfigurationen, was ein bekanntes Problem ist und von statischen Konfigurationsanalysatoren in Nginx Amplify und Gixy von Yandex (ja, das verwenden wir auch, danke). Bei der Verwendung von OpenResty kann man diese Möglichkeit leicht übersehen, aber unsere Konfiguration war davon nicht betroffen.

    Beispielkonfiguration:

    location ~ \/rewrite {
        rewrite ^.*$ $arg_x;
    }\n\nlocation \/ {
        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 einem Speicheraustritt führt, wenn die Rewrite-Zeile ein Nullbyte enthält. Beim Ausgeben einer Umleitung reserviert Nginx einen neuen Speicherpuffer, der der vollständigen Länge der Zeile entspricht, kopiert die Zeile jedoch über eine Zeichenfolgenfunktion, in der das Nullbyte ein Zeilenbegrenzer ist, sodass die Zeile nur bis zum Nullbyte kopiert wird und der Rest des Puffers nicht initialisierte Daten enthält. Eine detaillierte Analyse ist verfügbar. hier.

    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 erlaubt nur die Verwendung von GET-Parametern in der Rewrite-Regel. Daher ist es nicht möglich, über kontrollierte Benutzerparameter Injektionen in Nginx zu nutzen. POST-Parameter sind dabei nicht geschützt. OpenResty erlaubt die Arbeit mit sowohl GET- als auch POST-Parametern, weshalb bei der Verwendung von POST-Parametern über OpenResty die Möglichkeit besteht, spezielle Zeichen zu injizieren.

    Beispielkonfiguration:

    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/{...kann secret enthalten...}
    ...

Weitere Reaktion

Das Problem wurde an die Entwickler von nginx und OpenResty gemeldet. Die Entwickler betrachten das Problem nicht als Sicherheitsfehler in nginx, da es in nginx keine Möglichkeit gibt, den Fehler durch die Injektion von Sonderzeichen auszunutzen. Fix Speicherinhalt offenlegen wurde am 16. Dezember veröffentlicht. In den vier Monaten seit dem Bericht gab es in OpenResty ebenfalls keine Änderungen, obwohl klar war, dass eine sichere Variante der Funktion ngx.req.set_uri() notwendig war. Am 18. März 2020 veröffentlichten wir Informationen, und am 21. März brachte OpenResty Version 1.15.8.3, die eine URI-Prüfung hinzufügt.

Portswigger schrieb eine gute Artikel und holte sich Kommentare von OpenResty und Nginx (obwohl der Kommentar, dass nur ein kleiner Teil des Speichers offengelegt wird, falsch und irreführend ist, da dies durch die Länge der nachfolgenden Zeichenkette nach dem Null-Byte bestimmt wird und bei fehlenden expliziten Längenbeschränkungen vom Angreifer kontrolliert werden kann).

Also, wo lag der Fehler und was kann getan werden, um ihn zu verhindern?

Gab es einen Fehler in nginx? Ja, gab es, denn die Offenlegung von Speicherinhalt ist in jedem Fall ein Fehler.

Gab es einen Fehler in OpenResty? Ja, die Sicherheitsfragen bezüglich der angebotenen OpenResty-Funktionalitäten sind mindestens nicht untersucht und dokumentiert worden.

Wurde ein Fehler in der Konfiguration oder Nutzung von OpenResty gemacht? Ja, denn in Ermangelung einer ausdrücklichen Angabe wurde eine unüberprüfte Annahme über die Sicherheit der verwendeten Funktionalität getroffen.

Welche dieser Fehler stellt eine Sicherheitsanfälligkeit mit einem Bug-Bounty von 10.000 $ dar? Für uns ist das im Grunde genommen nicht wichtig. In jeder Software, insbesondere an der Schnittstelle mehrerer Komponenten, vor allem wenn diese von verschiedenen Projekten und Entwicklern bereitgestellt werden, kann niemand garantieren, dass alle Besonderheiten ihres Betriebs bekannt und dokumentiert sind und dass es keine Fehler gibt. Daher tritt jede Sicherheitsanfälligkeit genau dort auf, wo sie die Sicherheit beeinflusst.

In jedem Fall ist es eine gute Praxis, Eingabedaten zu normalisieren oder so weit wie möglich zu beschränken/filteren, die an externe Module/APIs gesendet werden, wenn es keine ausdrücklichen Anweisungen oder eindeutiges Verständnis dafür gibt, dass dies nicht erforderlich ist.

Errata

Aus Erfahrung Das verleiht ihm zugleich Einzigartigkeit und gewährleistet die Eindeutigkeit der Sortierreihenfolge:, um die sprachliche Klarheit zu bewahren:

Bug-Bounty — Wettbewerb zur Fehlersuche
Fehlerbericht — Fehlermeldung
Weiterleitung — Weiterleitung
Open Source — Open Source
Errata — Arbeiten an Fehlern

Quelle: habr.com

Zuverlässiges Webhosting mit DDoS-Schutz, VPS- und VDS-Server kaufen 🔥 Zuverlässiges Webhosting mit DDoS-Schutz, VPS- und VDS-Server kaufen | ProHoster