Noin yksi haavoittuvuus...

Noin yksi haavoittuvuus...

Vuosi sitten, 21. maaliskuuta 2019, Mail.Ru-ohjelman bugipalkkio Erittäin hyvä tuli HackerOnelle vikailmoitus alkaen maxarrKun HTTP-uudelleenohjauksen palauttaneen webmail API -pyynnön POST-parametriin lisättiin tyhjä tavu (ASCII 0), uudelleenohjaustiedoissa näkyi alustamattoman muistin paloja, jotka useimmiten paljastivat GET-parametrien osia ja muiden samalle palvelimelle lähetettyjen pyyntöjen otsikoita.

Tämä on kriittinen haavoittuvuus, koska pyynnöt sisältävät istuntoevästeitä. Muutamaa tuntia myöhemmin tehtiin väliaikainen korjaus, joka suodatti pois null-tavun (kuten myöhemmin kävi ilmi, tämä ei riittänyt, koska CRLF/ASCII 13, 10 -injektio oli edelleen mahdollinen, mikä mahdollisti HTTP-vastausotsikoiden ja -datan manipuloinnin. Tämä on vähemmän kriittinen, mutta silti ärsyttävä). Samalla ongelma siirrettiin tietoturva-analyytikoille ja kehittäjille tutkittavaksi ja korjattavaksi virheen perimmäinen syy.

Mail.ru Mail on erittäin monimutkainen sovellus; vastauksen luomiseen voi osallistua suuri määrä erilaisia ​​käyttöliittymän/taustajärjestelmän komponentteja, sekä avoimen lähdekoodin (suuret kiitokset kaikille vapaiden ohjelmistojen kehittäjille) että suljetun lähdekoodin komponentteja. Onnistuimme poistamaan kaikki komponentit paitsi nginx:n ja openrestyn ja eristämään ongelman ennen kuin se edes ilmeni. ngx.req.set_uri() OpenResty-skripti käyttäytyi odottamattomasti (tyhjän tavun tai rivinvaihdon lisääminen GET-parametrien avulla rewrite-komennolla ngx_http_rewrite_module-moduuliin, jota dokumentaation mukaan käytetään ja jonka pitäisi ilmeisesti toimia täsmälleen samalla tavalla, ei toiminut). Mahdollisia seurauksia käsiteltiin, lisättiin mahdollisimman tarkka suodatus ja varmistettiin, että suodatus poisti kaikki mahdolliset vektorit. Mutta muistivuodon aiheuttanut mekanismi pysyi mysteerinä. Kuukautta myöhemmin virheraportti suljettiin ratkaistuna, ja virheen syyn tutkinta lykättiin parempiin aikoihin.

OpenResty on erittäin suosittu lisäosa, jonka avulla voi kirjoittaa Lua-skriptejä Nginxissä, ja sitä käytetään useissa Mail.ru-projekteissa, joten ongelmaa ei pidetty ratkaistuna. Jonkin ajan kuluttua sitä tarkasteltiin lopulta uudelleen, jotta ymmärrettäisiin todelliset syyt ja mahdolliset seuraukset sekä annettaisiin suosituksia kehittäjille. Seuraavat henkilöt osallistuivat lähdekoodin kaivamiseen: Denis Denisov и Nikolay ErmiškinKävi ilmi, että:

  • Nginxissä, kun käytetään käyttäjätietojen uudelleenkirjoitusta, joissakin kokoonpanoissa on mahdollista hakemiston läpikulkua (ja luultavasti SSRF:ää), mutta tämä on tunnettu tosiasia ja staattisten kokoonpanoanalysaattoreiden tulisi havaita se. Nginx-vahvistin и gixy Yandexiltä (kyllä, mekin käytämme sitä, kiitos). Tämä ominaisuus on helppo ohittaa OpenRestyä käytettäessä, mutta se ei vaikuttanut kokoonpanoomme.

    Konfiguraatiosesimerkki:

    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 vika, joka aiheuttaa muistivuodon, jos uudelleenkirjoitusmerkkijono sisältää tyhjän tavun. Uudelleenohjauksen yhteydessä Nginx varaa uuden muistipuskurin, joka vastaa koko merkkijonon pituutta, mutta kopioi merkkijonon siihen merkkijonofunktiolla, jossa tyhjä tavu on merkkijonon päätemerkki. Siksi merkkijono kopioidaan vain tyhjään tavuun asti; loput puskurista sisältää alustamatonta dataa. Yksityiskohtainen analyysi löytyy täältä. täällä.

    Konfiguraatiosesimerkki (^@ null byte)

    
    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 merkkien injektoinnilta ja sallii uudelleenkirjoituksessa vain GET-parametrien käytön. Siksi injektointi käyttäjän ohjaamien parametrien kautta ei ole mahdollista Nginxissä. POST-parametreja ei kuitenkaan suojata. OpenResty tukee sekä GET- että POST-parametreja, joten POST-parametrien käyttö OpenRestyn kautta mahdollistaa erikoismerkkien injektoinnin.

    Konfiguraatiosesimerkki:

    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 OpenRestyn kehittäjille, kehittäjät eivät pidä ongelmaa nginxin tietoturvavirheenä, koska nginxissä itsessään ei ole mahdollista hyödyntää virhettä erikoismerkkien injektoinnilla, korjaus muistin sisällön paljastuminen julkaistiin 16. joulukuuta. Raportin jälkeisten neljän kuukauden aikana OpenResty ei ole tehnyt muutoksia, vaikka ymmärrettiin, että ngx.req.set_uri()-funktiosta tarvittiin suojattu versio. Julkaisimme tiedot 18. maaliskuuta 2020, ja 21. maaliskuuta OpenResty julkaisi versio 1.15.8.3, joka lisää URI-tarkistuksen.

Portswigger kirjoitin hyvä artikkeli ja otin kommentteja OpenRestyltä ja Nginxiltä (vaikka kommentti, jonka mukaan vain pieni osa muistista paljastetaan, on virheellinen ja harhaanjohtava, tämä määräytyy tyhjän tavun jälkeisen merkkijonon pituuden mukaan ja hyökkääjä voi hallita sitä, jos pituudelle ei ole asetettu nimenomaisia ​​rajoituksia).

Mikä siis oli virhe ja mitä sen estämiseksi voisi tehdä?

Oliko nginxissä bugi? Kyllä, sellainen oli, koska muistivuoto on joka tapauksessa virhe.

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

Oliko OpenRestyssä määritys-/käyttövirhe? Kyllä, koska nimenomaisen ohjeistuksen puuttuessa tehtiin vahvistamaton oletus käytetyn toiminnallisuuden turvallisuudesta.

Mikä näistä bugeista on 10 000 dollarin palkkiolla lunastettava tietoturvahaavoittuvuus? Meille tämä ei ole kovin tärkeää. Missään ohjelmistossa, varsinkaan useiden komponenttien yhtymäkohdissa, etenkin eri projektien ja kehittäjien toimittamissa, kukaan ei voi koskaan taata, että kaikki niiden toiminnan yksityiskohdat tunnetaan ja dokumentoidaan, eikä virheitä esiinny. Siksi kaikki tietoturvahaavoittuvuudet syntyvät juuri siellä, missä ne vaikuttavat tietoturvaan.

Joka tapauksessa on hyvä käytäntö normalisoida tai rajoittaa/suodattaa mahdollisimman paljon ulkoiseen moduuliin/APIin menevää syöttödataa, ellei ole olemassa nimenomaisia ​​ohjeita ja selkeää ymmärrystä siitä, ettei tätä vaadita.

painovirhe

Kokemuksesta edellinen artikkelikielen puhtauden säilyttämiseksi:

bug bounty - hyönteistenmetsästyskilpailu
vikailmoitus — virheilmoitus
uudelleenohjaus - uudelleenohjaus
avoin lähdekoodi - avoimen lähdekoodin
virhe - työskentele virheiden parissa

Lähde: will.com

Osta luotettava isännöinti sivustoille, joissa on DDoS-suojaus, VPS VDS -palvelimet 🔥 Osta luotettavaa verkkosivustojen hostingia DDoS-suojauksella, VPS VDS -palvelimilla | ProHoster