Dosaženie vykonania kódu pri kontrole nad textom komentára v skripte Python

Jeden z účastníkov súťaže UIUCTF 2025 podrobne rozobral, ako sa mu podarilo splniť úlohu, ktorá si vyžiadala dosiahnuť vykonanie jeho kódu na serveri, pričom mal len možnosť zmeniť obsah textu komentára v kóde.

Účastníci mohli odoslať sieťový požiadavku na skript Python, ktorý vytváral nový skript Python s náhodným menom, pridával získané od používateľa údaje do textu komentára, odstránil znaky „\n“ a „\r“, a spúšťal tento skript príkazom „python3 názov.py“. Kontrolujúc iba obsah komentára, účastník mal vyťažiť reťazec zo súboru „/home/ctfuser/flag“. Skript sa vytváral nasledujúcim kódom: comment = input(„> “).replace(„\n“, „“).replace(„\r“, „“) code = f"""print(„hello world!“) # Toto je komentár. Tu je ďalší: # {comment} print(„Ďakujeme za hru!“)"""

Namiesto „{comment}“ sa doplnili údaje, ktoré poskytol účastník, a nakoniec sa spustil nasledujúci kód: print(„hello world!“) # Toto je komentár. Tu je ďalší: # Údaje poskytnuté účastníkom súťaže print(„Ďakujeme za hru!“)

Úloha bola formulovaná na základe zraniteľnosti v parséri CPython, ktorý spracovával znak s nulovým kódom ako koniec riadku (zraniteľnosť sa napríklad dala využiť na skrytie škodlivých akcií v texte komentára). Problém bol odstránený v vydaniach CPython 3.12.0 a 3.11.4. Vo spracovateľovi použitom v súťaži sa odstránili iba znaky „\n“ a „\r“, ale pri použití zraniteľnej verzie CPython mohol účastník použiť znak „\0“ ako oddeľovač. Napriek tomu tento trik nevyšiel, pretože v súťaži bola už použitá opravená verzia CPython s odhľadom na to, že v parséri môžu zostať ešte nejaké podobné chyby a účastníci ich budú môcť odhaliť.

Úspešný účastník sa nerozhodol hľadať nové zraniteľnosti v parseri, ktoré by umožnili roztrhnúť reťazec na časti, ale využil špecifiká vykonávania súborov v Pythone podľa ich obsahu. Napríklad, namiesto zdrojového kódu môže do súboru s príponou „.py“ umiestniť predcachovaný bytecode, ktorý je ukladaný v súboroch s príponou „.pyc“, a takýto súbor bude vykonaný. V prebiehajúcej súťaži mohol účastník kontrolovať iba obsah v strede súboru, a preto nemohol pridať svoj vlastný hlavičku na skreslenie MIME typu.

Úlohu sa podarilo vyriešiť využitím toho, že Python od verzie 2.6 môže vykonávať obsah ZIP archívov pre dodávku Python balíkov v komprimovanej forme. Rovnako ako pri bytecode cache je prítomnosť zip archívu určená podľa obsahu, a nie podľa prípony súboru, t.j. do „soubor.py“ je možné umiestniť zip archív a pri spustení príkazom „python soubor.py“ bude spracovaný ako komprimovaný Python balík. Pri tom sú ZIP archívy v Pythone indexované nie podľa hlavičky na začiatku súboru, ale podľa sekcie EOCD (End of Central Directory Record) na konci súboru. Ak je v archíve prítomný súbor „__main__.py“, tento súbor sa automaticky spustí pri priamom spustení archívu príkazom „python archív“.

Súťažná úloha bola vyriešená generovaním podobného ZIP archívu a jeho vložením do textu komentára. Na zachovanie korektnosti štruktúry súboru za podmienok prítomnosti volania ‘print(„Thanks for playing!“)’ na konci zdrojového súboru sa využila prítomnosť oblasti komentára v sekcii EOCD umiestnenej na samom konci.

Dosaženie vykonania kódu pri kontrole nad textom komentára v skripte Python
Dosaženie vykonania kódu pri kontrole nad textom komentára v skripte Python


Zdroj: opennet.ru
Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster