
För ett Är sedan, den 21 mars 2019, i on HackerOne kom det en mycket bra frÄn . Vid införandet av null-byte (ASCII 0) i POST-parametern för en av API-frÄgorna frÄn webbmailen, som returnerade en HTTP-omdirigering, sÄgs bitar av icke initierat minne dÀr fragment frÄn GET-parametrar och huvuden frÄn andra förfrÄgningar till samma server oftast visades.
Detta Àr en kritisk sÄrbarhet, dÄ förfrÄgningarna Àven innehÄller sessionscookies. Inom nÄgra timmar gjordes en temporÀr fix som filtrerade bort null-byte (som det senare visade sig var otillrÀckligt, eftersom möjligheten till CRLF/ASCII 13, 10-injektion fortfarande kvarstod, vilket möjliggör manipulation av huvud och data i HTTP-svaret, nÄgot som Àr mindre kritiskt men fortfarande obehagligt). Samtidigt överlÀmnades problemet till sÀkerhetsanalytiker och utvecklare för att hitta och ÄtgÀrda orsakerna till buggen.
Mail.ru:s e-post Àr en mycket komplex applikation dÀr mÄnga olika frontend/backend-komponenter kan vara involverade, bÄde öppen kÀllkod (stort tack till alla utvecklare av fri programvara) och egna utvecklingar. Det lyckades utesluta alla komponenter förutom nginx och openresty och lokalisera problemet till anropet i OpenResty-skriptet, som inte fungerade som förvÀntat (att införa null-byte eller radbyte via GET-parametrar med omskrivning i ngx_http_rewrite_module, som enligt dokumentationen anvÀnds och som borde fungera helt likadant, gick inte). Eventuella konsekvenser har ÄtgÀrdats, strikt filtrering har lagts till och det har kontrollerats att filtreringen eliminerar alla möjliga vektorer. Men mekanismen som ledde till lÀckage av minnesinnehÄll förblev en gÄta. Efter en mÄnad stÀngdes buggrapporten som löst, medan analysen av orsaken till buggen sköts upp till bÀttre tider.
OpenResty Àr en mycket populÀr plugin som möjliggör skrivande av Lua-skript inuti nginx, och den anvÀnds i flera projekt av Mail.ru, sÄ problemet ansÄgs inte vara löst. Och efter en tid Äterkom man till det för att förstÄ de verkliga orsakerna, möjliga konsekvenser och skapa rekommendationer för utvecklarna. I granskningen av kÀllkoden deltog och . Det har visat sig att:
- I nginx, vid anvÀndning av rewrite med anvÀndardata, finns det en möjlighet för directory traversal (och sannolikt SSRF) i vissa konfigurationer, men detta Àr en kÀnd frÄga och bör upptÀckas av statiska konfigurationsanalysatorer i och frÄn Yandex (ja, vi anvÀnder det ocksÄ, tack). Vid anvÀndning av OpenResty kan denna möjlighet lÀtt missas, men vÄr konfiguration pÄverkades inte.
exempelkonfiguration:
location ~ /rewrite { rewrite ^.*$ $arg_x; } location / { root html; index index.html index.htm; }resultatet
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
... - I nginx finns det ett fel som leder till minneslÀckage om rewrite-strÀngen innehÄller en null-byte. Vid omdirigering allokerar nginx en ny minnesbuffer som motsvarar hela lÀngden pÄ strÀngen, men kopierar strÀngen med en strÀngfunktion dÀr null-byte Àr terminatorn för strÀngen, vilket gör att strÀngen endast kopieras fram till null-byte, resten av buffern innehÄller oinitialiserade data. En detaljerad analys kan hittas .
exempelkonfiguration (^@ null-byte)
location ~ /memleak { rewrite ^.*$ "^@asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdasdf"; } location / { root html; index index.html index.htm; }resultatet
curl localhost:8337/secret -vv
...
curl localhost:8337/memleak -vv
...
Location: http://localhost:8337/secret
...
- Nginx skyddar GET-parametrar frÄn injektion av kontrolltecken och ger möjlighet att anvÀnda i rewrite endast GET-parametrar. DÀrför Àr det inte möjligt att utnyttja injektion genom kontrollerade anvÀndarparametrar i nginx. POST-parametrar Àr dock inte skyddade. OpenResty tillÄter arbete med bÄde GET och POST-parametrar, sÄ vid anvÀndning av POST-parametrar genom OpenResty uppstÄr möjligheten för injektion av specialtecken.
exempelkonfiguration:
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; }resultat:
curl localhost:8337 -d "url=hemlig" -vv
...
curl localhost:8337 -d "url=asdfasdfasdfasdfasdfasdfasdfasdf" -vv
...
Plats: http://localhost:8337/{...kan innehÄlla hemlig...}
...
Vidare ÄtgÀrder
Problemet har rapporterats till utvecklarna av nginx och OpenResty, utvecklarna betraktar inte problemet som en sÀkerhetsbrist i nginx, eftersom det inte finns nÄgon möjlighet att utnyttja felet genom injektion av specialtecken; fix publicerades den 16 december. Under de fyra mÄnader som gÄtt sedan rapporteringen har det inte heller skett nÄgra förÀndringar i OpenResty, trots förstÄelse för att en sÀker version av funktionen ngx.req.set_uri() var nödvÀndig. Den 18 mars 2020 publicerade vi information, den 21 mars slÀppte OpenResty , som lÀgger till kontroller av URI.
Portswigger en bra artikel och tog kommentarer frÄn OpenResty och Nginx (Àven om kommentaren om att endast en liten del av minnet avslöjas Àr felaktig och missledande, detta bestÀms av lÀngden pÄ strÀngen som följer nollbyte och, i avsaknad av uppenbara begrÀnsningar av lÀngden, kan kontrolleras av en angripare).
Vad var felet och vad gör vi för att förhindra det?
Var felet i nginx? Ja, det var det, eftersom en minneslÀcka i alla avseenden Àr ett fel.
Var det fel i OpenResty? Ja, minst sagt var frÄgan om sÀkerheten i den funktionalitet som erbjuds av OpenResty inte undersökt och dokumenterad.
Var det en konfigurations-/anvÀndarfel i OpenResty? Ja, eftersom i avsaknad av ett uttryckligt angivet, gjordes en obekrÀftad antagelse om sÀkerheten i den anvÀnda funktionaliteten.
Vilket av dessa fel Àr en sÀkerhetsrisk med en bountykostnad pÄ $10000? För oss spelar det i stort sett ingen roll. I all mjukvara, sÀrskilt i skÀrningspunkten av flera komponenter, sÀrskilt som tillhandahÄlls av olika projekt och utvecklare, kan ingen och aldrig garantera att alla aspekter av deras arbete Àr kÀnda och dokumenterade och att det inte finns nÄgra fel. DÀrför uppstÄr varje sÀkerhetsrisk precis dÀr den pÄverkar sÀkerheten.
I alla fall, det Àr en bra praxis att normalisera eller maximalt begrÀnsa/filtera indata som gÄr till nÄgon extern modul/API, om det inte finns nÄgra tydliga riktlinjer och en entydig förstÄelse av att det inte behövs.
Errata
Enligt erfarenhet , för att bevara sprÄkets renhet:
bug bounty â en tĂ€vling för att upptĂ€cka fel
bugrapport â felanmĂ€lan
redirect â omdirigering
öppen kĂ€llkod â med öppen kĂ€llkod
errata â arbete med fel
KĂ€lla: habr.com
