Noin yksi haavoittuvuus...

Noin yksi haavoittuvuus...

Vuosi sitten, 21, sisään bug bounty -ohjelma Mail.Ru erittäin hyvä tuli HackerOneen virhe raportti alkaen maxarr. Kun yhden HTTP-uudelleenohjauksen palauttaneen webmailin API-pyynnön POST-parametriin lisättiin nollatavu (ASCII 0), uudelleenohjaustiedoissa näkyi alustamattoman muistin paloja, joissa GET-parametreista ja muiden pyyntöjen otsikot sama palvelin.

Tämä on kriittinen haavoittuvuus, koska... pyynnöt sisältävät myös istuntoevästeitä. Muutamaa tuntia myöhemmin tehtiin väliaikainen korjaus, joka suodatti nollatavun (kuten myöhemmin kävi ilmi, tämä ei riittänyt, koska silti oli mahdollisuus pistää CRLF / ASCII 13, 10, jonka avulla voit käsitellä otsikoita ja HTTP-vastauksen tiedot, tämä on vähemmän kriittinen, mutta silti epämiellyttävä). Samalla ongelma siirrettiin tietoturva-analyytikoille ja kehittäjille vian syiden löytämiseksi ja poistamiseksi.

Mail.ru-sähköposti on erittäin monimutkainen sovellus; vastauksen luomiseen voidaan osallistua suuri määrä erilaisia ​​etu-/taustakomponentteja, sekä avoimen lähdekoodin (paljon kiitos kaikille ilmaisten ohjelmistojen kehittäjille) että itse kehitettyjä. Onnistuimme sulkemaan pois kaikki komponentit paitsi nginx ja openresty ja paikallistamaan ongelman ennen soittamista ngx.req.set_uri() OpenResty-komentosarjassa, joka ei toiminut odotetusti (nollatavun tai rivinsyötön lisääminen GET-parametrien kautta engx_http_rewrite_module-moduuliin uudelleenkirjoituksella, jota dokumentaation mukaan käytetään ja jonka pitäisi näyttää toimivan täsmälleen samalla tavalla, ei toimi). Mahdolliset seuraukset eliminoitiin, suodatus lisättiin mahdollisimman tarkasti ja suodatus varmistettiin kaikkien mahdollisten vektoreiden poistamiseksi. Mutta mekanismi, joka johti muistin sisällön vuotamiseen, jäi mysteeriksi. Kuukautta myöhemmin vikailmoitus suljettiin ratkaistuna ja vian syiden analysointi lykättiin parempiin aikoihin.

OpenResty on erittäin suosittu laajennus, jonka avulla voit kirjoittaa Lua-skriptejä nginxin sisällä, ja sitä käytetään useissa Mail.ru-projekteissa, joten ongelmaa ei pidetty ratkaistuna. Ja jonkin ajan kuluttua he lopulta palasivat siihen ymmärtääkseen todelliset syyt, mahdolliset seuraukset ja antaakseen suosituksia kehittäjille. Osallistui lähdekoodin kaivamiseen Denis Denisov и Nikolai Ermishkin. Osoittautui että:

  • Nginxissä, kun käytetään uudelleenkirjoitusta käyttäjätietojen kanssa, joissakin kokoonpanoissa on mahdollisuus hakemiston läpikäyntiin (ja luultavasti SSRF:ään), mutta tämä on tunnettu tosiasia ja staattisten konfigurointianalysaattoreiden pitäisi havaita se Nginx Amplify и gixy Yandexistä (kyllä, käytämme myös sitä, kiitos). OpenRestyä käytettäessä tämä ominaisuus on helppo missata, mutta se ei vaikuttanut kokoonpanoomme.

    kokoonpanoesimerkki:

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

    tulos

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

  • Nginxissä on virhe, joka aiheuttaa muistin vuotamisen, jos uudelleenkirjoitusrivi sisältää nollatavun. Kun uudelleenohjaus annetaan, nginx varaa uuden muistipuskurin, joka vastaa rivin koko pituutta, mutta kopioi rivin sinne rivifunktion kautta, jossa nollatavu on rivin päättäjä, joten rivi kopioidaan vain nollaan asti. tavu; loput puskurista sisältää alustamattomia tietoja. Yksityiskohtainen analyysi löytyy täällä.

    kokoonpanoesimerkki (^@ nolla tavu)

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

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

  • Nginx suojaa GET-parametreja palvelumerkkien lisäämiseltä ja mahdollistaa vain GET-parametrien käytön uudelleenkirjoituksessa. Siksi injektiota ei ole mahdollista hyödyntää käyttäjän ohjaamien parametrien kautta nginxissä. POST-parametreja ei ole suojattu. OpenResty antaa sinun työskennellä sekä GET- että POST-parametrien kanssa, joten kun käytät POST-parametreja OpenResty-palvelun kautta, on mahdollista lisätä erikoismerkkejä.

    kokoonpanoesimerkki:

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

    tulos:

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

Lisäreaktio

Ongelmasta ilmoitettiin nginxin ja OpenResty-kehittäjille, kehittäjät eivät pidä ongelmaa nginxin tietoturvavirheenä, koska itse nginxissä ei ole mitään keinoa hyödyntää virhettä lisäämällä erikoismerkkejä, korjaa muistin paljastaminen julkaistiin 16. joulukuuta. Raportin jälkeisten neljän kuukauden aikana OpenRestyyn ei ole tehty muutoksia, vaikka ymmärrettiin, että ngx.req.set_uri()-funktiosta tarvitaan turvallinen versio. 4 julkaisimme tiedot, 18. OpenResty julkaistiin versio 1.15.8.3, joka lisää URI-vahvistuksen.

Portswigger kirjoitin hyvä artikkeli ja otti kommentit OpenRestyltä ja Nginxiltä (vaikka kommentti, että vain pieni osa muistista on paljastettu, on virheellinen ja harhaanjohtava, tämä määräytyy nollatavua seuraavan rivin pituuden perusteella ja, jos nimenomaisia ​​rajoituksia ei ole pituus, hyökkääjä voi hallita).

Joten mikä oli virhe ja mitä voidaan tehdä sen estämiseksi?

Oliko nginxissä vikaa? Kyllä, se oli, koska muistin sisällön vuotaminen on joka tapauksessa virhe.

Oliko OpenRestyssä virhe? Kyllä, ainakaan OpenRestyn tarjoaman toiminnallisuuden turvallisuutta koskevaa kysymystä ei ole tutkittu ja dokumentoitu.

Oliko OpenRestyssä asetus-/käyttövirhe? Kyllä, koska nimenomaisen lausunnon puuttuessa käytetyn toiminnon turvallisuudesta tehtiin vahvistamaton oletus.

Mikä näistä bugeista on tietoturvahaavoittuvuus ja 10000 XNUMX dollarin palkkio? Meille tämä ei yleensä ole tärkeää. Missään ohjelmistossa, varsinkin useiden komponenttien risteyksessä, erityisesti eri projektien ja kehittäjien toimittamissa, kukaan ei voi koskaan taata, että kaikki heidän työn ominaisuudet ovat tiedossa ja dokumentoituja ja ettei virheitä ole. Siksi kaikki tietoturvahaavoittuvuudet esiintyvät juuri siellä, missä ne vaikuttavat turvallisuuteen.

Joka tapauksessa on hyvä käytäntö normalisoida tai rajoittaa/suodattaa mahdollisimman paljon mihin tahansa ulkoiseen moduuliin/API:hen menevää syöttötietoa, ellei ole olemassa nimenomaisia ​​ohjeita ja selkeää ymmärrystä, että tätä ei vaadita.

painovirhe

Kokemuksesta edellinen artikkeli, kielen puhtauden säilyttämiseksi:

bug bounty - vikojen metsästyskilpailu
virhe raportti - virheilmoitus
uudelleenohjaus - uudelleenohjaus
avoin lähdekoodi - avoin lähdekoodi
virhe - työskentele virheiden parissa

Lähde: will.com

Lisää kommentti