В задании изначально не был дан ELF-файл
srv
. Задание было не решаемо во время соревнования.
Нам дали ссылочку и бинарник, а название таска недвухсмысленно намекает куда
нужно заливать payload, что подтвержает и протокол http у ссылки. Смотрим
декомпилятор, видим в цикле сравнение с %
и вызов функции fromHex
, которые
складываются в какой-то массив. Скорее всего, здесь есть переполнение. Заодно
заметим, что бинарник ожидает один аргумент, который потом прокидывается в bind.
То есть надо вызывать с портом. По пути также заметим вызовы fopen
, fread
и
подобные, а затем он отправляет прочитанное.
Запустив процесс под strace и отправив GET /
мы увидим, что программа пытается
открыть файл /index
и падает с ошибкой. Запомним это.
Теперь попробуем сделать GET
на какой-нибудь путь. Нам отдают 409. Вспоминаем
про процентики и думаем о percent-encoding. Пытаемся сделать GET /%41
. Нам
возвращают 200. Уже неплохо.
Запускаем под дебагом, ставим точку остановки на вызов write
после fromHex
. Отправим запрос с какой-нибудь узнаваемой строкой, например, %41%42%43
. Смотрим на стек:
Мы видим наш ABC
, а чуть дальше уже знакомый нам /index
. Видимо, мы можем его перетереть! Попробуем отправить 40 букв A и снова посмотрим на стек.
И да, у нас получилось. Нетрудно заметить, что надо отправить 32 байта мусора. Напишем простой генератор:
def generate(path):
return '%' + '%'.join(hex(ord(c))[2:] for c in ('a' * 32 + path))
И попробуем зайти куда-нибудь на сервере. Какое-то внутреннее жжение просит нас
посмотреть на /etc/passwd
. Правим, затем отправляем GET /
. Видим HTML,
открываем в браузере. Внимательно читаем то, что видим, замечаем интересную
строчку:
kettle:x:12:33:ctf:/home/kettle:/home/kettle/flag
Это следующее место, куда мы отправимся. Снова отправляем нагрузку, переходим в
браузер, нажимаем F5 и... Готовимся бросать камни в автора. Возвращаемся в
консоль, делаем curl -v
и внимательно смотрим на заголовок ответа, где и
находим флаг.
Флаг: kettle_pwn_1n_url_ohhhh