
Vuosi sitten, 21. maaliskuuta 2019, Erittäin hyvä tuli HackerOnelle alkaen Kun 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. 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: и Kä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. и 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ä. .
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 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 , joka lisää URI-tarkistuksen.
Portswigger 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 kielen 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
