Om en sårbarhet i...

Om en sårbarhet i...

Eit år sidan, 21. mars 2019, kom det inn bounty-programmet til Mail.Ru på HackerOne ein svært god feilmelding fra maxarr. Ved implementering av nullbyte (ASCII 0) i POST-parameteret til ein av API-forespørslane til nettposttenesta, som returnerte HTTP-omdirigering, kom det fram fragment av nicht initialisert minne, der det oftast vart avslørt deler av GET-parametrar og overskrifter frå andre forespørselar til den same serveren.

Dette er ein kritisk sårbarheit, sidan forespørslane også inneheld sesjonscookies. Nokre timer seinare vart det laga ein midlertidig fix som filtrerte nullbyte (som det seinare viste seg, var dette ikkje tilstrekkeleg, sidan det framleis var mogleg å injisere CRLF /ASCII 13, 10, som gjer det mogleg å manipulere overskrifter og data i HTTP-svaret, dette er mindre kritisk, men likevel ubehageleg). Samtidig vart problemet sendt til sikkerheitsanalytikarar og utviklarar for å finne årsakene til feil.

Mail.ru post er eit særs komplekst program, der eit stort antal av ulike frontend/backend-komponentar kan vere involvert i genereringa av svaret, både open source (takk til alle utviklarar av fri programvare) og eigne utviklingar. Det vart mogleg å ekskludere alle komponentar unntatt nginx og openresty, og lokalisere problemet til kallet ngx.req.set_uri() i OpenResty-skriptet, som oppførte seg ikkje som forventa (det viser seg at ein ikkje kan sette inn nullbyte eller linjeskift via GET-parametrar med rewrite i ngx_http_rewrite_module, som ifølge dokumentasjonen vert brukt og som tilsynelatande burde fungere heilt likt). Moglege konsekvensar vart fjerna, den strenge filtreringa vart lagt til, og det vart kontrollert at filtreringa eliminerer alle moglegheiter. Men mekanismen som førte til lekkasje av innhaldet i minnet forblev eit mysterium. Eit månad seinare vart bugraporten stengt som løyst, mens analysen av årsakene til feilen vart utsett til seinare.

OpenResty er ein svært populær plugin som lar skriving av Lua-skript inne i nginx, og det blir brukt i fleire prosjekt av Mail.ru, så problemet vart ikkje sett på som løyst. Og etter ei stund vart det faktisk teke opp att for å forstå dei sanne årsakene, mulige konsekvensar og lage anbefalingar for utviklarar. I gravearbeidet i kildekoden deltok Denis Denisov og Nikolai ErmishkinDet viste seg at:

  • I nginx, ved bruk av rewrite med brukerdata, er det mulig med directory traversal (og sannsynligvis SSRF) i visse konfigurasjoner, men dette er et kjent faktum, og det bør oppdages av statiske konfigurasjonsanalysatorer i Nginx Amplify og Gixy fra Yandex (ja, vi bruker det også, takk). Ved bruk av OpenResty er det lett å overse denne muligheten, men vår konfigurasjon ble ikke berørt.

    eksempelkonfigurasjon:

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

    resultat

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

  • I nginx er det en feil som fører til at innholdet i minnet lekker hvis rewrite-strengen inneholder et nullbyte. Når nginx returnerer en redirect, allokerer den en ny minnebuffer som svarer til full lengde av strengen, men kopierer den til strengen via en funksjon der nullbyte er strengterminatoren, så strengen blir bare kopiert frem til nullbyte, resten av bufferen inneholder ikke-initialiserte data. En detaljert analyse kan finnes her.

    eksempelkonfigurasjon (^@ nullbyte)

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

    resultat
    curl localhost:8337/secret -vv
    ...
    curl localhost:8337/memleak -vv
    ...
    Location: http://localhost:8337/secret
    ...

  • Nginx beskytter GET-parametre mot injeksjon av spesialtegn og gir mulighet til å bruke i rewrite bare GET-parametre. Derfor er det ikke mulig å utnytte injeksjon gjennom kontrollerte brukerparametre i nginx. POST-parametre er imidlertid ikke beskyttet. OpenResty tillater arbeid både med GET og POST-parametre, så ved bruk av POST-parametre gjennom OpenResty oppstår muligheten for injeksjon av spesialtegn.

    eksempelkonfigurasjon:

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

    resultat:

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

Videre reaksjon

Utviklerne av nginx og OpenResty har blitt informert om problemet, utviklerne anser ikke problemet som en sikkerhetsfeil i nginx, siden det i nginx ikke er mulighet for å utnytte feilen gjennom injeksjon av spesialtegn, fiksen memorlekasje ble publisert 16. desember. I løpet av 4 måneder etter rapporteringen har det ikke blitt gjort noen endringer i OpenResty, selv om det var forståelse for at det var behov for en sikker variant av funksjonen ngx.req.set_uri(). 18. mars 2020 publiserte vi informasjon, 21. mars utgav OpenResty versjon 1.15.8.3, som legger til URI-kontrollen.

Portswigger skrev en god artikkel og fikk kommentarer fra OpenResty og Nginx (selv om kommentaren om at bare et lite minnefragment avdekkes, er feil og misvisende, dette bestemmes av lengden av strengen som følger etter nullbyte, og i fravær av eksplisitte lengdebegrensninger kan angriperen kontrollere dette).

Hva var feilen og hva kan gjøres for å forhindre den?

Var det en feil i nginx? Ja, det var det, fordi minneinnhold lekkasje alltid er en feil.

Var det en feil i OpenResty? Ja, i det minste ble ikke sikkerhetsaspektet ved OpenResty-funksjonaliteten undersøkt eller dokumentert.

Ble det gjort en konfigurasjons- / bruksfeil med OpenResty? Ja, fordi i fravær av eksplisitt angivelse, ble det gjort en uverifisert antagelse om sikkerheten til den brukte funksjonaliteten.

Hvilken av disse feilene er en sikkerhetsrisiko med en belønning på $10000? For oss er det i utgangspunktet ikke viktig. I all programvare, spesielt når man kobler sammen flere komponenter, spesielt fra ulike prosjekter og utviklere, kan ingen noen gang garantere at alle funksjonene er kjent og dokumentert og at det ikke finnes feil. Derfor oppstår enhver sikkerhetsrisiko nettopp der det påvirker sikkerheten.

Uansett vil det være en god praksis å normalisere eller maksimalt begrense/filtere inndata som går til et hvilket som helst eksternt modul/API, med mindre det er klare indikasjoner og entydig forståelse for at dette ikke er nødvendig.

Errata

Basert på erfaring den forrige artikkelen, for å bevare språket:

bug bounty — feiljakt konkurranse
feilmelding — feilrapport
redirigering — videresending
åpen kildekode — med åpen kildekode
errata — arbeide med feil

Kilde: habr.com

Kjøp pålitelig hosting for nettsteder med DDoS-beskyttelse, VPS VDS-servere 🔥 Kjøp pålitelig hosting for nettsteder med DDoS-beskyttelse, VPS VDS-servere | ProHoster