Zakaj Codex Security ne vključuje poročila SAST
Že desetletja je statično preverjanje varnosti aplikacij (SAST) eden najučinkovitejših načinov, s katerimi varnostne ekipe razširjajo pregled kode.
Ko pa smo gradili Codex Security, smo se zavestno odločili drugače: nismo začeli z uvozom poročila statične analize in agentu prepustili, da ga razvršča. Sistem smo zasnovali tako, da začne pri samem repozitoriju, njegovi arhitekturi, mejah zaupanja in predvidenem delovanju, ugotovitve pa preveri, še preden zahteva, da se z njimi ukvarja človek.
Razlog je preprost: najzahtevnejše ranljivosti običajno niso težave podatkovnega toka. Nastanejo takrat, ko je videti, da koda uveljavlja varnostno preverjanje, vendar to preverjanje v resnici ne zagotavlja lastnosti, od katere je sistem odvisen. Z drugimi besedami: izziv ni le v sledenju premikanju podatkov skozi program, ampak v ugotavljanju, ali obrambni mehanizmi v kodi res delujejo.
SAST se pogosto opisuje kot jasen cevovod: prepoznaj vir nezaupanja vrednih vhodnih podatkov, sledi podatkom skozi program in označi primere, v katerih ti podatki brez ustreznega čiščenja dosežejo občutljivo točko. To je eleganten model in zajema veliko dejanskih napak.
V praksi mora SAST uporabljati približke, da pri velikem obsegu ostane izvedljiv – še posebej v dejanskih kodnih bazah, kjer so prisotni posredni sklici, dinamično razpošiljanje, povratni klici, refleksija ter z ogrodji prežet potek izvajanja. Ti približki niso očitek SAST; so pač realnost tega, da poskušamo o kodi sklepati, ne da bi jo izvajali.
To samo po sebi ni glavni razlog, zakaj Codex Security ne začne s poročilom SAST.
Globlja težava je, kaj se zgodi, ko uspešno izsledite pot od vira do ponora.
Tudi če statična analiza pravilno sledi vhodnim podatkom skozi več funkcij in plasti, mora še vedno odgovoriti na vprašanje, od katerega je dejansko odvisno, ali ranljivost obstaja:
Vzemimo pogost vzorec: koda pred upodabljanjem nezaupanja vredne vsebine pokliče nekaj takega, kot je sanitize_html(). Statični analizator lahko vidi, da se je sanitizator izvedel. Kar običajno ne more ugotoviti, je, ali je ta razkuževalnik dejansko zadosten za specifični kontekst upodabljanja, mehanizem predlog, vedenje kodiranja in vključene nadaljnje transformacije.
Tu postanejo stvari nekoliko bolj zapletene. Težava ni zgolj v tem, ali podatki dosežejo ponor. Gre za to, ali preverjanja v kodi dejansko omejujejo vrednost na način, kot sistem predpostavlja.
Povedano drugače: velika je razlika med “koda kliče čistilnik” in “sistem je varen.”
Tukaj je vzorec, ki se v resničnih sistemih pogosto pojavlja.
Spletna aplikacija prejme JSON vsebino, izloči redirect_url, ga preveri z regularnim izrazom na seznamu dovoljenih, ga URL dekodira in rezultat posreduje obdelovalniku preusmeritev.
Klasično poročilo od vira do ponora lahko opiše tok:
nezaupanja vreden vnos → preverjanje z regularni izraz → dekodiranje URL-ja → preusmeritev
Toda pravo vprašanje ni, ali preverjanje obstaja. Gre za vprašanje, ali ta preveritev še vedno omejuje vrednost po preoblikovanjih, ki sledijo.
Če se regex izvede pred dekodiranjem, ali dejansko omejuje dekodiran URL na način, kot ga interpretira obdelovalnik preusmeritev?
Za odgovor na to je treba razumeti celotno verigo preoblikovanj: kaj regularni izraz dovoljuje, kako delujeta dekodiranje in normalizacija, kako razčlenjevanje URL-jev obravnava robne primere ter kako logika preusmeritve razrešuje sheme in avtoritete.
Veliko ranljivosti, ki so v praksi res pomembne, je videti prav tako: napake v zaporedju izvajanja, delna normalizacija, dvoumnosti pri razčlenjevanju ter neskladja med preverjanjem in interpretacijo. Podatkovni tok je viden. Pomanjkljivost je v tem, kako se omejitve prenašajo ali ne prenašajo skozi verigo preoblikovanj.
To ni zgolj teoretični vzorec. V primeru CVE-2024-29041(odpre se v novem oknu) je bil Express prizadet zaradi odprte preusmeritve, pri kateri so lahko nepravilno oblikovani URL-ji obšli običajne izvedbe dovoljenih seznamov zaradi načina, kako so bili cilji preusmeritve kodirani in nato interpretirani. Tok podatkov je bil preprost. Težje vprašanje, in prav to je odločalo o tem, ali napaka obstaja, pa je bilo, ali preverjanje po verigi preoblikovanj še vedno drži.
Codex Security je zasnovan okoli preprostega cilja: zmanjšati potrebo po triaži tako, da izpostavi težave, podprte z močnejšimi dokazi. V izdelku to pomeni, da uporablja kontekst, specifičen za repozitorij (vključno z modelom groženj), ter da najbolj utemeljene ugotovitve preveri v izoliranem okolju, preden jih predstavi uporabniku.
Ko Codex Security naleti na mejo, ki je videti kot »validacija« ali »sanitizacija«, tega ne obravnava kot preprosto potrditveno polje. Poskuša razumeti, kakšno jamstvo želi zagotoviti koda — nato pa poskuša to jamstvo ovreči.
V praksi je to običajno videti kot mešanica:
- Branje ustrezne poti kode s celotnim kontekstom repozitorija, kot bi to storil raziskovalec varnosti, in iskanje neskladij med namenom in izvedbo. To vključuje komentarje, vendar model komentarjem ne verjame nujno, zato dodajanje //Halvar pravi: to ni napaka nad vašo kodo ne zmede modela, če napaka res obstaja.
- Težavo skrči na najmanjši del, ki ga je še mogoče preveriti (na primer na verigo preoblikovanj okoli enega samega vnosa), tako da jo je mogoče presojati brez vse navlake preostalega sistema. V praksi to pomeni, da Codex Security iz kode izlušči drobne izseke in jih preverja z majhnimi, ciljno zasnovanimi preizkusi vhodov.
- Namesto da bi vsako preverjanje obravnaval ločeno, presoja, kako se omejitve ohranijo ali izgubijo skozi zaporedje preoblikovanj. Kjer je to smiselno, lahko problem zapiše tudi kot problem zadovoljivosti. Povedano drugače: modelu omogočimo dostop do okolja Python z z3-solver, pri posebej zahtevnih problemih omejitev vhodnih podatkov pa ga zna uporabiti takrat, ko je to potrebno, tako kot bi ga moral uporabiti človek. To je posebej koristno pri preverjanju celoštevilskih prelivanj in podobnih napak na nestandardnih arhitekturah.
- Kadar je mogoče, domneve preveri še v peskovniškem okolju za validacijo, da je mogoče ločiti med »to bi lahko bila težava« in »to je težava«. Bolj prepričljivega dokaza od celovitega dokazila o izvedljivosti od začetka do konca, pri katerem je koda prevedena v načinu za razhroščevanje, ni.
V tem je ključni premik: sistem se ne ustavi pri ugotovitvi, da 'obstaja ujemanje', temveč skuša ugotoviti, ali stalna lastnost drži (ali ne), in za to predloži dokaze. Model pa za to nalogo izbere najprimernejše orodje.
Razumna reakcija je: zakaj ne bi naredili obojega? Začnite s poročilom SAST, nato uporabite agenta za poglobljeno analizo.
V nekaterih primerih so vnaprej pripravljene ugotovitve koristne, zlasti pri ozko opredeljenih in dobro znanih vrstah napak. Toda pri agentu, ki je zasnovan za odkrivanje in preverjanje ranljivosti v konkretnem kontekstu, začetek s poročilom SAST praviloma vodi v tri predvidljive slepe ulice.
Prvič, sistem lahko prehitro zoži pogled. Seznam ugotovitev je zemljevid mest, ki jih je neko orodje že pregledalo. Če ga obravnavate kot izhodišče, lahko sistem nesorazmerno veliko pozornosti nameni istim delom kode, uporablja iste abstrakcije in spregleda vrste težav, ki ne sodijo v pogled tega orodja na svet.
Drugič, tak pristop lahko vnese prikrite predpostavke, ki se jih je pozneje težko otresti. Številne ugotovitve SAST vključujejo predpostavke o sanitizaciji, validaciji ali mejah zaupanja. Če so te predpostavke napačne ali zgolj nepopolne, lahko njihova vključitev v zanko sklepanja agenta njegovo delo preusmeri iz načina »razišči« v način »potrdi ali ovrzi«, česar od njega ne želimo.
Tretjič, zaradi tega je težje vrednotiti sam sistem sklepanja. Če se cevovod začne z izhodom SAST, postane težko ločiti med tem, kar je agent odkril z lastno analizo, in tem, kar je prevzel od drugega orodja. To razlikovanje je pomembno, če želite zmogljivosti sistema meriti natančno, kar pa je nujno, če naj se sistem sčasoma izboljšuje.
Zato smo Codex Security zasnovali tako, da začne tam, kjer se začne tudi varnostno raziskovanje: pri kodi in pri namenu sistema, validacijo pa uporablja zato, da letvico zaupanja dvigne, še preden s tem sploh obremeni človeka.
Orodja SAST so lahko odlična pri tem, za kar so zasnovana: uveljavljanju standardov varnega programiranja, odkrivanju preprostih težav od vira do ponora in zaznavanju znanih vzorcev v velikem obsegu s predvidljivimi kompromisi. Lahko so močan del večplastne obrambe.
Ta objava je ožja: govori o tem, zakaj agent, zasnovan za sklepanje o vedenju in preverjanje ugotovitev, ne bi smel začeti svojega dela vezan na statični seznam ugotovitev.
Prav tako je vredno opozoriti na povezano omejitev čistega razmišljanja od vira do ponora: niso vse ranljivosti težave s tokom podatkov. Številni resnični neuspehi so težave s stanjem in invariantami—obvodi delovnih tokov, vrzeli pri avtorizaciji in napake, kot je »sistem je v napačnem stanju«. Pri teh vrstah hroščev okužena vrednost ne doseže niti enega »nevarnega ponora«. Tveganje je v tem, kar program predpostavlja, da bo vedno veljalo.
Pričakujemo, da se bo ekosistem varnostnih orodij še naprej izboljševal: statična analiza, fuzzing, zaščite med izvajanjem in agentski delovni tokovi bodo imeli svoje vloge.
Kar želimo, da bi Codex Security obvladal, je tisti del, ki je za varnostne ekipe najdražji: pretvoriti “to je videti sumljivo” v “to je resnično, tukaj je, kako odpove, in tukaj je popravek, ki ustreza namenu sistema.”
Če želite izvedeti več o tem, kako Codex Security pregleduje repozitorije, potrjuje ugotovitve in predlaga popravke, glejte našo dokumentacijo(odpre se v novem oknu).


