25 октября в казанском ИТ-парке имени Башира Рамеева прошёл финал GO CTF Tatarstan. За победу боролись 20 команд — по десять в школьном зачёте и зачёте СПО. Призовой фонд составил 700 тысяч рублей. Финалисты играли в Attack/Defense: защищали собственные сервисы и искали уязвимости в чужих, чтобы добывать флаги.
В школьном зачёте победила команда daywave, второе место заняла Pudge Fun Club, третье — uz83k1. Среди СПО первой стала o1d_bu7_go1d, серебро досталось FR13NDS, бронза — Cit Code.


Участники решали четыре сервиса:
- ОРАНЖЕРЕЯ — use-after-free, рассинхрон авторизации по фрагменту URL, обратимая рекуррента.
- АСТРОЛЯБИЯ — шесть логических уязвимостей (коллизии ID, SSRF, symlink и др.).
- МАЯК — chosen-plaintext на самодельный FEAL-подобный шифр.
- ДОК — повторный промокод, обход подписи курсора, prefix-match контракта.
Репозиторий — https://github.com/acisoru/GoCTF-2026-AD
О заданиях и ходе игры нам рассказали победитель СПО зачёта Илья TakuyaYagam1 из o1d_bu7_go1d, и представители школьного зачёта: Тимофей GreenHaze из daywave, Николай Kolya080808 из uz83k1 и Алексей codem4ster из [mshp] BPT2019.
Тёмный зал и орбитальная визуализация
«Финал проходил в большом тёмном зале с неоново-фиолетовыми лучами.»
Тимофей считает, что организаторам удалось передать эстетику киберпанка, хотя ИИ-изображений в оформлении, по его мнению, было слишком много. Отдельно он отметил питание: полноценные обед и ужин на CTF ему встретились впервые.
Особенно понравилась визуализация и её орбитальный блок:
«Порой реально создавалось ощущение что ты сидишь где то в штабе во время галактического сражения», — пишет Тимофей.
Также он отметил и мерч:
«Ещё мерч порадовал. Хоть его было не так много, но за футболки с названиями команд респект.»
Площадку и организацию он оценил на 10 из 10. Алексей тоже похвалил сеть и кофебрейк, а у Ильи не было претензий к площадке и работе организаторов.

Старт и первые атаки
Начало игры ушло на осмотр сервисов, распределение работы и настройку инструментов. В o1d_bu7_go1d четверо участников взяли по сервису, а пятый занялся входящим и исходящим трафиком. BPT2019 первые полчаса не могла получить доступ к вулнбоксу — машине с уязвимыми сервисами. Пока подключиться не удавалось, команда обсуждала, кто чем займётся после получения доступа.
Для анализа кода и исправлений использовали в том числе ИИ. По словам Николая, uz83k1 работала с Codex и DeepSeek. Заранее подготовленный ИИ-оркестратор не запустился, поэтому уже во время финала команда написала другой. Его Николай впоследствии назвал одним из решений, которые помогли в игре.
Первые флаги o1d_bu7_go1d получила на «Оранжерее». По словам Ильи, примерно через 15 минут после старта команда забрала first blood: ошибка в проверке доступа позволяла читать чужие данные. Эксплойт проверили на NPC-команде, получили настоящий флаг и добавили атаку в ферму для автоматического запуска по соперникам.
BPT2019 написала первый эксплойт в течение первых 40 минут открытой сети: в бинарном сервисе нашли IDOR — ошибку контроля доступа к чужим объектам. У uz83k1 первая успешная атака тоже была на веб-сервис. Николай не помнит точный тип уязвимости, но отмечает, что именно эта атака принесла больше всего флагов в начале игры. Дальше сбор и сдачу флагов автоматизировали: эксплойт запускался каждый раунд.
Фильтры, шифрование и симлинки
«Маяк» потребовал более сложного разбора:
«На деле это сервис с зашифрованными очередями сообщений, для которых пользователи могли загружать собственные фильтры. Мы предположили, что через такой фильтр можно добраться до чужих данных на сервере и соответственно читать эти журналы, поэтому пришлось на тестовых сообщениях получить способ расшифровки и уже после сплоит отработал на ура,» — o1d_bu7_go1d.
Николаю запомнился сервис «Астролябия» на Rust:
«Проблема была в том, что при неправильной конфигурации, неточных изменениях в коде и т. п. он просто падал и не поднимался, и мы долго не могли понять этот момент. Когда поняли, сервис падать перестал.»
Алексей также выделил сервис «Астролябия»:
«Больше всего мне понравился сервис на Rust. Там было 6 уязвимостей, и последняя была загрузка tar-архивов и симлинки, там текла именно бизнес логика, и всё было взаимосвязано, поэтому он и запомнился.»
После чтения райтапов Тимофей отметил, что в сервисах сочетались простые уязвимости и задачи, над которыми требовалось подумать, в том числе криптография.
Защита: патч тоже нужно проверять
Чекеры следили за штатной работой сервисов; неудачное исправление снижало SLA — долю успешных проверок. Поэтому закрыть найденную уязвимость было только частью работы: после изменений требовалось убедиться, что сервис сохраняет нужное поведение.
Так произошло у o1d_bu7_go1d с «Маяком». Участник добавил обязательную проверку заголовка X-Queue-Key для запроса POST /api/queues/<id>/filter. Чекер этот заголовок не отправлял и получал 403. По словам Ильи, сервис начал проходить проверки только спустя семь с лишним раундов, когда SLA уже было нулевым.
«Паниковать не стали, вдвоем спокойно пошли разбираться», — вспоминает Илья.
Проверку убрали, вернув исходное поведение метода. Остальные участники в это время продолжали атаковать и работать со своими сервисами.
Находить уязвимости помогал входящий трафик. BPT2019 по запросам соперников разбиралась с кражей своих флагов и вносила точечные исправления. Был и эпизод с нагрузкой в 1800 запросов в секунду: по словам Алексея, запросы шли от разных команд, а SLA падал. Решение этой проблемы поручили девопсу.
Команда uz83k1 ближе к концу игры через tshark восстановила чужую атаку, закрыла уязвимости и написала собственный эксплойт. Результат защиты проверили в следующем раунде: свои флаги терять перестали.
Однако успешная проверка патча не гарантировала полной защиты. В «Доке» o1d_bu7_go1d нашла сценарий, в котором атакующий заранее готовил аккаунт, быстро покупал созданный чекером товар и получал флаг из его груза. Выдачу груза ограничили с учётом времени создания аккаунта и заказа. Старый эксплойт перестал работать, штатные проверки проходили. Но примерно раз в 30–50 раундов соперники всё равно уносили один флаг. Этот обход команда до конца не разгадала.

DoS: нагрузка на сервисы и мониторинг
По словам Николая, участникам разрешили DoS-атаки «в разумных пределах», если вызывающую отказ уязвимость можно исправить. Для uz83k1 это стало неожиданностью, хотя команда успела закрыть большую часть таких уязвимостей и сама воспользовалась атаками.
Тимофей тоже рассказал об обмене DoS-атаками с соперниками:
«Из забавного во время самой игры — обмены intended-досами с другими командами. На пике нам прилетало по 200 мегабит трафика, что 4/8 машинке с Packmate давалось тяжко, поэтому порой приходилось его отключать, и мы оставались без мониторинга.»
Николай считает проблемой одновременный DoS одной команды несколькими соперниками: под нагрузкой можно потерять доступ к машине и возможность установить патч. По его словам, с этим столкнулась Pudge Fun Club.
Последние раунды и впечатления от финала
Ближе к финишу команды искали ошибки в чужих патчах. У o1d_bu7_go1d основное внимание переключилось на «Астролябию»: первый эксплойт принёс 44 флага, затем соперники исправили уязвимость. Стабильный новый обход найти не удалось. BPT2019 тоже адаптировала атаки под изменившуюся защиту.
Команда uz83k1 одновременно удерживала третье место и пыталась догнать Pudge Fun Club. По словам Николая, разрыв заметно сократился. Увидев шанс побороться за второе место, команда активнее взялась за сложные цепочки уязвимостей, но итоговый порядок не изменился.
В daywave, по словам Тимофея, за всю игру не заметили сбоев сети, чекеров или игровой инфраструктуры. У Ильи осталось необъяснённое поведение «Дока»: после серии успешных раундов сервис мог на один раунд получить check failed, затем снова вернуться в up. Причину — в сервисе или чекере — команда не установила. Ещё одно его пожелание касается структуры исходников: сервис на Rust в одном файле примерно на тысячу строк затруднял разбор.
Сам финал Илья оценил как «обычный хороший A/D». Тимофей назвал GO CTF одним из лучших посещённых событий сезона — с оговоркой, что сезон только начинается.
