Pri unu vundebleco en...

Pri unu vundebleco en...

Antaŭ unu jaro, la 21-an de marto 2019, en cimo-premioprogramo Mail.Ru tre bona venis al HackerOne cimraporto el maxarr. Kiam oni enkondukis nul bajton (ASCII 0) en la POST-parametron de unu el la retpoŝtaj API-petoj, kiuj resendis HTTP-redirektilon, pecoj de neinicialigita memoro estis videblaj en la alidirektilaj datumoj, en kiuj fragmentoj de GET-parametroj kaj kapoj de aliaj petoj al la sama servilo.

Ĉi tio estas kritika vundebleco ĉar... petoj ankaŭ enhavas sesiajn kuketojn. Kelkajn horojn poste, provizora riparo estis farita, kiu filtris la nulan bajton (kiel montriĝis poste, tio ne sufiĉis, ĉar ankoraŭ ekzistis la ebleco injekti CRLF / ASCII 13, 10, kiu ebligas manipuli la kapliniojn kaj datumoj de la HTTP-respondo, ĉi tio estas malpli kritika, sed ankoraŭ malagrabla). Samtempe, la problemo estis transdonita al sekurecaj analizistoj kaj programistoj por trovi kaj forigi la kaŭzojn de la cimo.

Mail.ru-poŝto estas tre kompleksa aplikaĵo; granda nombro da malsamaj antaŭfinaj/malantaŭaj komponentoj, kaj malfermfonte (multe danke al ĉiuj liberprogramaraj programistoj) kaj endome evoluigitaj, povas esti implikitaj en generado de la respondo. Ni sukcesis ekskludi ĉiujn komponantojn krom nginx kaj openresty kaj lokalizi la problemon antaŭ ol voki ngx.req.set_uri() en OpenResty-skripto kiu ne kondutis kiel atendite (enmetante nulan bajton aŭ liniofluon per GET-parametroj kun reverkado en ngx_http_rewrite_module, kiu, laŭ la dokumentado, estas uzata kaj, ŝajne, devus funkcii ĝuste en la sama maniero, ne funkcias). Eblaj sekvoj estis eliminitaj, filtrado estis aldonita kiel eble plej strikte, kaj filtrado estis kontrolita por forigi ĉiujn eblajn vektorojn. Sed la mekanismo kiu kondukis al la liko de memorenhavo restis mistero. Monaton poste, la cimraporto estis fermita kiel solvita, kaj la analizo de la kaŭzoj de la cimo estis prokrastita ĝis pli bonaj tempoj.

OpenResty estas tre populara kromaĵo, kiu permesas vin skribi Lua-skriptojn ene de nginx, kaj ĝi estas uzata en pluraj Mail.ru-projektoj, do la problemo ne estis konsiderata solvita. Kaj post iom da tempo, ili finfine revenis al ĝi por kompreni la verajn kialojn, eblajn konsekvencojn kaj fari rekomendojn por programistoj. Partoprenis en la elfosado de la fontkodo Denis Denisov и Nikolao Ermiŝkin. Montriĝis ke:

  • En nginx, kiam oni uzas reverki kun uzantdatenoj, ekzistas la ebleco de dosierujo-trapaso (kaj verŝajne SSRF) en iuj agordoj, sed ĉi tio estas konata fakto kaj devus esti detektita de statikaj agordaj analiziloj en Nginx Amplifi и gixy de Yandex (jes, ni uzas ankaŭ tion, dankon). Kiam vi uzas OpenResty, ĉi tiu funkcio estas facile maltrafi, sed tio ne influis nian agordon.

    ekzemplo de agordo:

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

    efekto

    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 havas cimon, kiu igas memoron liki se la reverka linio enhavas nulan bajton. Kiam alidirektilo estas elsendita, nginx asignas novan memorbufron respondan al la tuta longo de la linio, sed kopias la linion tie per liniofunkcio en kiu la nula bajto estas linia finaĵo, do la linio estas kopiita nur ĝis la nulo. bajto; la resto de la bufro enhavas neinicialigitajn datenojn. Detala analizo troveblas tie.

    agorda ekzemplo (^@ nul bajto)

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

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

  • Nginx protektas GET-parametrojn kontraŭ injekto de servaj signoj kaj ebligas uzi nur GET-parametrojn en reverko. Tial, ne eblas ekspluati injekton per uzant-kontrolitaj parametroj en nginx. POST-parametroj ne estas protektitaj. OpenResty ebligas al vi labori kun kaj GET kaj POST-parametroj, do kiam vi uzas POST-parametrojn per OpenResty, eblas injekti specialajn signojn.

    ekzemplo de agordo:

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

    rezulto:

    curl localhost:8337 -d "url=secret" -vv
    ...
    curl localhost:8337 -d "url=%00asdfasdfasdfasdfasdfasdfasdfasdf" -vv
    ...
    Location: http://localhost:8337/{...может содержать secret...}
    ...

Plia reago

La problemo estis raportita al la programistoj de nginx kaj OpenResty, la programistoj ne konsideras la problemon kiel sekurecan cimon en nginx, ĉar en nginx mem ne ekzistas maniero ekspluati la eraron per injekto de specialaj signoj, riparu memormalkovro estis publikigita la 16-an de decembro. En la 4 monatoj ekde la raporto, neniuj ŝanĝoj estis faritaj al OpenResty, kvankam estis kompreno ke sekura versio de la funkcio ngx.req.set_uri() estas necesa. La 18-an de marto 2020 ni publikigis informojn, la 21-an de marto OpenResty publikigis versio 1.15.8.3, kiu aldonas URI-validigon.

Portswigger skribis bona artikolo kaj prenis komentojn de OpenResty kaj Nginx (kvankam la komento, ke nur malgranda fragmento de memoro estas elmontrita, estas malĝusta kaj misgvida, tio estas determinita de la longo de la linio sekvanta la nulan bajton kaj, en foresto de eksplicitaj restriktoj sur la longeco, povas esti kontrolita de la atakanto).

Kio do estis la eraro kaj kion oni povas fari por malhelpi ĝin?

Ĉu estis cimo en nginx? Jes, estis, ĉar liki memorenhavon ĉiukaze estas eraro.

Ĉu estis cimo en OpenResty? Jes, almenaŭ la afero de la sekureco de la funkcieco proponita de OpenResty ne estis esplorita kaj dokumentita.

Ĉu estis eraro pri agordo/uzo kun OpenResty? Jes, ĉar en foresto de eksplicita deklaro, nekontrolita supozo estis farita pri la sekureco de la funkcieco uzata.

Kiu el ĉi tiuj cimoj estas sekureca vundebleco kun $10000 premio? Por ni ĉi tio ĝenerale ne gravas. En iu ajn programaro, precipe ĉe la intersekco de pluraj komponantoj, precipe tiuj provizitaj de malsamaj projektoj kaj programistoj, neniu iam povas garantii, ke ĉiuj funkcioj de sia laboro estas konataj kaj dokumentitaj kaj ke ne ekzistas eraroj. Sekve, ajna sekureca vundebleco okazas ĝuste kie ĝi influas sekurecon.

Ĉiukaze, estas bona praktiko normaligi aŭ limigi/filtri kiel eble plej multe la enigajn datumojn, kiuj eniras en ajnan eksteran modulon/API, krom se estas eksplicitaj instrukcioj kaj klara kompreno, ke tio ne estas postulata.

Misprilaboro

De sperto antaŭa artikolo, por konservi la purecon de la lingvo:

cimo premio — konkurso pri ĉasado de cimoj
cimraporto - sciigo pri eraro
alidirekti - alidirekto
malferma fonto - malferma fonto
eraro - labori pri eraroj

fonto: www.habr.com

Aldoni komenton