
На одном из первых jeopardy-соревнований я решил web-таск через SSTI в Jinja2 — обход фильтрации занял четыре часа. Payload сработал, флаг сдан, дофамин получен. Через две недели на тренировке команды — аналогичный шаблонизатор. Ещё три часа. Потому что не записал ни payload, ни логику обхода, ни даже тип фильтра. С тех пор каждый решённый таск заканчивается не сдачей флага, а write-up'ом. За четыре года эта привычка сэкономила мне, по грубой оценке, сотни часов. И нет, я не преувеличиваю.
Главная ошибка — садиться за write-up после соревнования. К этому моменту вы устали, контекст забыт, а организаторы уже сняли задания с платформы. Write-up пишется параллельно с решением, а не вместо сна после финала. Подробнее — в нашем руководстве по создание ctf заданий.
Откройте .md-файл перед началом каждого таска. Назовите его по шаблону ctfname_taskname.md — потом проще искать. Записывайте по ходу решения:
nmap -sV 10.10.10.5, но и результат. Через неделю вы не вспомните, какие порты были открыты и что на них висело.robots.txt? Получили нестандартный HTTP-заголовок? Увидели stack trace в ответе сервера? Скриншот. Как отмечает LearnHacking.io: скриншотов лучше с избытком — удалить лишние проще, чем восстановить недостающие.id — WAF блокирует UNION SELECT, переключился на blind time-based — тоже фильтрация, тогда обратил внимание на заголовок X-Custom-Auth» ценнее, чем «нашёл SQL injection». Тупики показывают методологию CTF и ход мышления, а не только финальный результат.Формат важнее инструмента: если записываете в Markdown сразу, финальный write-up потребует минимальной доработки. Но выбор есть:
| Инструмент | Формат | Сильная сторона | Ограничение |
|---|---|---|---|
| Obsidian | Markdown | Теги, обратные ссылки, граф знаний | Требует привыкания к вики-подходу |
| CherryTree | Rich text | Древовидная структура, скриншоты встроены | Не Markdown — сложнее публиковать |
| VS Code | Markdown | Знакомый интерфейс, превью, расширения | Нет специфичных CTF-функций |
| Vim / nano | Plaintext / MD | Работает в любом терминале | Без визуального превью |
Я использую Obsidian. Через полгода обнаруживаете, что три задачи из разных соревнований эксплуатировали одну и ту же ошибку конфигурации — и обратные ссылки это показывают наглядно. Но vim в соседнем терминале тоже работает. Главное, чтобы заметки велись.
Хороший write-up — не скриншот флага с подписью «solved». Это документ, по которому другой человек (или вы через полгода) может воспроизвести решение и понять логику каждого шага. Разберём обязательные блоки.
Каждый write-up начинается с контекста. По рекомендациям cheatsheet команды P=NP (pequalsnp-team.github.io), обязательные поля:
P=NP также рекомендуют указывать год — чтобы читатель знал, не устарело ли решение. Совет кажется очевидным, но в половине write-up'ов на GitHub дата отсутствует. Проверьте свои — скорее всего, тоже.
Опишите, что увидели при первом контакте с задачей. Для web-таска — скриншот страницы, интересные заголовки ответа, результат просмотра исходного кода. Для pwn — вывод file и checksec (NX, ASLR, canary, PIE). Для forensics — тип файла, результат strings, exiftool. Для reverse — первичный анализ в Ghidra или IDA: структура бинарника, найденные строки, таблица импортов.
Принцип простой: скриншот + два предложения контекста работает лучше абзаца текста без визуала. Стены текста утомляют — разбивайте их подзаголовками и скриншотами.
Вот что отличает обучающий разбор CTF задания от формального отчёта. Расскажите, куда пошли и почему не сработало: «Пробовал XSS через <script>alert(1)</script> — фильтруется. Попробовал обход через <img src=x onerror=alert(1)> — тоже закрыто. Обратил внимание на параметр redirect_url — оказался открыт для open redirect, и через него удалось пробросить JavaScript».
Но мера нужна. Не надо описывать каждую набранную команду. Опишите ключевые развилки — моменты, где приняли решение сменить вектор атаки. LearnHacking.io формулирует точно: совсем не упоминать тупики — выглядите гением (или очень везучим); описывать каждый — похоже на жалобу. Оптимум — ровно столько, чтобы сэкономить время следующему человеку.
Пошаговое описание от момента обнаружения правильного вектора до получения флага. Каждый шаг — три компонента:
Третий компонент превращает write-up из пошаговой инструкции в обучающий материал. «Сервер вернул 200 вместо 403» — это результат. «Приложение проверяло IP через заголовок X-Forwarded-For без валидации — классическая ошибка доверия клиентским данным» — это понимание. Именно объяснение проверяет, что вы разобрались в уязвимости, а не просто скопировали чужой payload.
Если ваш таск эксплуатировал реальную уязвимость — укажите CVE-идентификатор. Например: «Задача воспроизводила CVE-2025-8088 — path traversal в WinRAR (CVSS 8.4, HIGH, CWE-35), позволяющая выполнение произвольного кода через crafted-архив. Уязвимость эксплуатировалась в реальных атаках и добавлена в CISA KEV». Такая ссылка добавляет контекст и помогает читателю копнуть глубже. На GitHub уже есть PoC-репозитории для этой CVE с десятками звёзд — их тоже стоит упомянуть, если использовали.
Приведите рабочий payload или скрипт с комментариями к ключевым строкам. Если CTF завершён и задания не будут переиспользоваться — включите сам флаг. Если задачи активны на постоянной платформе — следуйте правилам площадки.
Использовали чужой PoC? Нашли подсказку в блоге PortSwigger? Прочитали про технику в OWASP? Укажите источник. Это уважение к автору и полезная информация для читателя, который захочет разобраться в теме глубже.
Готовый шаблон — скопируйте и заполните под конкретный таск:
# [CTF] — [Таск] | [Категория] | [Очки] pts
**Дата:** YYYY-MM-DD | **Описание:** [текст задачи]
## Разведка
[Первый контакт: скриншоты, сканы, наблюдения]
## Тупики
[Что не сработало и почему — 2-3 ключевых развилки]
## Решение
[Пошагово: действие → результат → объяснение]
## Payload / Флаг
[Рабочий код с комментариями. Флаг — если разрешено]
## Ссылки
[Источники, благодарности, полезные материалы]
Адаптируйте под категорию: для pwn добавьте секцию «Защитные механизмы» (checksec output), для web — «Стек технологий», для crypto — «Математическая модель». Шаблон не догма — это скелет, который обрастает мясом под конкретную задачу.
Markdown — стандарт технического письма в ИБ-сообществе. Пара символов для заголовков (#), выделения (**bold**) и блоков кода (тройные обратные кавычки) — и текст выглядит чисто на любой платформе: GitHub, Codeby, Habr, личный блог.
Несколько правил оформления, которые делают write-up CTF читаемым:
вот так) подходит для коротких команд и имён файлов. Многострочный код — только в отдельном блоке с указанием языка. Это включает подсветку синтаксиса и переключает внимание в «технический режим».admin=true — вот и вектор».\ или используйте горизонтальную прокрутку в блоке кода.Команда P=NP в своём cheatsheet добавляет: используйте bold и italic для выделения ключевых моментов, форматируйте inline-код для путей, строк и переменных, прикладывайте исходники задачи, когда это возможно. Если write-up воспроизводим — он автоматически ценнее.
Если нужно отправить write-up как PDF — для портфолио, собеседования или архива — не переоформляйте текст в Word. Ryan Kozak описывает workflow: Markdown конвертируется в PDF через Pandoc с шаблоном Eisvogel. Установка: sudo apt-get install texlive pandoc, затем шаблон с GitHub.
pandoc --pdf-engine=xelatex ./writeup.md \
-o ./writeup.pdf \
--from markdown --template eisvogel --listings
Тот же файл с минимальными правками заголовка (замена Pandoc-метаданных на Jekyll/Hugo front matter) становится постом для блога. Для активных машин на HTB PDF можно защитить паролем через pdftk — паролем ставится root-флаг, чтобы не нарушать правила площадки. Один Markdown-файл на входе — три формата на выходе.
За годы чтения чужих и собственных старых разборов — список проблем, которые повторяются раз за разом. Каждая стоит времени и внимания.
Самый частый антипаттерн: один скриншот терминала с флагом и подпись «solved». Ноль контекста, ноль пользы, ноль обучения. Даже для себя — через месяц не вспомните, что происходило до этого скриншота.
Минимальный write-up из 200 слов — «задача про X, попробовал Y, сработало Z, вот флаг» — уже в десять раз полезнее. Вы создаёте поисковую точку входа для будущего себя. Не «потенциально может пригодиться», а конкретно пригодится — проверено на четырёх годах ведения заметок.
Обратная крайность: Python-скрипт на 80 строк без единого комментария. Ни абзаца текста до, ни строчки после. Команда P=NP в cheatsheet формулирует без обиняков: «Just don't post your code without a description or some comments please». Код — инструмент. Объяснение — инструкция. Без инструкции инструмент бесполезен для другого человека.
Как исправить: комментируйте не каждую строку, а ключевые моменты. Перед блоком кода — абзац о том, что скрипт делает и зачем. После — что получили на выходе и как это привело к следующему шагу.
«Получил shell» — а как? «Нашёл уязвимость» — где, какую, каким инструментом? Пропуск промежуточных шагов — системная проблема новичковых write-up'ов. Классика из мира разработки: комментарий на форуме «never mind, I figured it out» без объяснения. Бесполезен и для автора, и для сообщества.
Проверка: после написания пройдите write-up как чек-лист. Может ли человек, впервые видящий задачу, повторить ваши шаги от начала до флага? Если на каком-то этапе «непонятно, откуда это взялось» — допишите. LearnHacking.io рекомендует, если CTF-платформа ещё доступна, прогнать все шаги повторно и убедиться, что payload работает без ошибок копирования.
Write-up начинается с «открыл Burp, отправил запрос» — без описания таска, скриншота промпта, категории. Через полгода даже автор не поймёт контекст. Блок метаданных решает проблему за 30 секунд, а читателю экономит минуту на вопрос «это вообще про что?».
Не ошибка оформления, а этическая проблема. На постоянных платформах — Hack The Box, TryHackMe, Codeby Games — задачи переиспользуются. Публикация write-up'а по активной задаче позволяет другим списать и обесценивает работу организаторов. HTB разрешает write-up'ы только для retired-машин. LearnHacking.io прямо указывает: перед публикацией проверьте, разрешено ли это организаторами, и дождитесь окончания соревнования.
Нашли payload в исследовании PortSwigger? Использовали PoC с GitHub? Прочитали про технику в OWASP? Укажите источник. Это уважение к автору, дополнительный контекст для читателя и доказательство того, что вы понимаете происхождение техники. Если задача эксплуатировала реальную CVE, указание идентификатора и CVSS-скора добавляет write-up'у вес и связывает учебный контекст с реальными угрозами.
Площадка зависит от цели. У каждой — своя логика.
CTFTime.org — международный стандарт для командных соревнований. После окончания CTF публикуйте write-up к конкретной задаче — он привязывается к профилю команды и виден всему сообществу. Если играете в команде и хотите рейтинг — публикация на CTFTime обязательна.
GitHub — полный контроль над контентом и структурой. Создайте репозиторий: отдельная папка на каждый CTF, внутри — README.md плюс вспомогательные файлы. Пример организации: репозиторий t4mpr/ctf-writeups — каждый write-up в отдельной директории с Markdown-файлом, скриптами и скриншотами. Минус — нет встроенной аудитории, трафик нужно привлекать через другие каналы.
Форум Codeby, Habr и аналоги — готовая аудитория из тысяч специалистов, обратная связь в комментариях, видимость в поисковиках. На Codeby write-up найдут те, кто ищет разбор конкретного таска или изучает категорию. Для первых публикаций — оптимальный вариант: вы получаете фидбек от опытных игроков, и следующие write-up'ы становятся заметно лучше.
Личный блог — долгосрочная инвестиция. На Hugo или Jekyll через GitHub Pages — полностью под вашим контролем. На собеседовании вы отправляете работодателю ссылку на свой сайт с десятком структурированных разборов — это весомее строчки «CTF experience» в резюме.
Один write-up можно публиковать параллельно: исходник на GitHub, адаптированная версия на Codeby, PDF для портфолио. Pandoc-workflow решает задачу мультиформатности — один Markdown-файл превращается в пост и PDF без двойной работы.
Начинающие CTF-игроки часто недооценивают карьерный эффект write-up'ов. На собеседовании фраза «я умею в web security» — это слова. Ссылка на write-up, где вы разобрали XSS через DOM clobbering с объяснением каждого шага — это демонстрация. Работодатель видит не строчку в резюме, а ход мышления: как вы подходите к задаче, как справляетесь с тупиками, как формулируете результат. Написание отчёта по пентесту CTF — тот же навык, который потом используется при составлении отчётов для заказчиков на реальных проектах.
Девять из десяти начинающих CTF-игроков, которых я наблюдал в команде, решают таск и переходят к следующему. Через три месяца — 50 решённых задач и ноль документации. Спрашиваю «как ты решил ту web-задачу на прошлом соревновании?» — пожимание плечами. Это не лень, это ложная экономия: кажется, что write-up отнимает время у решения новых задач. На практике он отнимает 20-30 минут и экономит часы при повторной встрече с аналогичной техникой.
Есть распространённый миф: write-up'ы пишут только топовые команды из CTFTime-рейтинга. В реальности — наоборот. Именно новичковые разборы часто полезнее. В них описаны тупиковые ветки и ошибки, которые опытный игрок пропускает как очевидные. Ваш «наивный» путь через три неудачных попытки к флагу может оказаться ценнее прямолинейного двухшагового решения от организатора — потому что следующий новичок пойдёт тем же кривым маршрутом, и ваш write-up станет для него тем самым «ааа, вот как!»-моментом.
Я веду write-up'ы четвёртый год. Периодически перечитываю старые — и вижу, как менялось мышление. Первые были списком команд без объяснений. Текущие — документ, который можно передать джуниору, и он воспроизведёт решение без дополнительных вопросов. Между этими точками — разница между «решил таск» и «понял, почему решение работает». Если только входите в ИБ и хотите выстроить базу системно — на IB Basics показывают, что делать в первый месяц после «хочу в ИБ», а write-up'ы по пройденным задачам станут первым портфолио.
🚀 Хочешь закрепить на практике? Реши задачи по теме на HackerLab — категория «pentest-machines».
0 комментариев
Пожалуйста, войдите, чтобы оставить комментарий.
Загрузка комментариев...