A UIUCTF 2025 verseny egyik résztvevője részletesen elmagyarázta, hogyan sikerült végrehajtania a feladatot, amely megkövetelte, hogy a kód kommentjének tartalmának megváltoztatásával elérje a kód végrehajtását a szerveren.
A résztvevők hálózati kérést küldhettek a Python szkriptnek, amely új Python szkriptet hozott létre véletlenszerű névvel, hozzáadta a felhasználótól érkező adatokat a komment szöveghez, eltávolította a «\n» és «\r» karaktereket, és ezt a szkriptet a «python3 név.py» parancsal futtatta. Csak a komment tartalmát irányítva a résztvevőnek ki kellett nyernie egy sort a «/home/ctfuser/flag» fájlból. A szkript a következő kóddal hozható létre: comment = input(«> «).replace(«\n», «»).replace(«\r», «») code = f"""print(«hello world!») # Ez egy komment. Itt van egy másik: # {comment} print(«Köszönjük a játékot!»)"""
A «{comment}» helyére a résztvevőtől érkező adatok kerültek, végül a következő kód futott: print(«hello world!») # Ez egy komment. Itt van egy másik: # A verseny résztvevőjétől származó adatok print(«Köszönjük a játékot!»)
A feladat a CPython parserének egy sebezhetőségén alapult, amely a nullás kódú karaktert sorvégződésként kezelte (a sebezhetőség például felhasználható volt a rosszindulatú tevékenységek elrejtésére a komment szövegében). A problémát a CPython 3.12.0 és 3.11.4 verzióiban orvosolták. A verseny során alkalmazott feldolgozó csak a «\n» és «\r» karaktereket távolította el, de ha a résztvevő sebezhető CPython verziót használt, a «\0» karaktert elválasztóként használhatta. Ennek ellenére ez a trükk nem működött, mivel a verseny során már egy javított CPython verziót használtak, remélve, hogy a parserben még találhatók hasonló hibák, amelyeket a résztvevők felfedezhetnek.
A successfully accomplished participant did not seek new vulnerabilities in the parser that would allow breaking the string into parts, but instead utilized the feature of Python execution based on the type of file content. For example, instead of placing source code in a file with the '.py' extension, cached bytecode stored in '.pyc' files can be used, and such a file will be executed. In the contest in question, the participant could only control the content within the file, thus could not add their own header to distort the MIME type.
The task was solved by taking advantage of the fact that Python starting from version 2.6 can execute the contents of ZIP archives for delivering Python packages in compressed form. Similar to bytecode cache, the presence of a zip archive is determined by its content, not the file extension, meaning that a 'file.py' can contain a zip archive and when run with the command 'python file.py', it will be processed as a compressed Python package. Additionally, ZIP archives in Python are indexed not by the header at the beginning of the file but by the EOCD (End of Central Directory Record) section at the file’s end. If the archive contains a file named '__main__.py', it runs automatically when the archive is executed directly with the command 'python archive'.
The contest task was solved by generating a similar ZIP archive and substituting it into the comment text. To maintain the structural integrity of the file considering the call 'print("Thanks for playing!")' at the end of the original file, the presence of a comment area in the EOCD section, placed at the very end, was utilized.

Forrás: opennet.ru
