
Prije godinu dana, 21. ožujka 2019., u jedan vrlo dobar došao je u HackerOne iz . Prilikom uvođenja nultog bajta (ASCII 0) u POST parametar jednog od API zahtjeva web pošte koji je vratio HTTP preusmjeravanje, dijelovi neinicijalizirane memorije bili su vidljivi u podacima preusmjeravanja, u kojima su fragmenti iz GET parametara i zaglavlja drugih zahtjeva prema isti server.
Ovo je kritična ranjivost jer... zahtjevi također sadrže kolačiće sesije. Nekoliko sati kasnije napravljen je privremeni popravak koji je filtrirao nulti bajt (kako se kasnije pokazalo, to nije bilo dovoljno, jer je još uvijek postojala mogućnost ubacivanja CRLF / ASCII 13, 10, što vam omogućuje manipuliranje zaglavljima i podataka HTTP odgovora, ovo je manje kritično, ali još uvijek neugodno). Istodobno, problem je prebačen na sigurnosne analitičare i programere kako bi pronašli i otklonili uzroke buga.
Mail.ru mail je vrlo složena aplikacija; velik broj različitih front-end/back-end komponenti, kako otvorenog koda (veliko hvala svim programerima besplatnog softvera), tako i interno razvijenih, može biti uključen u generiranje odgovora. Uspjeli smo isključiti sve komponente osim nginxa i openrestyja i lokalizirati problem prije poziva u OpenResty skripti koja se nije ponašala kako se očekivalo (umetanje null byte ili line feed putem GET parametara s rewrite u ngx_http_rewrite_module, koji se, prema dokumentaciji, koristi i, čini se, trebao bi raditi na potpuno isti način, će ne rade). Moguće posljedice su eliminirane, filtriranje je dodano što je moguće strože, a filtriranje je provjereno kako bi se eliminirali svi mogući vektori. No mehanizam koji je doveo do curenja sadržaja memorije ostao je misterij. Mjesec dana kasnije, izvještaj o grešci je zatvoren kao riješen, a analiza uzroka greške odgođena je za bolja vremena.
OpenResty je vrlo popularan dodatak koji vam omogućuje pisanje Lua skripti 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 razumjeli prave razloge, moguće posljedice i dali preporuke programerima. Sudjelovao u iskapanju izvornog koda и . Ispostavilo se da:
- U nginxu, kada se koristi prepisivanje s korisničkim podacima, postoji mogućnost obilaženja direktorija (i vjerojatno SSRF-a) u nekim konfiguracijama, ali to je poznata činjenica i trebali bi je otkriti analizatori statičke konfiguracije u и s Yandexa (da, i mi to koristimo, hvala). Kada koristite OpenResty, ovu značajku je lako propustiti, ali to nije utjecalo na našu konfiguraciju.
primjer konfiguracije:
location ~ /rewrite { rewrite ^.*$ $arg_x; } location / { root html; index index.html index.htm; }rezultirati
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 redak za ponovno pisanje sadrži nulti bajt. Kada se izda preusmjeravanje, nginx dodjeljuje novi memorijski međuspremnik koji odgovara punoj duljini retka, ali kopira redak tamo kroz funkciju retka u kojoj je nulti bajt krajnik retka, tako da se redak kopira samo do nule. bajt; ostatak međuspremnika sadrži neinicijalizirane podatke. Detaljnu analizu možete pronaći .
primjer konfiguracije (^@ nula bajta)
location ~ /memleak { rewrite ^.*$ "^@asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdasdf"; } location / { root html; index index.html index.htm; }rezultirati
curl localhost:8337/secret -vv
...
curl localhost:8337/memleak -vv
...
Location: http://localhost:8337/secret
...
- Nginx štiti GET parametre od ubacivanja servisnih znakova i omogućuje korištenje samo GET parametara u prepisivanju. Stoga nije moguće iskoristiti ubrizgavanje putem parametara koje kontrolira korisnik u nginxu. POST parametri nisu zaštićeni. OpenResty vam omogućuje rad s GET i 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; }proizlaziti:
curl localhost:8337 -d "url=secret" -vv
...
curl localhost:8337 -d "url=%00asdfasdfasdfasdfasdfasdfasdfasdf" -vv
...
Location: http://localhost:8337/{...может содержать secret...}
...
Daljnja reakcija
Problem je prijavljen programerima nginxa i OpenRestyja, programeri ne smatraju problem sigurnosnom greškom u nginxu, jer u samom nginxu ne postoji način da se greška iskoristi kroz ubacivanje posebnih znakova, popravi objavljen je 16. prosinca. U 4 mjeseca od izvješća nisu napravljene promjene u OpenRestyju, iako je postojalo razumijevanje da je potrebna sigurna verzija funkcije ngx.req.set_uri(). 18. ožujka 2020. objavili smo informaciju, 21. ožujka objavljen je OpenResty , koji dodaje URI provjeru valjanosti.
Portswigger dobar članak i uzeo komentare od OpenResty i Nginx (iako je komentar da je izložen samo mali fragment memorije netočan i obmanjujući, to je određeno duljinom retka koji slijedi nulti bajt i, u nedostatku izričitih ograničenja na duljina, koju može kontrolirati napadač).
Dakle, u čemu je bila pogreška i što se može učiniti da se to spriječi?
Je li bilo greške u nginxu? Da, bilo je, jer curenje sadržaja memorije je greška u svakom slučaju.
Je li bilo greške u OpenRestyju? Da, barem pitanje sigurnosti funkcionalnosti koju nudi OpenResty nije istraženo i dokumentirano.
Je li došlo do pogreške konfiguracije/korištenja s OpenResty? Da, jer je u nedostatku izričite izjave napravljena neprovjerena pretpostavka o sigurnosti funkcionalnosti koja se koristi.
Koji je od ovih bugova sigurnosna ranjivost s nagradom od 10000 USD? Za nas to uglavnom nije važno. U bilo kojem softveru, posebno na sjecištu nekoliko komponenti, posebno onih koje pružaju različiti projekti i programeri, nitko nikada ne može jamčiti da su sve značajke njihova rada poznate i dokumentirane te da nema grešaka. Stoga se svaka sigurnosna ranjivost javlja upravo tamo gdje utječ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 izričite upute i jasno razumijevanje da to nije potrebno.
tiskarske pogreške
Iz iskustva , radi očuvanja čistoće jezika:
nagrada za bube — natjecanje u lovu na bube
izvješće o grešci - obavijest o grešci
preusmjeriti - preusmjeravanje
otvoreni izvor - otvoreni izvor
errata - rad na greškama
Izvor: www.habr.com
