Rreth njĂ« dobĂ«sie në 

Rreth njĂ« dobĂ«sie në 

Një vit më parë, më 21 mars 2019, në programin e keqësisë Mail.Ru në HackerOne erdhi një raport shumë i mirë raportin e gabimit nga maxarr. Në integrimin e byte-zero (ASCII 0) në parametrin POST të një prej API kërkesave të web-mail, e cila kthente një HTTP-redirect, në të dhënat e redirect kishin pjesë të kujtesës të pa inicializuar, ku shpesh shfaqeshin fragmente nga parametrat GET dhe kokat e kërkesave të tjera për të njëjtin server.

Kjo është një dobësi kritike, pasi kërkesat përfshijnë gjithashtu cookie-t e sesionit. Pas disa orësh, u bë një rregullim provisional, i cili filtroi byte-zero (siç u zbulua më vonë, kjo ishte e pamjaftueshme, pasi mbetej mundësia e injeksionit CRLF / ASCII 13, 10, e cila lejonte manipulimin e kokave dhe të dhënave të përgjigjeve HTTP, kjo është më pak kritike, por akoma e pakëndshme). Njëkohësisht, problemi iu kalua analistëve të sigurisë dhe zhvilluesve për të kërkuar dhe zgjidhur shkakun e shfaqjes së defektit.

Mail.ru është një aplikacion shumë kompleks, në formimin e përgjigjes mund të përfshihen një numër i madh komponentësh të ndryshëm frontend/backend, si komponentë open-source (faleminderit shumë të gjithë zhvilluesve të softuerit të lirë), ashtu edhe zhvillime të brendshme. Mundëm të përjashtojmë të gjithë komponentët përveç nginx dhe openresty dhe të lokalizojmë problemin deri te thirrja ngx.req.set_uri() në skriptin OpenResty, i cili vepronte ndryshe nga sa pritej (nuk është e mundur të vendosësh byte-zero ose ndërrim rreshti përmes parametrave GET me rewrite në ngx_http_rewrite_module, i cili, sipas dokumentacionit, përdoret dhe, duket se, duhet të funksionojë absolutisht në mënyrë të ngjashme). U eliminuan pasojat e mundshme, u shtua filtrimi më i ashpër dhe u verifikua që filtrimi eliminon të gjitha vektorët e mundshëm. Por mekanizmi që çonte në rrjedhjen e përmbajtjes së memorieve ka mbetur enigmë. Pas një muaji, raporti i defektit u mbyll si i zgjidhur, ndërsa analiza e shkakut të shfaqjes së defektit u shty për kohë më të mira.

OpenResty Ă«shtĂ« njĂ« plugin shumĂ« popullor qĂ« lejon shkruarjen e skripteve Lua brenda nginx, dhe ai pĂ«rdoret nĂ« disa projekte tĂ« Mail.ru, kĂ«shtu qĂ« problemi nuk u konsiderua i zgjidhur. Dhe pas njĂ« kohe, ata u kthyen pĂ«rsĂ«ri pĂ«r ta kuptuar shkakun e vĂ«rtetĂ«, pasojat e mundshme dhe pĂ«r tĂ« pĂ«rgatitur rekomandime pĂ«r zhvilluesit. NĂ« gĂ«rmadhat e kodit burimor morĂ«n pjesĂ« Denis Denisov dhe Nikolai ErmißkinU zbulua se:

  • NĂ« nginx, kur pĂ«rdoret rewrite me tĂ« dhĂ«na tĂ« personalizuara, ka mundĂ«sinĂ« pĂ«r directory traversal (dhe ndoshta SSRF) nĂ« disa konfigurime, por kjo Ă«shtĂ« njĂ« fakt i njohur dhe duhet tĂ« zbulohet nga analizatorĂ«t statikĂ« tĂ« konfigurimeve nĂ« Nginx Amplify dhe Gixy nga Yandex (po, ne gjithashtu e pĂ«rdorim atĂ«, faleminderit). Kur pĂ«rdoret OpenResty, kjo mundĂ«si mund tĂ« kalojĂ« lehtĂ«, por konfigurimi ynĂ« nuk ishte prekur.

    shembulli i konfigurimit:

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

    rezultatin

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

  • NĂ« nginx ka njĂ« gabim qĂ« çon nĂ« rrjedhjen e pĂ«rmbajtjes sĂ« memories nĂ«se stringu rewrite pĂ«rmban njĂ« byte zero. Kur nginx jep njĂ« redirect, ai alokon njĂ« tampon tĂ« ri memory qĂ« i pĂ«rgjigjet gjatĂ«si totale tĂ« stringut, por e kopjon atĂ« pĂ«rmes njĂ« funksioni string, nĂ« tĂ« cilin byte zero Ă«shtĂ« terminatori i stringut, kĂ«shtu qĂ« stringu kopjohet vetĂ«m deri nĂ« byte zero, pjesa tjetĂ«r e tamponit pĂ«rmban tĂ« dhĂ«na tĂ« pa inicializuara. Mund tĂ« gjeni njĂ« analizĂ« tĂ« detajuar kĂ«tu.

    shembulli i konfigurimit (^@ byte zero)

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

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

  • Nginx mbron parametrat GET nga injeksioni i simboleve tĂ« veçanta dhe jep mundĂ«sinĂ« pĂ«r tĂ« pĂ«rdorur nĂ« rewrite vetĂ«m parametrat GET. Prandaj, nuk Ă«shtĂ« e mundur tĂ« shfrytĂ«zohet injeksioni pĂ«rmes parametrave tĂ« kontrolluar nga pĂ«rdoruesi nĂ« nginx. Parametrat POST, nga ana tjetĂ«r, nuk janĂ« tĂ« mbrojtur. OpenResty lejon punĂ«n me parametrat si GET ashtu edhe POST, kĂ«shtu qĂ« kur pĂ«rdoren parametrat POST pĂ«rmes OpenResty, krijohet mundĂ«sia pĂ«r injeksion tĂ« simboleve tĂ« veçanta.

    shembulli i konfigurimit:

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

    rezultati:

    curl localhost:8337 -d "url=secret" -vv
    ...
    curl localhost:8337 -d "url=asdfasdfasdfasdfasdfasdfasdfasdf" -vv
    ...
    Location: http://localhost:8337/{...mund mund të përmbajë secret...}
    ...

Reagimi i mëtejshëm

Problemi iu raportua zhvilluesve të nginx dhe OpenResty, dhe zhvilluesit nuk e konsiderojnë problemin si një gabim sigurie në nginx, pasi në vetë nginx nuk ka mundësi për shfrytëzimin e gabimit përmes injeksionit të simboleve speciale, rregullimi i zbuluar i përmbajtjes së memories u publikua më 16 dhjetor. Për 4 muaj që nga raportimi në OpenResty nuk ishin bërë asnjë ndryshim, edhe pse kishte një kuptim se ishte e nevojshme një variant i sigurt i funksionit ngx.req.set_uri(). Në 18 mars 2020, ne publikuan informacionin, më 21 mars OpenResty lëshoi versionin 1.15.8.3, i cili shton një kontroll të URI.

Portswigger shkroi Një artikull të mirë dhe mora komente nga OpenResty dhe Nginx (pavarësisht se komenti për faktin se zbulon vetëm një fragment të vogël të memories është i pasaktë dhe i shpif, kjo përcaktohet nga gjatësi e vargut që vjen pas bajtit të zeros dhe, në mungesë të kufizimeve të qarta për gjatësi, mund të kontrollohet nga sulmuesi).

Cila ishte gabimi dhe çfarë duhet bërë për ta parandaluar atë?

A ishte gabimi në nginx? Po, ishte, sepse rrjedhja e përmbajtjes së memories është një gabim në çdo rast.

A kishte gabim në OpenResty? Po, së paku nuk ishte hetuar dhe dokumentuar çështja e sigurisë së funksionalitetit që ofron OpenResty.

A ishte bërë një gabim konfigurimi / përdorimi të OpenResty? Po, sepse në mungesë të një tregimi të qartë, ishte bërë një supozim i pandërprerë mbi sigurinë e funksionalitetit të përdorur.

Cila nga këto gabime është një vulnerabilitet i sigurisë me bounty prej $10000? Për ne, në përgjithësi, nuk ka rëndësi. Në çdo program të softuerit, veçanërisht në kufirin e disa komponentëve, veçanërisht të ofruara nga projekte dhe zhvillues të ndryshëm, askush dhe kurrë nuk mund të garantojë se të gjitha veçoritë e funksionimit të tyre janë të njohura dhe të dokumentuara dhe se nuk ka gabime. Prandaj, çdo vulnerabilitet i sigurisë lind pikërisht aty ku ndikon në siguri.

Në çdo rast, një praktikë e mirë do të ishte të normalizosh ose të kufizosh / filtrosh sa më shumë që të jetë e mundur të dhënat hyrëse që shkojnë në çdo modul / API të jashtëm, nëse nuk ka tregime të qarta dhe një kuptim të qartë se kjo nuk është e nevojshme.

Errata

Nga eksperienca artikulli i mëparshëm, për ruajtjen e pastërtisë së gjuhës:

bug bounty — njĂ« garĂ« pĂ«r gjetjen e gabimeve
raportin e gabimit — njoftim pĂ«r gabim
redirect — ridrejtim
me burim tĂ« hapur — me kod tĂ« hapur
errata — punĂ« mbi gabime

Burimi: habr.com

Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS đŸ”„ Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS | ProHoster