Postizanje izvršenja koda pod kontrolom teksta komentara u Python skripti.

Eden od udeležencev tekmovanja UIUCTF 2025 je podrobno razložil, kako mu je uspelo izpolniti nalogo, ki je zahtevala izvršitev njegove kode na strežniku, pri čemer je imel le možnost spreminjanja vsebine besedila komentarja v kodi.

Udeleženci so lahko poslali omrežni zahtevek Python skriptu, ki je ustvaril nov Python skript s naključnim imenom, dodal prejeti uporabniški podatek v besedilo komentarja, izrezal znake "\n" in "\r", ter zagnal to skripto z ukazom "python3 ime.py". Kontrolirajoč le vsebino komentarja je moral udeleženec izvleči niz iz datoteke "/home/ctfuser/flag". Skript je bil ustvarjen z naslednjo kodo: comment = input(«> «).replace(«\n», «»).replace(«\r», «») code = f»»»print(«hello world!») # To je komentar. Tu je še en: # {comment} print(«Thanks for playing!»)»»»

Namesto «{comment}» so bile vstavljene podatke, ki jih je posredoval udeleženec, in na koncu je bil zagnan naslednji kodo: print(«hello world!») # To je komentar. Tu je še en: # Podatki, ki jih je posredoval udeleženec tekmovanja print(«Thanks for playing!»)

Naloga je bila oblikovana po vzoru ranljivosti v parserju CPython, ki je obdeloval znak z ničelno kodo kot konec vrstice (ranljivost se je lahko uporabila za prikrivanje zlonamernih dejanj v besedilu komentarja). Težava je bila odpravljena v izdajah CPython 3.12.0 in 3.11.4. V obdelovalcu, uporabljenem v tekmovanju, so bili izrezani le znaki "\n" in "\r", vendar je lahko udeleženec z uporabo ranljive različice CPython uporabil znak "\0" kot ločilo. Kljub temu ta trik ni deloval, saj je bilo v tekmovanju uporabljeno že popravljeno različico CPython, ob predvidevanju, da bi v parserju lahko ostajale še kakšne podobne napake, ki bi jih udeleženci lahko odkrili.

Udeleženec, ki je uspešno opravil nalogo, se ni odločil iskati novih ranljivosti v parserju, ki bi mu omogočile razdelitev niza na dele, temveč je izkoristil značilnost izvajanja v Pythonu, kjer se datoteke izvajajo glede na njihovo vsebino. Na primer, namesto izvorne kode lahko v datoteko z razširitvijo «.py» umestite predpomnjeni bajtkod, ki se shranjuje v datotekah z razširitvijo «.pyc», in taka datoteka bo bila izvršena. V omenjenem tekmovanju je udeleženec lahko nadzoroval le vsebino znotraj datoteke, zato ni mogel dodati svojega naslova za izkrivljanje MIME-tipa.

Uspešno smo rešili problem korišćenjem činjenice da Python od verzije 2.6 može izvršavati sadržaj ZIP arhiva za isporuku Python paketa u komprimovanom obliku. Kao i kod keširanja bajtkoda, prisutnost ZIP arhiva se određuje prema sadržaju, a ne ekstenziji datoteke, tj. u „file.py“ se može smestiti ZIP arhiv, i prilikom pokretanja komandom „python file.py“ on će se obraditi kao kompresovani Python paket. Pri tome, ZIP arhivi u Pythonu se indeksiraju ne prema zaglavlju na početku datoteke, već prema EOCD sekciji (End of Central Directory Record) na kraju datoteke. Ako arhiv sadrži datoteku „__main__.py“, ova datoteka se automatski izvršava prilikom direktnog pokretanja arhiva komandom „python archive“.

Takmičarska zadaća je rešena generisanjem sličnog ZIP arhiva i umetanjanjem u tekst komentara. Da bi se očuvala ispravnost strukture datoteke u slučaju postojanja poziva 'print("Thanks for playing!")' na kraju izvorne datoteke, korišćena je prisutnost oblasti komentara u EOCD sekciji koja se nalazi na samom kraju.

Postizanje izvršenja koda pod kontrolom teksta komentara u Python skripti.
Postizanje izvršenja koda pod kontrolom teksta komentara u Python skripti.


Izvor: opennet.ru
Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki 🔥 Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki | ProHoster