O jednoj ranjivosti u…

O jednoj ranjivosti u…

Prije godinu dana, 21. marta 2019. godine, u bug bounty program Mail.Ru jedan veoma dobar je došao u HackerOne izvještaj o grešci iz maxarr. Prilikom uvođenja nultog bajta (ASCII 0) u POST parametar jednog od zahtjeva API-ja web pošte koji je vratio HTTP preusmjeravanje, dijelovi neinicijalizirane memorije bili su vidljivi u podacima za preusmjeravanje, u kojima su fragmenti iz GET parametara i zaglavlja drugih zahtjeva na isti server.

Ovo je kritična ranjivost jer... zahtjevi također sadrže kolačiće sesije. Nekoliko sati kasnije, napravljena je privremena popravka koja je filtrirala nulti bajt (kako se kasnije ispostavilo, to nije bilo dovoljno, jer je i dalje postojala mogućnost ubrizgavanja CRLF / ASCII 13, 10, što vam omogućava da manipulišete zaglavljima i podataka HTTP odgovora, ovo je manje kritično, ali ipak neugodno). Istovremeno, problem je prebačen na bezbednosne analitičare i programere kako bi pronašli i eliminisali uzroke greške.

Mail.ru mail je vrlo složena aplikacija; veliki broj različitih front-end/back-end komponenti, kako otvorenog koda (veliko hvala svim programerima besplatnog softvera) tako i in-house razvijenih, može biti uključen u generiranje odgovora. Uspjeli smo isključiti sve komponente osim nginxa i openrestyja i lokalizirati problem prije poziva ngx.req.set_uri() u OpenResty skripti koja se nije ponašala kako se očekivalo (ubacivanje null bajta ili feeda linije preko GET parametara sa prepisivanjem u ngx_http_rewrite_module, koji se, prema dokumentaciji, koristi i, čini se, trebao bi raditi na potpuno isti način, ne radi). Moguće posljedice su eliminirane, filtriranje je dodano što je moguće strože, a filtriranje je provjereno kako bi se eliminisali svi mogući vektori. Ali mehanizam koji je doveo do curenja memorijskog sadržaja ostao je misterija. Mjesec dana kasnije izvještaj o grešci je zatvoren kao riješen, a analiza uzroka greške je odložena za bolja vremena.

OpenResty je vrlo popularan dodatak koji vam omogućava da pišete Lua skripte unutar nginxa, a koristi se u nekoliko Mail.ru projekata, tako da se problem nije smatrao riješenim. I nakon nekog vremena, konačno su se vratili tome kako bi shvatili prave razloge, moguće posljedice i dali preporuke za programere. Učestvovao u iskopavanju izvornog koda Denis Denisov и Nikolay Ermishkin. Ispostavilo se da:

  • U nginx-u, kada se koristi prepisivanje sa korisničkim podacima, postoji mogućnost obilaženja direktorijuma (i vjerovatno SSRF) u nekim konfiguracijama, ali to je poznata činjenica i trebalo bi da je detektuju statički analizatori konfiguracije u Nginx Amplify и gixy sa Yandexa (da, i mi to koristimo, hvala). Kada koristite OpenResty, ovu funkciju je lako propustiti, ali to nije uticalo na našu konfiguraciju.

    primjer konfiguracije:

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

    efekat

    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 ima grešku koja uzrokuje curenje memorije ako linija za ponovno upisivanje sadrži null bajt. Kada se izda preusmjeravanje, nginx dodjeljuje novi memorijski bafer koji odgovara punoj dužini linije, ali tamo kopira liniju kroz funkciju linije u kojoj je nulti bajt terminator linije, tako da se linija kopira samo do nule bajt; ostatak bafera sadrži neinicijalizirane podatke. Detaljnu analizu možete pronaći ovdje.

    primjer konfiguracije (^@ nula bajtova)

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

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

  • Nginx štiti GET parametre od ubrizgavanja servisnih znakova i omogućava korištenje samo GET parametara u ponovnom pisanju. Stoga nije moguće iskoristiti injekciju kroz parametre koje kontrolira korisnik u nginxu. POST parametri nisu zaštićeni. OpenResty vam omogućava da radite i sa GET i sa POST parametrima, tako da kada koristite POST parametre kroz OpenResty, postaje moguće ubaciti posebne znakove.

    primjer konfiguracije:

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

    rezultat:

    curl localhost:8337 -d "url=secret" -vv
    ...
    curl localhost:8337 -d "url=%00asdfasdfasdfasdfasdfasdfasdfasdf" -vv
    ...
    Location: http://localhost:8337/{...может содержать secret...}
    ...

Dalja reakcija

Problem je prijavljen programerima nginx-a i OpenResty-a, programeri ne smatraju problem sigurnosnim bugom u nginx-u, jer u samom nginx-u ne postoji način da se greška iskoristi kroz ubacivanje specijalnih znakova, popravi otkrivanje memorije objavljena je 16. decembra. U 4 mjeseca od izvještaja nisu napravljene nikakve promjene u OpenRestyju, iako je postojalo razumijevanje da je potrebna sigurna verzija funkcije ngx.req.set_uri(). 18. marta 2020. objavili smo informaciju, 21. marta objavljen OpenResty verzija 1.15.8.3, što dodaje URI validaciju.

Portswigger napisao je dobar članak i preuzete komentare od OpenResty i Nginx (iako je komentar da je izložen samo mali fragment memorije netačan i obmanjujući, to je određeno dužinom reda nakon nul bajta i, u nedostatku eksplicitnih ograničenja na dužinu, napadač može kontrolisati).

Dakle, u čemu je bila greška i šta se može učiniti da se to spreči?

Da li je postojala greška u nginxu? Da, bilo je, jer curenje memorijskog sadržaja je greška u svakom slučaju.

Da li je postojala greška u OpenRestyju? Da, barem pitanje sigurnosti funkcionalnosti koje nudi OpenResty nije istraženo i dokumentovano.

Da li je došlo do greške u konfiguraciji/korišćenju sa OpenResty? Da, jer je u nedostatku eksplicitne izjave napravljena neprovjerena pretpostavka o sigurnosti funkcionalnosti koja se koristi.

Koja od ovih grešaka je sigurnosna ranjivost sa nagradom od 10000 dolara? Za nas to generalno nije važno. U bilo kom softveru, posebno na raskrsnici nekoliko komponenti, posebno onih koje su dali različiti projekti i programeri, niko nikada ne može garantovati da su sve karakteristike njihovog rada poznate i dokumentovane i da nema grešaka. Stoga se svaka sigurnosna ranjivost javlja upravo tamo gdje utiče na sigurnost.

U svakom slučaju, dobra je praksa normalizirati ili ograničiti/filtrirati što je više moguće ulazne podatke koji ulaze u bilo koji vanjski modul/API, osim ako ne postoje eksplicitne upute i jasno razumijevanje da to nije potrebno.

Greška

Iskustvom prethodni članak, radi očuvanja čistoće jezika:

bug bounty — takmičenje u lovu na bube
izvještaj o grešci - obavještenje o grešci
preusmjeravanje - preusmjeravanje
open source - open source
erratum - rad na greškama

izvor: www.habr.com

Dodajte komentar