Вход на сайт

Просмотр новости

Найдите то, что Вас интересует

30 сентября мы провели конференцию по информационной безопасности ZeroNights 2026. ...

Дата публикации: 06-10-2026 19:30:47

30 сентября мы провели конференцию по информационной безопасности ZeroNights 2026. Спасибо всем, кто решил поучаствовать! Без вас не было бы ни классных докладов, ни мерча, ни весёлой суеты вокруг всего этого. Скоро начнём выкладывать материалы на сайт — там будут доступны презентации и видеозаписи докладов.
А пока хотим поделиться райтапами на задания HackQuest этого года. Это традиционное соревнование в формате CTF, которое мы проводим до начала конференции. Сильнейшие участники получают бесплатные билеты на ZeroNights. Отличный способ встряхнуться перед мероприятием!
Первый таск погружает нас в автомобильную электронику. Легенда: у друга появилась старая японская машина с CD-чейнджером, но магнитола упорно выдаёт странную ошибку. Участникам выдали дамп логического анализатора — сессию sigrok. На шести аналоговых каналах записаны две дифференциальные шины: CAN 62.5 kbps и Toyota AVC-LAN — шина CD-чейнджера.
Беглая характеризация уровней и ширин импульсов дала картину: напряжение борт-сети меняется с 12.4 В до 8.9 В при работе стартера и до 14.2 В от генератора; ACC-питание включается на отметке примерно 0.817 секунды. На одном канале видны 2.5 В покоя, ±1 В доминант, кратность 8 сэмплов и серии, обрывающиеся на 5 битах, — это CAN с битстаффингом и скоростью 62.5 kbps. На другом канале старт-бит 168 мкс, период бита 39 мкс, high 20/33 мкс — AVC-LAN.
CAN декодировался в 491 кадр, все CRC-valid. Среди ID нашлись шесть чанков с индексом в байте 0, повторяющиеся каждые ~320 мс. Склейка дала строку — ту самую «странную ошибку» на дисплее магнитолы, и явное указание искать в другом месте, на шине чейнджера.
Кадр AVC-LAN оказался ровно 12 бит после старт-бита. Засада — полярность бита инвертирована относительно типичных описаний: здесь high 33 мкс = 0, 20 мкс = 1. Проверяется мгновенно: только при такой полярности адреса становятся корректными — голова и чейнджер, а длина сходится. Голова перебирает магазин (выбор диска и трека), запрашивает статус, а чейнджер отвечает байтом — и вот этот последний байт и есть символ флага. Диски опрашиваются в перемешанном порядке, сортировка по номеру диска собирает строку.
Второй таск был развёрнут в Tor и касался Monero. Анонс обещал бесплатный XMR: операторы ShadowPool были осторожны с деньгами, но не достаточно осторожны с доказательствами. На сайте нашлись документация, REST API и GraphQL. Полезной оказалась страница со схемой proof. Verifier должен пройти по Merkle-дереву и получить корень. В схеме есть случайная соль для commitment: если один и тот же лист использовать несколько раз с разными солями, commitment будет разным.
В GraphQL-схеме подозрительно, что account ID и operation лежат рядом с proof, но не внутри него. В формуле challenge их тоже нет. Значит, proof ничего не говорит о том, для какого аккаунта и какой операции он создан. Сначала показалось, что всё равно понадобится настоящий лист, но это оказалось ложным следом.
Через API выгружалось около 600 заданий, в них 147 уникальных аккаунтов. Разница ровно в три аккаунта выглядела странно. Было много работы, которая в итоге не понадобилась: сбор job'ов, выделение уникальных ID, сравнение аккаунтов по эпохам и действиям, попытки восстановить UUID. Все они с proof давали общий ответ.
Следующей находкой стала история persisted queries. В ней встречались многообещающие названия, но почти все поля уже отсутствовали в текущей схеме. Некоторое время казалось, что решение должно использовать старые операции, но ничего не сработало.
Ещё в приложении был публичный beta token. По названию GraphQL-поля выглядело логично, что token надо куда-то передать. Попробовали обычные варианты — как часть secret, serial, blind. Поведение не изменилось, для успешной эксплуатации token не понадобился.
Маршрут отдавал Monero-адрес и приватный view key. Ключ действительно соответствовал адресу, это удалось проверить локально. Но приватный view key позволяет видеть входящие транзакции, а не тратить средства. Флаг к view key отношения не имел.
Отдельно мешал wallet RPC, который периодически падал. Из-за этого нельзя было понять, отвергнут ли action или просто не поднялся сервис.
После всех кругов снова посмотрели на формат доказательства. У verifier три сущности: доверенный корень, с которым надо сравнить результат. Первые две присылает пользователь, третью сервер обязан брать у себя. Но корень находился прямо в proof. Тогда возник простой тест: что будет, если путь пустой? Обычный расчёт Merkle root выглядит так: если путь пуст, цикл не выполняется и результатом становится сам лист. Получается, весь proof можно собрать из произвольных данных.
Скрипт был написан быстро. Задача фактически решена: сервер считает доказательство валидным, хотя ни одного настоящего листа не известно. Никакой крипты тут нет — сервер пересчитывает все хеши, но сравнивает результат ещё с одним значением атакующего.
После этого GraphQL не сразу отдал token или flag. Пришлось перебирать действия из открытых job'ов и варианты от имени GraphQL-операции. Сработал последний нормальный кандидат. Оказалось, что привилегированная операция не была частью challenge, поэтому тот же самодельный proof можно использовать для неё. В proof нет идентификатора аккаунта, значит сервер криптографически не может установить, для кого proof был выпущен.
Полный вариант на Python написала нейронка. Дело сделано. Всего-то нужно было пару часов отдыха и два бокала пива, чтобы вернуться с бара и сдать флаг.
Третий таск — традиционные ежи от SPbCTF. Путь к инвайту на ZeroNights лежит через Hedgewars: нужно победить бота в матче до семи побед. Разрешено работать вместе с AI-агентами, но в тестах агенты сами не справились.
Выдан телеграм-бот, который выдаёт инстанс, набор настроек оргов и информацию об игре — Hedgewars версии 1.0.0. Скачиваем исходники и готовую версию, начинаем изучать. Игра очень напоминает Worms, но со своим флёром FLOSS. Заходим, пытаемся играть — и терпим фиаско.
Бот противника ходит первым и кидает снаряд. У нас есть возможность сделать один ход. После этого бот вызывает авиаудар и гарантированно убивает, даже с идеальной меткостью лучшее, что мы можем кинуть — тот же снаряд, и нанести столько же урона, чтобы он нас авиаударом добил. Раньше использовать авиаудар нельзя: в правилах комнаты есть задержка.
Нужно искать другие выходы. Основная идея — контейнеры и PRNG, но сначала надо понять архитектуру. Движок на паскале отвечает за физику и логику игры — по сути ядро проекта. Qt-интерфейс на плюсах отвечает за всю не-игровую логику: мультиплеер, чат, меню. Связан по IPC с движком. Сервер на хаскеле — дополнительный слой для передачи между множеством движков. Он не реализует никакой логики и физики, а является по сути файерволом, который решает, какие сообщения раскидать всем движкам.
Исходя из этой экзотической архитектуры, заметна уязвимая точка: сервер не валидирует ничего кроме базовых проверок пакетов. Анализируем код сервера и находим валидацию. Из валидации здесь — только команды в матче, legalMsgs и checkNetCmd. Несмотря на передачу отправителя в checkNetCmd, реально он проверяется только для опкода h. Остальные опкоды слепо передаются во все движки, которые находятся в игре.
Смотрим, какие опкоды существуют и какую пользу могут дать. В движке находим опкод с запятой — он в вайтлисте, значит можно отправить его не в свой ход, и движок противника обработает. При выставлении флага происходит обнуление времени хода и его автоматическое завершение. Мы можем отправить не в свой ход — завершить ход противника.
Попробовав реализовать простое чит-меню, при попытке использования бот выводит ошибку. Погоняв тесты, понимаем, что в 1/10 случаев трюк работает и бот пропускает свой ход. Прогресс, но такая нестабильность не даст 50+% побед, необходимых, чтобы обыграть бота минимум 7 из 14 раз.
С обычными командами ходов передаётся таймстамп команды, привязанный к тикам. Для skip итоговый фрейм выглядит концептуально так: движок кладёт его в FIFO-команд, а потом исполняет, только если timestamp совпадает с его GameTicks. Поэтому обычная отправка умирает, если не угадать тик.
Изучив код очереди и диспатча ходов, находим интересный опкод N, который тоже в вайтлисте. Самое интересное — что делает отключение... На этом месте райтап обрывается, но очевидно, что участники в итоге разобрались с PRNG и контейнерами и смогли одержать победу.
Все три задания — отличный пример того, как важно смотреть не только на очевидные вещи, но и на архитектуру, доверенные данные и нестандартные интерфейсы. Какой из райтапов показался вам самым неожиданным? И какой подход — анализ CAN-шин, подделка Merkle-доказательств или поиск уязвимостей в распределённой архитектуре игры — вы бы хотели попробовать сами?

Схожие новости

#Наименование новостиТональностьИнформативностьДата публикации
1Daily Hacker News for 2026-09-2309.5924-09-2026
2Daily Hacker News for 2026-09-2809.4229-09-2026
3TryHackMe CC: Pen Testing - Full Walkthrough (2026)012.1230-09-2026
4Chinese espionage groups swarm to exploit triple-link chain of zero-days014.3209-09-2026
5ч2: Разбор. Как мы закрывали утечку через tun0 в AmneziaVPN07.7801-10-2026
6Microsoft discloses two actively exploited zero-days among 974 vulnerabilities013.6708-09-2026
7#blog@mikhail_tarasovcom #forensics@mikhail_tarasovcom Форензика спутниковых снимков: OSINT из открытого космоса Спутниковый ...06.4729-09-2026
8[club28812240|KOS.MOS.MUSIC / Русский Космос] представляет полную 2-х часовую версию сентябрьского ...014.8601-10-2026
9[club28812240|KOS.MOS.MUSIC / Русский Космос] представляет полную 2-х часовую версию сентябрьского ...014.8601-10-2026

Классификация: Пресс-релизы. Схожих патентов: 0. Схожих новостей: 9. Тональность: 1. Информативность: 9.58. Источник: vk.com.