/Разборы задач
31 октября 2026
Райтап на задачу «Не доела ...»
Разбор задачи «Не доела ...»: восстанавливаем заголовок PNG и размеры изображения по CRC.9
5

Forensics
Задача «Украденный флаг»
Злоумышленники нашли уязвимость в поисковой строке сайта и с помощью слепой SQL-инъекции украли флаг из БД, а потом стёрли его.
Из логов есть только access-лог nginx. Попробуйте понять, какой флаг был украден.
Проанализировав лог, видим, что перед нами time-based blind SQLi. Если условие истинное, то будет выполнен тяжёлый запрос с RANDOMBLOB, что сможет увидеть злоумышленник.
Для того чтобы определить, когда начинаются действия с флагом, просто в файле лога жмём Ctrl+F и ищем строку flag.
В самом конце видим подбор символов флага. Нам нужны все строки, где в запросе встречается конструкция CAST(flag AS TEXT). Также заметим, что точные символы мы можем определить только если текущее значение сравнивается с каким-то символом оператором != (например, ...LIMIT 0,1),61,1)!=CHAR(55)), следовательно, вторым условием является наличие != в строке.
Теперь остаётся спарсить лог и собрать строку флага:
import urllib.parse
chars = {}
for line in open("bug-makers.ru-access.log"):
query = urllib.parse.unquote(line.split('"')[1].split("q=", 1)[1])
if "CAST(flag AS TEXT)" not in query or "!=" not in query:
continue
left, right = query.split("!=", 1)
right = right.strip()
left = left.rstrip()
if left.endswith(")"):
left = left[:-1].rstrip()
parts = left.rsplit(",", 2)
position = int(parts[1])
char_code = int(right[5:right.find(")")])
chars[position] = char_code
flag = "".join(chr(chars[p]) for p in sorted(chars))Запускаем и получаем hex-кодированную строку. Используем bytes.fromhex() для перевода в читаемый текст и получаем флаг!