Как создаются задания для CTF: разбор уязвимостей от Positive Technologies

«Правила игры в CTF часто остаются за кадром: ты видишь задания, ищешь флаги, но не понимаешь логику их составления. Разбор, это не просто решение, а обратный инженерный разбор уязвимостей, как если бы ты сам писал таски для соревнований. Это показывает, как создатели думают о безопасности.»

Структура CTF и типы заданий

CTF от Positive Technologies традиционно делится на несколько треков, каждый из которых проверяет разные навыки. Часто это веб-сервисы, криптография, реверс-инжиниринг, форензика и задачи на эксплуатацию (pwn). Веб обычно представляет собой несколько связанных страниц или приложение с намеренно небезопасной реализацией. Реверс требует анализа бинарных файлов, понимания логики работы программы и поиска способов обхода защиты. Форензика — работа с образами дисков, памятью или сетевым трафиком, чтобы найти скрытые данные.

Создатели часто закладывают многоуровневые уязвимости. Например, в вебе сначала нужно найти способ авторизации, затем обойти фильтры, а в конце выполнить код на сервере. Это имитирует реальную цепочку атаки.

Разбор веб-заданий

Одна из типичных задач — веб-приложение для управления заметками. На первый взгляд всё просто: регистрация, вход, создание заметок. Однако при просмотре исходного кода или анализе запросов выясняется, что есть скрытый эндпоинт /admin, доступ к которому требует особых прав.

Первая проблема — аутентификация. Часто встречается уязвимость с JWT-токенами. Алгоритм подписи может быть установлен на none, или сервер проверяет подпись некорректно, принимая токены без неё. Решение — сгенерировать токен с полем role: admin и алгоритмом none. Инструменты вроде jwt_tool помогают автоматизировать эту проверку.

Далее идёт эксплуатация. Допустим, в админке есть функция чтения файлов с сервера. Если не реализована проверка пути, можно попробовать чтение за пределами разрешённой директории (Path Traversal): filename=../../../../etc/passwd. Так можно найти файл с флагом, который часто расположен в корне или домашней директории пользователя.

Более сложный случай — Server-Side Template Injection (SSTI). Если приложение использует шаблонизатор, например, Jinja2, и пользовательский ввод попадает в шаблон без экранирования, можно выполнить произвольный код. Полезная нагрузка может выглядеть так: {{ config.__class__.__init__.__globals__['os'].popen('cat /flag.txt').read() }}. Для разных шаблонизаторов инъекции различаются.

Криптография: неочевидные ошибки реализации

Задачи по криптографии редко требуют взлома современных алгоритмов вроде AES. Чаще всего флаг находится из-за ошибок в использовании криптографических примитивов.

Пример — шифрование в режиме ECB (Electronic Codebook). В этом режиме одинаковые блоки открытого текста шифруются в одинаковые блоки шифротекста. Если передать серверу для шифрования известный префикс (например, «admin»), а затем зашифрованный флаг, можно сравнить блоки и определить его содержание по частям. Использование ECB считается небезопасным для структурированных данных.

Другая частая ошибка — использование самописных или ослабленных алгоритмов. Например, RSA с маленькой экспонентой или одинаковым модулем для нескольких пользователей. Атака Хастада или атака Франклина-Рейтера позволяют в таких условиях восстановить сообщение. В CTF-задачах это проявляется как возможность получить зашифрованный флаг и, имея возможность шифровать свои сообщения, расшифровать его.

Практический пример: Padding Oracle

Режим шифрования CBC (Cipher Block Chaining) уязвим к атаке Padding Oracle, если приложение сообщает об ошибке проверки дополнения (padding). Атака позволяет расшифровать сообщение блоками, не зная ключа. Задача сводится к тому, чтобы подобрать последний байт каждого блока, наблюдая за ответом сервера («padding error» или нет). Инструменты вроде padbuster или скрипты на Python автоматизируют этот процесс. В CTF такая уязвимость часто скрывается за API, который шифрует и расшифровывает данные для пользователя.

Реверс-инжиниринг и поиск спрятанной логики

Задачи на реверс обычно предлагают исполняемый файл под Linux. Первый шаг — определить тип файла: file challenge.bin. Далее можно использовать дизассемблеры вроде IDA, Ghidra или radare2. Ghidra удобна тем, что декомпилирует код на Си.

Часто в программе есть функция, которая сравнивает ввод пользователя с правильным значением. Эта строка может быть зашифрована или спрятана. Анализ показывает, что перед сравнением над вводом выполняется серия преобразований: XOR с ключом, сдвиги, арифметические операции. Нужно понять этот алгоритм и написать скрипт, который выполнит обратные операции, чтобы из известного результата (флага) получить ожидаемый ввод.

Иногда флаг просто хранится в виде строки, но спрятан среди мусора или обфусцирован. Утилита strings может помочь, но создатели маскируют строки, разбивая их или кодируя. Тогда приходится анализировать граф вызовов функций и отслеживать, где строка собирается воедино.

Пример: простая проверка пароля

В дизассемблере видим функцию main, которая вызывает check_password. Внутри неё ввод сравнивается посимвольно с жёстко заданными значениями. Значения могут храниться не как текст, а как числа (ASCII-коды) или результаты операций. Задача — выписать эти значения, преобразовать в символы и получить флаг. Если сравнение проходит успешно, программа выводит флаг из другого места в памяти.

[КОД: пример Python-скрипта для восстановления строки из числовых значений, найденных в бинарнике]

Форензика: поиск в данных

Форензические задания дают файл: образ диска (формат .img), дамп памяти (.raw) или сетевой захват (.pcap). Первым делом нужно определить тип данных и использовать подходящие инструменты.

Для образа диска: монтируем его или используем binwalk для поиска встроенных файлов. Часто внутри образа есть удалённые файлы, фрагменты в свободных секторах или скрытые разделы. Инструмент foremost или scalpel помогают восстановить файлы по заголовкам.

Для дампа памяти: используем Volatility Framework. Сначала определяем профиль ОС: volatility -f memory.dump imageinfo. Затем ищем процессы, открытые соединения, команды из истории. Флаг может быть в переменных окружения процесса, в содержимом файла, который был открыт, или в области памяти выделенной под строки.

Сетевой захват анализируют в Wireshark. Фильтры помогают вычленить интересные пакеты: http.request или tcp contains "flag". Флаг может передаваться в незашифрованном виде внутри HTTP-запроса, быть частью DNS-трафика (техника exfiltration) или скрыт в нестандартных полях пакетов. Иногда требуется восстановить передаваемый файл (например, по протоколу FTP или из фрагментированного TCP-потока). Wireshark позволяет экспортировать объекты из сессий.

Pwn: эксплуатация уязвимостей в бинарниках

Этот трек требует понимания работы стека, кучи и механизмов защиты. Типичная задача — программа с функцией, использующей gets() или strcpy() без проверки длины. Это приводит к переполнению буфера на стеке.

Цель — перезаписать адрес возврата из функции, чтобы перенаправить выполнение на полезную нагрузку. Если в программе есть функция win(), которая выводит флаг, нужно сделать так, чтобы управление перешло на неё. Для этого вычисляется смещение от начала буфера до адреса возврата, затем вводится строка, состоящая из мусора нужной длины и адреса функции win в little-endian формате.

Современные бинарники имеют защиту: ASLR (рандомизация адресного пространства) и NX (отказ от исполнения кода в стеке). В условиях CTF ASLR часто отключена, что упрощает задачу. NX обходится с помощью Return-Oriented Programming (ROP), когда исполняется цепочка уже существующих в программе инструкций (гаджетов). Они используются для подготовки аргументов и вызова системных функций.

Для начинающих задачи часто упрощены: ASLR и NX отключены, а в программе есть функция system() и строка /bin/sh. Тогда эксплуатация сводится к вызову system("/bin/sh") для получения shell.

Тактика и инструменты для соревнований

Участие в CTF — командная работа. Важно распределять задачи по специализациям. Базовый набор инструментов включает:

  • Для веба: Burp Suite, OWASP ZAP, браузер с DevTools.
  • Для крипто: Python с библиотеками pycryptodome, gmpy2, SageMath для сложных вычислений.
  • Для реверса: Ghidra, IDA (если есть лицензия), radare2, GDB с плагинами.
  • Для форензики: Wireshark, binwalk, Volatility, автономные утилиты для анализа файловых систем.
  • Для pwn: GDB с плагином Pwndbg, ROP-гаджет-искатели (ROPGadget), генераторы полезных нагрузок.

Не менее важны скрипты для автоматизации повторяющихся действий: перебор параметров, отправка запросов, обработка ответов. Язык Python с библиотеками requests, pwntools (для pwn) становится основным.

Ключевой навык — умение читать документацию к инструментам и быстро применять их в новых условиях. CTF проверяет не только знание уязвимостей, но и способность адаптироваться.

Что даёт разбор чужих решений

После соревнований организаторы часто публикуют write-up — подробные решения задач. Их изучение даёт больше, чем самостоятельное решение. Ты видишь альтернативные подходы, о которых не подумал. Например, в веб-задаче мог быть неочевидный способ SQL-инъекции через заголовки HTTP.

Разборы показывают, как создатели маскируют уязвимости. Это помогает думать как атакующий и, как следствие, лучше защищать свои системы. Понимание типичных ошибок в CTF напрямую связано с реальными уязвимостями: небезопасная десериализация, инъекции, ошибки конфигурации.

Для специалиста по безопасности в России, работающего в свете требований ФСТЭК и 152-ФЗ, такой опыт ценен. Он развивает навыки поиска уязвимостей, анализа кода и сетевого трафика, которые необходимы для проведения тестов на проникновение и аудита защищённости. Знание методов атаки — основа для построения адекватной защиты.

Оставьте комментарий