Over een kwetsbaarheid in…

Over een kwetsbaarheid in…

Een jaar geleden, op 21 maart 2019, in het bug bounty-programma van Mail.Ru kwam er een zeer goede bugrapport van maxarr. Bij de invoering van een nul-byte (ASCII 0) in de POST-parameter van een van de API-verzoeken van webmail, dat een HTTP-redirect terugstuurde, verschenen er stukken niet-geĆÆnitieerde geheugen in de gegevens van de redirect, waarin vaak fragmenten van GET-parameters en headers van andere verzoeken naar dezelfde server werden onthuld.

Dit is een kritieke kwetsbaarheid, aangezien de verzoeken ook sessiecookies bevatten. Enkele uren later werd er een tijdelijke patch gemaakt die de nul-byte filterde (zoals later bleek, was dit niet voldoende, aangezien er nog steeds een mogelijkheid was voor CRLF-injectie / ASCII 13, 10, wat het mogelijk maakte om headers en gegevens van de HTTP-respons te manipuleren, dit is minder kritiek, maar nog steeds ongewenst). Tegelijkertijd werd het probleem doorgegeven aan beveiligingsanalisten en ontwikkelaars voor het opsporen en oplossen van de oorzaken van de bug.

Mail.ru Mail is een zeer complexe applicatie, waarbij een groot aantal verschillende frontend/backend-componenten betrokken kan zijn, zowel open source (grote dank aan alle ontwikkelaars van vrije software), als van eigen ontwikkeling. Het is gelukt om alle componenten uit te sluiten, behalve nginx en openresty, en het probleem te lokaliseren tot het aanroepen van ngx.req.set_uri() in het OpenResty-script, dat zich niet gedroeg zoals verwacht (het was niet mogelijk om een nul-byte of een nieuwe regel door GET-parameters met rewrite in ngx_http_rewrite_module in te voeren, die volgens de documentatie wordt gebruikt en, zou moeten werken, identiek). Mogelijke gevolgen werden geƫlimineerd, er werd een zo streng mogelijke filtering toegevoegd en gecontroleerd dat de filtering alle mogelijke vectoren uitsluit. Maar het mechanisme dat leidde tot de lek van geheugeninhoud bleef een raadsel. Na een maand werd het bugrapport gesloten als opgelost, en de analyse van de oorzaken van de bug werd uitgesteld tot een later tijdstip.

OpenResty is een zeer populaire plugin waarmee Lua-scripts binnen nginx kunnen worden geschreven, en het wordt gebruikt in verschillende projecten van Mail.ru, dus het probleem werd niet als opgelost beschouwd. En na een tijdje werd er weer naar teruggekeerd om de ware oorzaken, mogelijke gevolgen en aanbevelingen voor ontwikkelaars te begrijpen. Bij het doorspitten van de broncode waren Denis Denisov en Nikolai ErmisjkinHet bleek dat:

  • In nginx, bij het gebruik van rewrite met gebruikersgegevens, er mogelijkheid tot directory traversal (en waarschijnlijk SSRF) is in sommige configuraties, maar dit is een bekend feit en moet worden gedetecteerd door statische configuratie-analysatoren in Nginx Amplify en Gixy van Yandex (ja, we gebruiken het ook, bedankt). Bij het gebruik van OpenResty kan deze mogelijkheid gemakkelijk worden gemist, maar onze configuratie werd er niet door getroffen.

    voorbeeldconfiguratie:

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

    het resultaat

    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 is er een fout die leidt tot geheugeninhoudslekken als de rewrite-string een nulbyte bevat. Bij het retourneren van een omleiding maakt nginx een nieuwe geheugenbuffer aan die overeenkomt met de volledige lengte van de string, maar kopieert deze via een stringfunctie waarbij de nulbyte de tekenreeks beĆ«indigt, zodat de string slechts tot de nulbyte wordt gekopieerd en de rest van de buffer niet-geĆÆnitialiseerde gegevens bevat. Een gedetailleerde analyse is te vinden hier.

    voorbeeldconfiguratie (^@ nulbyte)

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

    het resultaat
    curl localhost:8337/secret -vv
    ...
    curl localhost:8337/memleak -vv
    ...
    Locatie: http://localhost:8337/secret
    ...

  • Nginx beschermt GET-parameters tegen injectie van controltekens en stelt alleen GET-parameters toe in de rewrite. Daarom kan de injectie via door de gebruiker gecontroleerde parameters in nginx niet worden uitgebuit. POST-parameters zijn hierbij niet beschermd. OpenResty maakt het mogelijk om zowel met GET als POST-parameters te werken, waardoor bij het gebruik van POST-parameters via OpenResty de mogelijkheid van injectie van speciale tekens ontstaat.

    voorbeeldconfiguratie:

    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;
    }
    

    resultaat:

    curl localhost:8337 -d "url=secret" -vv
    ...
    curl localhost:8337 -d "url=asdfasdfasdfasdfasdfasdfasdfasdf" -vv
    ...
    Locatie: http://localhost:8337/{...kan secret bevatten...}
    ...

Verdere reactie

Het probleem werd gemeld aan de ontwikkelaars van nginx en OpenResty, de ontwikkelaars beschouwen het probleem niet als een beveiligingsfout in nginx, aangezien er in nginx zelf geen mogelijkheid is om de fout via injectie van speciale tekens te exploiteren, fix vrijgave van geheugeninhoud werd op 16 december gepubliceerd. In de 4 maanden sinds de rapportage zijn er ook geen wijzigingen gemaakt in OpenResty, hoewel er begrip was dat er een veilige variant van de functie ngx.req.set_uri() noodzakelijk was. Op 18 maart 2020 publiceerden we informatie, op 21 maart bracht OpenResty uit versie 1.15.8.3, die een controle van de URI toevoegt.

Portswigger schreef Een goed artikel en de opmerkingen van OpenResty en Nginx besproken (de opmerking dat slechts een klein deel van het geheugen wordt onthuld is echter onjuist en misleidend; dit wordt bepaald door de lengte van de string die volgt op de nulbyte, en in het geval van ontbrekende expliciete lengtebeperkingen kan dit door de aanvaller worden gecontroleerd).

Wat was de fout en wat kunnen we doen om deze te voorkomen?

Was de fout in nginx? Ja, dat was het, omdat een geheugenlek in ieder geval een fout is.

Was er een fout in OpenResty? Ja, in ieder geval is de kwestie van de veiligheid van de aangeboden OpenResty-functies niet onderzocht of gedocumenteerd.

Was er een fout in de configuratie / het gebruik van OpenResty? Ja, omdat er in het ontbreken van expliciete aanwijzingen een ongecontroleerde veronderstelling is gedaan over de veiligheid van de gebruikte functionaliteit.

Welke van deze fouten is een beveiligingskwetsbaarheid met een bounty van $10000? Voor ons maakt dat eigenlijk niet uit. In elke software, vooral aan de snijpunten van verschillende componenten, vooral geleverd door verschillende projecten en ontwikkelaars, kan niemand ooit garanderen dat alle kenmerken van hun werking bekend en gedocumenteerd zijn en dat er geen fouten zijn. Daarom ontstaat elke beveiligingskwetsbaarheid juist daar waar deze invloed heeft op de veiligheid.

In ieder geval is het een goede praktijk om binnenkomende gegevens te normaliseren of zo veel mogelijk te beperken/filteren die naar een externe module/API gaan, als er geen expliciete aanwijzingen en ondubbelzinnige begrijpelijkheid zijn dat dit niet nodig is.

Errata

Op basis van ervaring het vorige artikel, ter behoud van de zuiverheid van de taal:

bug bounty — wedstrijd voor het opsporen van fouten
bugrapport — foutmelding
redirect — omleiding
open-source — open source
errata — werken aan fouten

Bron: habr.com

Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers šŸ”„ Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers | ProHoster