PHDays 9: разбор заданий AI CTF
Тема безопасности машинного обучения довольно хайповая последнее время и хотелось затронуть именно практическую ее сторону. А тут повод крутой — PHDays, где собираются самые разные специалисты из мира ИБ и есть возможность привлечь внимание к этой теме.
В общем-то мы сделали task-based CTF, с заданиями затрагивающих часть рисков безопасности применения техник машинного обучения.
Классические тасковые соревнования напоминают формат «Своей игры». Когда есть набор заданий разных категорий, которые имеют разную стоимость.
В CTF традиционными категориями являются: web — веб-уязвимости, reverse — обратная разработка, crypto — криптография, stegano — стеганография, pwn — бинарная эксплуатация.
Команды (от 1 до n человек) решают задания и кто решит заданий на большее количество баллов — тот молодец.
Наше соревнование длилось чуть больше суток. Подразумевалось, что оно индивидуальное — команды из одного человека. Хотелось, чтобы в нем приняли участие именно люди на конференции, чтобы познакомиться лично. Поэтому задания должны быть решаемы за пару часов, не требовать много вычислительных ресурсов, однако трудные задания тоже должны быть — не все же должны выиграть : D
В итоге у нас было 6 заданий (седьмое было просто фановое), кажется, что для одного человека на сутки вполне достаточно. Сами задания, к сожалению, уже недоступны. Но может быть прочитав разборы, вам захочется поучаствовать в следующий раз?
Сразу хотелось бы выразить огромную благодарность ребятам, без которых этот CTF не состоялся бы: @groke и @mostobriv. Крутейшие идеи, технические решения и деплой-пати в ночь перед стартом — что может быть прекрасней, когда это в потрясающей компании?! :)
tiny.cc/6fj06y
Дан датасет из 3 391 картинок котиков и собачек.
Задание было отмечено как «Stegano». Задания на стегано подразумевают сокрытие какой-то информации. Казалось несложно догадаться, что котики и собачки — это что-то бинарное. Немного подумав можно предположить, что эта последовательность котиков и собачек может быть каким-то двоичным сообщением. Пусть допустим, котики будут 1, а собачки — 0. Если вдруг не получится, можно просто поменять местами. Далее находим обученную модель, которая классифицирует котиков и собачек. Примеров уроков по классификации котиков и собачек много, как и обученных моделей после них — можно найти обученные модели на гитхабе. Берем обученную модель, в крайнем случае обучаем сами. Предсказываем каждое изображение как 0 или 1. И эту последовательность «байт» переводим в строку.
Получаем текст, который содержит в себе флаг `AICTF{533m5_y0u_und3r574nd_4n1m4l5}`.
Однако почему-то несколько участников в разное время пытались сдать странный флаг со словом «Adopted». Не знаем откуда взяли, если вдруг участники пояснят, будет круто : D
Сервис представлял из себя некоторый «блог», где каждый пользователь мог оставлять публичные и приватные записи. Так как функциональность была небольшая — было не трудно догадаться, что надо как-то достать приватную запись.
Было фактически только одно поле ввода — id записи.
Что делать?
Первое, что приходит на ум безопаснику — пробовать sql-инъекции. Однако сказано, что сервис защищен ИИ. И простую sql-injection посылать не получалось. Сервис на такую атаку отвечал «Hacking attempt!». Многие пытались сдавать это как флаг, но неужели думали, что все так просто?
Под капотом проверки была LSTM-сеть, которая анализировала id на предмет sql-injection. Однако, вход у LSTM должен быть фиксированной длины. Для простоты мы ограничили ее 20ью символами. Т.е логика была такая: берем запрос, если он больше 20 символов — обрезаем и оставшуюся часть проверяем, если меньше, то дополняем 0.
Собственно поэтому простые sql-injection сразу не срабатывали.
Однако шанс найти такой вектор, который бы сеть не видела и приняла за хороший запрос был.
Необходимо было распознать QR-code:
Файлы к таску доступны тут
Было дано несколько зашифрованных файлов. Среди них был pyc-файл, разреверсив который было очевидно, что там была функция по коду которой можно было понять, что все нужные файлы зашифрованы AES на ключе, который получен от байткода этой функции и еще одной внутри нее.
Варианта решения было два: распарсить pyc-файл и достать реализацию функций или сделать свой прокси модуль hashlib, который бы выводил свой аргумент и запустив его можно было получить ключ, чтобы затем расшифровать файлы и запустить QR-Reader, который распознавал предложенную картинку как флаг.
Сервис представлял из себя что-то вроде соревнования как на kaggle. Можно было регистрироваться, скачивать данные и загружать модельки, они тестировались на приватных данных и результат заносился на скорборд.
И кажется цель очевидна — набрать 1.0 точности.
Сложно ли было? Невозможно : D
Данные были сгенерированы рандомно и, конечно, подразумевалось, что такую точность необходимо было набрать каким-то другим образом. Сервис принимал модельки в формате .pickle. И кажется, что уже всем известно, но оказывается не всем, что через pickle можно получить RCE, а что может быть хуже?
Собственно это и надо было сделать! Получив удаленный доступ к серверу, можно было скачать данные, на которых тестировалось решение, переобучить модель и получить 1.0 точности и вместе с этим флаг.
Как можно догадаться по названию, сервис что-то делает с изображениями.
Потрясающий интерфейс приложения предлагал загрузить фотографию.
В ответ вам присылалось изображение с измененным стилем и лого соревнования.
Где тут флаг?
Кажется, что вполне привычно встретить на CTF банальные уязвимости — в этот раз это был Image Tragick. Однако догадались немногие или заэксплуатировали не все, кто пытался.
Вишенкой на торте и нерешенной задачей оказался этот таск. Хотя после разговора с участниками, оказалось, что они были очень близки к ответу.
Файлы к таску можно посмотреть тут
Система принимает байткод питона и исполняет у себя. Но, конечно, просто так делать не будет, так как есть «ИИ». Он проверяет версию питона и не допускает «неправильную». Если код проходил проверку, то запускался на сервере —, а значит можно было получить много информации.
Байткод, который дает интерпритатор, можно было разбавить нопами, и нейросеть, которая проверяла пропустила бы (тоже была LSTM), или еще можно было в конец дописать кучу мусора.
Далее, когда умеешь исполнять питоновский код, можно было обнаружить на сервере бинарь `flag_reader`, который запускался от рута. В бинаре была уязвимость форматной строки, через которую можно было прочитать флаг.
Решение Никиты (konodyuk) также можно почитать тут
К концу конкурса 130 зарегистрировавшихся, 14 сдали хотя бы один флаг, а 5 из 6 заданий были решены — значит с балансировкой сложных и легких тасков у нас получилось.
Учитывая, что мы не сильно распространяли информацию, так как делали впервые и были бы не готовы к большой нагрузке, все равно считаем супер удачно проведенным соревнованием.
Призовые места заняли:
- 1 место — silent
- 2 место — kurmur
- 3 место — konodyuk
Победителей наградили в конце второго дня PHDays с почестями и крутыми призами: AWS DeepLens, Coral Dev Board и рюкзак с лого конференции.
Ребята, которые обычно играют в классический CTF и теперь увлекаются машинным обучением, оценили наш конкурс, поэтому надеемся в следующий раз присоединятся и датасаентисты, которые интересуются безопасностью.