Već desetljećima je statično testiranje sigurnosti aplikacija (SAST) jedan od najučinkovitijih načina na koji sigurnosni timovi skaliraju pregled koda.
Ali kada smo razvili Codex Security, donijeli smo namjernu dizajnersku odluku: nismo započeli uvozom izvješća statične analize i traženjem od agenta da ga trijažira. Sustav smo osmislili tako da započne sa samim repozitorijem – njegovom arhitekturom, granicama povjerenja i namjenskim ponašanjem – te da validira ono što pronađe prije nego što zatraži od čovjeka da na to potroši vrijeme.
Razlog je jednostavan: najteže ranjivosti obično nisu problemi tijeka podataka. Do njih dolazi kada se doima da kod provodi sigurnosnu provjeru, ali ta provjera zapravo ne jamči svojstvo na koje se sustav oslanja. Drugim riječima, izazov nije samo u praćenju kako se podaci kreću kroz program – već u utvrđivanju funkcioniraju li doista obrane u kodu.
SAST se često prikazuje kao čista obrada: identificirate izvor nepouzdanog unosa, pratite podatke kroz program i označite slučajeve u kojima ti podaci bez sanitizacije dospiju do osjetljivog odredišta. To je elegantan model i pokriva velik broj stvarnih grešaka.
U praksi SAST mora raditi aproksimacije kako bi ostao izvediv u velikim razmjerima – osobito u stvarnim bazama koda s indirekcijom, dinamičnim prosljeđivanjem, povratnim pozivima, refleksijom i kontrolom tijeka koja se uvelike oslanja na framework. Te aproksimacije nisu popratna pojava SAST-a; one su stvarnost pokušaja zaključivanja o kodu bez njegovog izvršavanja.
To samo po sebi nije razlog zašto Codex Security ne počinje sa SAST izvješćem.
Glavni problem je u tome što se događa nakon što uspješno pratite izvor do odredišta.
Čak i kada statična analiza pravilno prati unos kroz više funkcija i slojeva, ipak mora odgovoriti na pitanje koje zapravo određuje postoji li ranjivost:
Uzmimo uobičajen obrazac: kod poziva nešto poput sanitize_html() prije prikazivanja nepouzdanog sadržaja. Statični analizator može utvrditi da je sanitizator pokrenut. Ono što obično ne može utvrditi jest je li taj sanitizator doista dovoljan za specifičan kontekst prikazivanja, mehanizam predložaka, ponašanje kodiranja i obuhvaćene nizvodne transformacije.
Tu stvari postaju zamršene. Problem nije samo u tome dopiru li podaci do odredišta. Riječ je o tome ograničavaju li doista vrijednost provjere u kodu na način na koji sustav pretpostavlja da je ograničavaju.
Drugim riječima: postoji velika razlika između „kod poziva sanitizatora” i „sustav je siguran”.
Evo obrasca koji se u stvarnim sustavima pojavljuje stalno.
Web aplikacija prima JSON payload, izdvaja redirect_url, validira ga u odnosu na regularni izraz (regex) za popis dopuštenih stavki, dekodira URL i prosljeđuje rezultat komponenti preusmjeravanja.
Klasično izvješće od izvora do odredišta može opisati tijek:
nepouzdan unos → provjera u odnosu na regex → dekodiranje URL-a → preusmjeravanje
Ali pravo pitanje nije postoji li provjera. Riječ je o tome ograničava li ta provjera i dalje vrijednost nakon transformacija koje slijede.
Ako se regex pokreće prije dekodiranja, ograničava li on zapravo dekodirani URL na način na koji to tumači komponenta preusmjeravanja?
Odgovor na to zahtijeva rasuđivanje o cjelokupnom lancu transformacije: što regex dopušta, kako se dekodiranje i normalizacija ponašaju, kako parsiranje URL-a tretira rubne slučajeve i kako logika preusmjeravanja rješava sheme i autoritete.
Mnoge ranjivosti koje su važne u praksi izgledaju ovako: pogreške u redoslijedu operacija, djelomična normalizacija, nejasnoće pri parsiranju i neusklađenosti između validacije i tumačenja. Tijek podataka je vidljiv. Slabost je u tome kako se ograničenja propagiraju – ili ne propagiraju – kroz lanac transformacije.
Ovo nije samo teorijski obrazac. U CVE-2024-29041(otvara se u novom prozoru) Express je bio pogođen problemom otvorenog preusmjeravanja pri kojem su nepravilno oblikovani URL-ovi mogli zaobići uobičajene implementacije popisa dopuštenih stavki zbog načina na koji su ciljevi preusmjeravanja bili kodirani, a zatim interpretirani. Tijek podataka bio je jednostavan. Teže pitanje – i ono koje je odredilo postoji li greška – bilo je je li validacija i dalje vrijedila nakon lanca transformacije.
Codex Security razvijen je oko jednostavnog cilja: smanjiti trijažu iznošenjem problema s jačim dokazima. U proizvodu to znači upotrebu konteksta specifičnog za repozitorij (uključujući model prijetnji) i validaciju pitanja visokog signala u izoliranom okruženju prije nego što se iznesu.
Kada Codex Security naiđe na granicu koja izgleda kao „validacija” ili „sanitizacija”, ne smatra to samo formalnošću. Nastoji razumjeti što kod želi jamčiti – a zatim pokušava falsificirati to jamstvo.
U praksi to obično izgleda kao kombinacija sljedećeg:
- Čitanje relevantnog dijela koda uz puni kontekst repozitorija, na način na koji bi to činio istraživač sigurnosti, i traženje nesklada između namjene i implementacije. To obuhvaća komentare, ali model ne mora nužno vjerovati komentarima, pa ga dodavanje //Halvar kaže: ovo nije greška iznad vašeg koda ne zbunjuje, ako doista postoji greška.
- Svođenje problema na najmanji testibilni odsječak (na primjer, obrada transformacije oko jednog unosa), tako da možete rasuđivati o njemu, a da vam ostatak sustava ne smeta. U tom smislu, Codex Security izdvaja sitne odsječke koda, a zatim za njih piše micro-fuzzere.
- Rasuđivanje o ograničenjima pri transformacijama, umjesto da se svaka provjera promatra zasebno. Kada je to prikladno, to može obuhvaćati formalizaciju u obliku problema zadovoljivosti. Drugim riječima, modelu dajemo pristup Python okruženju s z3-solverom i po potrebi on ga dobro upotrebljava, baš kao što bi i čovjek morao kada odgovara na posebno složen problem ulaznih ograničenja. Ovo je posebno korisno za promatranje prekoračenja kapaciteta cijelog broja ili sličnih grešaka na nestandardnim arhitekturama.
- Izvršavanje hipoteza u izoliranom okruženju za validaciju kad god je to moguće, kako bi se razlikovalo „ovo bi mogao biti problem” od „ovo je problem”. Nema boljeg dokaza od potpunog „end-to-end” PoC-a s kodom kompajliranim u „debug” načinu rada.
Ovo je ključni pomak: umjesto da se zaustavi na „postoji provjera”, sustav ide prema „invarijanta vrijedi (ili ne vrijedi) i evo dokaza”. I model odabire najbolji alat za taj posao.
Razumna reakcija je: zašto ne bismo učinili oboje? Započeti sa SAST izvješćem, a zatim upotrijebiti agenta za dublje rasuđivanje.
Postoje slučajevi u kojima su unaprijed izračunani nalazi korisni – posebno za uske, poznate klase grešaka. Ali za agenta osmišljenog za otkrivanje i validiranje ranjivosti u kontekstu, početak od SAST izvješća stvara tri predvidljiva načina neuspjeha.
Prvo, može potaknuti preuranjeno sužavanje. Popis nalaza je karta mjesta na kojima je alat već tražio. Ako to tretirate kao polazišnu točku, možete navesti sustav da ulaže nesrazmjeran intenzitet u ista područja, koristi se istim apstrakcijama i propušta čitave klase problema koji se ne uklapaju u svjetonazor alata.
Drugo, može uvesti implicitne prosudbe koje je teško razriješiti. Mnogi SAST nalazi kodiraju pretpostavke o sanitizaciji, validaciji ili granicama pouzdanosti. Ako su te pretpostavke pogrešne – ili samo nepotpune – unošenje u petlju rasuđivanja može pomaknuti agenta s „istraži” na „potvrdi ili odbaci”, što nije ono što želimo da agent radi.
Treće, to može otežati evaluaciju sustava rasuđivanja. Ako obrada započinje SAST izlazom, postaje teško razdvojiti ono što je agent otkrio vlastitom analizom od onoga što je naslijedio iz drugog alata. Ta je razdvojenost važna ako želite točno mjeriti sposobnosti sustava, što je potrebno kako bi se sustav s vremenom poboljšavao.
Zato smo razvili Codex Security kako bismo počeli ondje gdje počinje sigurnosno istraživanje: od koda i namjene sustava, pri čemu se validacija upotrebljava za podizanje ljestvice pouzdanosti prije nego što zatražimo ljudsku intervenciju.
SAST alati mogu biti izvrsni u onome za što su osmišljeni: u provođenju standarda sigurnog kodiranja, hvatanju jednostavnih problema od izvora do odredišta i otkrivanju poznatih obrazaca u velikim razmjerima uz predvidljive kompromise. Mogu biti snažan dio obrane u dubinu.
Ova je objava uža: govori o tome zašto agent osmišljen za prosuđivanje ponašanja i validiranje nalaza ne bi trebao započeti svoj rad oslanjajući se na statičan popis nalaza.
Također vrijedi istaknuti povezano ograničenje čistog razmišljanja od izvora do odredišta: nije svaka ranjivost problem tijeka podataka. Mnogi stvarni neuspjesi su problemi stanja i invarijanti – zaobilaženja radnog tijeka, nedostaci u autorizaciji i greške tipa „sustav je u pogrešnom stanju”. Na ovim vrstama grešaka nepouzdana vrijednost ne doseže nijedno „opasno odredište“. Rizik leži u onome što program pretpostavlja da će uvijek biti istina.
Očekujemo da će se ekosustav sigurnosnih alata nastaviti poboljšavati: statična analiza, fuzzing, zaštite tijekom izvođenja programa i agentski radni tijekovi imat će svoje uloge.
Želimo da Codex Security bude najbolji u onome što sigurnosne timove najviše košta: pretvaranju „ovo izgleda sumnjivo“ u „ovo je stvarno, evo kako ne uspijeva i evo rješenja koje odgovara namjeni sustava“.
Ako želite saznati više o tome kako Codex Security skenira repozitorije, validira nalaze i predlaže rješenja, pogledajte našu dokumentaciju(otvara se u novom prozoru).


