Über eine Schwachstelle in


Über eine Schwachstelle in


Vor einem Jahr, am 21. MĂ€rz 2019, kam das Bug-Bounty-Programm von Mail.Ru auf HackerOne ein sehr guter Fehlerbericht ab maxarr. 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 ngx.req.set_uri() 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 Denis Denisov und Nikolai Jermishkin. 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 Nginx Amplify und Gixy 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 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 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 offenlegung der Speicherdaten 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 Version 1.15.8.3, die eine URI-ÜberprĂŒfung hinzufĂŒgt.

Portswigger schrieb 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 dem vorherigen Artikel, 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

60GB SSD 8Gb DDR4