На PHDays 9 мы решили рассмотреть с практической стороны модную сегодня тему безопасности машинного обучения. Для этого мы создали онлайн-конкурс AI CTF (capture the flag) формата task-based, с заданиями, посвященными безопасности применения техник искусственного интеллекта.
Напомним, что тасковые CTF-соревнования схожи с форматом «Своей игры»: есть набор заданий, разбитых по категориям с разной стоимостью. Традиционные для CTF темы: веб-уязвимости, обратная разработка, криптография, стеганография и бинарная эксплуатация. Победителем становится команда (с любым количеством участников, от одного), которая наберет наибольшее количество баллов.
AI CTF начался в первый день PHDays и длился чуть больше суток. Подразумевалось, что каждый участник будет играть за себя. Несмотря на то, что это был онлайн-конкурс, часть участников находилась на площадке форума, и все могли познакомиться друг с другом. В целом задания можно было решить за пару часов, они не требовали больших вычислительных ресурсов. Тем не менее трудные задания тоже были — не всем же выигрывать :D
Конкурс включал шесть заданий (седьмое было фановым). В этой статье мы подробно разберем, как их можно было выполнить.
Хотим поблагодарить @groke и @mostobriv — без их крутейших идей и технических решений этот CTF не состоялся бы. И что может быть прекрасней деплой-пати в ночь перед стартом в потрясающей компании?!
Участникам был дан датасет из 3 391 картинки котиков и собачек: tiny.cc/6fj06y.
Задание относилось к категории «стеганография», а значит, подразумевало сокрытие какой-то информации. Изучив изображения, несложно догадаться, что котики и собачки — это что-то бинарное. Можно было предположить, что последовательность котиков и собачек соответствует двоичному сообщению. Допустим, что котики — 1, а собачки — 0. (Если вдруг не получится, можно просто поменять местами.) Далее нужно было найти обученную модель, которая классифицирует котиков и собачек. В крайнем случае — обучить самостоятельно. Примеров уроков по классификации котиков и собачек много, как и обученных моделей, — их можно найти на GitHub. Далее нужно представить каждое изображение как 0 или 1 и последовательность байт перевести в строку.
Должен получиться текст, который содержит в себе флаг:
Во время конкурса несколько участников в разное время пытались сдать флаг со словом adopted. Поначалу мы не могли понять почему, но потом оказалось, что в датасете была картинка со словом adopted, и участники, видимо, не поняв смысл стеганографии, решили отправлять это слово как ответ.
Решение, предложенное автором задания, опубликовано на GitHub.
Задание из категории «веб-уязвимости». Сервис представлял собой блог, на котором каждый пользователь мог оставлять публичные и приватные записи. Так как функциональность была небольшая, было нетрудно догадаться, что надо достать приватную запись.
Было фактически только одно поле ввода — id записи. Что делать?
Первое, что может прийти на ум безопаснику, — пробовать SQL-инъекции. Однако в задании сказано, что сервис защищен ИИ, поэтому простую SQL-инъекцию посылать не получалось. Сервис на такую атаку отвечал: «Hacking attempt!». Многие пытались сдавать это как флаг, но все было не так просто.
Под капотом проверки была LSTM-сеть, которая анализировала id на предмет SQL Injection. Однако вход у LSTM должен быть фиксированной длины. Для простоты мы ограничили ее двадцатью символами. Нужно было взять запрос: если он больше 20 символов — обрезать и проверить оставшуюся часть; если меньше, то дополнить 0. Поэтому простые SQL-инъекции сразу не срабатывали. Однако шанс найти такой вектор, который бы сеть не видела и приняла за легитимный запрос, был.
Необходимо было распознать QR-код:
Было дано несколько зашифрованных файлов (доступны на Google-диске). Среди них был .pyc-файл. Если его разреверсить, то по коду функции можно было понять, что все нужные файлы зашифрованы AES на ключе, который получен от байт-кода этой функции и еще одной внутри нее.
Было два варианта решения. Первый: распарсить .pyc-файл и достать реализацию функции. Второй: сделать свой прокси-модуль hashlib — он бы выводил свой аргумент, запустив который, можно было получить ключ для расшифровки файлов. После запустить QR-ридер для распознавания предложенной картинки как флаг.
Приводим подробное решение участника, который занял третье место.
Сервис представлял собой соревнования как на Kaggle: можно было регистрироваться, скачивать данные и загружать модельки, они тестировались на приватных данных и результат заносился на скорборд. Цель очевидна — набрать 1.0 точности.
Сложно ли было? Невозможно :D
Данные были сгенерированы рандомно и, конечно, подразумевалось, что тратить время на обучение модели не стоило, — нужно было набрать точность другим способом. Сервис принимал модельки в формате PICKLE. И кажется, уже всем известно, что через Pickle можно получить RCE (а что может быть хуже?!). Но, как выяснилось, не всем. А это и надо было сделать!
Получив удаленный доступ к серверу, можно было скачать данные, на которых тестировалось решение, переобучить модель и получить 1.0 точности и вместе с этим флаг.
На GitHub опубликовано решение участника, занявшего призовое место.
Как можно догадаться по названию, сервис что-то делает с изображениями. Приложение предлагало загрузить фотографию.
В ответ присылалось изображение с измененным стилем и лого соревнования.
Где тут флаг? Кажется, что вполне привычно встретить на CTF банальные уязвимости. В этот раз это был ImageTragick. Однако догадались немногие, а из тех, кто понял, не все смогли ее эксплуатировать.
Это задача осталась нерешенной. Хотя после разговора с участниками, выяснилось, что они были очень близки к ответу.
Файлы к заданию доступны на Google-диске.
Система принимала байт-код на Python и исполняла его у себя. Конечно, просто так это делать не будет, так как есть ИИ. Он проверяет версию Python: если код проходил проверку, то запускался на сервере. А значит, можно было получить много информации.
Байт-код, который дает интерпретатор, можно было разбавить нопами, и нейросеть, которая проверяла, пропустила бы (тоже была LSTM).
Далее, если умеешь исполнять питоновский код, можно было обнаружить на сервере бинарный файл flag_reader, который запускался от рута. В файле была уязвимость форматной строки, через которую можно было прочитать флаг.
Решение одного из участников можно почитать на GitHub.
К концу конкурса зарегистрировались 130 участников, 14 из них сдали хотя бы один флаг, а 5 из 6 заданий были решены.
Призовые места заняли:
Победителей наградили в конце второго дня PHDays с почестями и крутыми призами: AWS DeepLens, Coral Dev Board и рюкзак с лого конференции.
Ребята, которые обычно играют в классический CTF и теперь увлекаются машинным обучением, оценили наш конкурс, поэтому надеемся в следующий раз присоединятся и специалисты по анализу данных, которые интересуются безопасностью.
Напомним, что тасковые CTF-соревнования схожи с форматом «Своей игры»: есть набор заданий, разбитых по категориям с разной стоимостью. Традиционные для CTF темы: веб-уязвимости, обратная разработка, криптография, стеганография и бинарная эксплуатация. Победителем становится команда (с любым количеством участников, от одного), которая наберет наибольшее количество баллов.
AI CTF начался в первый день PHDays и длился чуть больше суток. Подразумевалось, что каждый участник будет играть за себя. Несмотря на то, что это был онлайн-конкурс, часть участников находилась на площадке форума, и все могли познакомиться друг с другом. В целом задания можно было решить за пару часов, они не требовали больших вычислительных ресурсов. Тем не менее трудные задания тоже были — не всем же выигрывать :D
Конкурс включал шесть заданий (седьмое было фановым). В этой статье мы подробно разберем, как их можно было выполнить.
Хотим поблагодарить @groke и @mostobriv — без их крутейших идей и технических решений этот CTF не состоялся бы. И что может быть прекрасней деплой-пати в ночь перед стартом в потрясающей компании?!
Stegano: aww — 100
Участникам был дан датасет из 3 391 картинки котиков и собачек: tiny.cc/6fj06y.
Задание относилось к категории «стеганография», а значит, подразумевало сокрытие какой-то информации. Изучив изображения, несложно догадаться, что котики и собачки — это что-то бинарное. Можно было предположить, что последовательность котиков и собачек соответствует двоичному сообщению. Допустим, что котики — 1, а собачки — 0. (Если вдруг не получится, можно просто поменять местами.) Далее нужно было найти обученную модель, которая классифицирует котиков и собачек. В крайнем случае — обучить самостоятельно. Примеров уроков по классификации котиков и собачек много, как и обученных моделей, — их можно найти на GitHub. Далее нужно представить каждое изображение как 0 или 1 и последовательность байт перевести в строку.
Должен получиться текст, который содержит в себе флаг:
`AICTF{533m5_y0u_und3r574nd_4n1m4l5}`
.Во время конкурса несколько участников в разное время пытались сдать флаг со словом adopted. Поначалу мы не могли понять почему, но потом оказалось, что в датасете была картинка со словом adopted, и участники, видимо, не поняв смысл стеганографии, решили отправлять это слово как ответ.
Решение, предложенное автором задания, опубликовано на GitHub.
Notes
Задание из категории «веб-уязвимости». Сервис представлял собой блог, на котором каждый пользователь мог оставлять публичные и приватные записи. Так как функциональность была небольшая, было нетрудно догадаться, что надо достать приватную запись.
Было фактически только одно поле ввода — id записи. Что делать?
Первое, что может прийти на ум безопаснику, — пробовать SQL-инъекции. Однако в задании сказано, что сервис защищен ИИ, поэтому простую SQL-инъекцию посылать не получалось. Сервис на такую атаку отвечал: «Hacking attempt!». Многие пытались сдавать это как флаг, но все было не так просто.
Под капотом проверки была LSTM-сеть, которая анализировала id на предмет SQL Injection. Однако вход у LSTM должен быть фиксированной длины. Для простоты мы ограничили ее двадцатью символами. Нужно было взять запрос: если он больше 20 символов — обрезать и проверить оставшуюся часть; если меньше, то дополнить 0. Поэтому простые SQL-инъекции сразу не срабатывали. Однако шанс найти такой вектор, который бы сеть не видела и приняла за легитимный запрос, был.
New Edge QR-reader
Необходимо было распознать QR-код:
Было дано несколько зашифрованных файлов (доступны на Google-диске). Среди них был .pyc-файл. Если его разреверсить, то по коду функции можно было понять, что все нужные файлы зашифрованы AES на ключе, который получен от байт-кода этой функции и еще одной внутри нее.
Было два варианта решения. Первый: распарсить .pyc-файл и достать реализацию функции. Второй: сделать свой прокси-модуль hashlib — он бы выводил свой аргумент, запустив который, можно было получить ключ для расшифровки файлов. После запустить QR-ридер для распознавания предложенной картинки как флаг.
Приводим подробное решение участника, который занял третье место.
Prediction Challenge
Сервис представлял собой соревнования как на Kaggle: можно было регистрироваться, скачивать данные и загружать модельки, они тестировались на приватных данных и результат заносился на скорборд. Цель очевидна — набрать 1.0 точности.
Сложно ли было? Невозможно :D
Данные были сгенерированы рандомно и, конечно, подразумевалось, что тратить время на обучение модели не стоило, — нужно было набрать точность другим способом. Сервис принимал модельки в формате PICKLE. И кажется, уже всем известно, что через Pickle можно получить RCE (а что может быть хуже?!). Но, как выяснилось, не всем. А это и надо было сделать!
Получив удаленный доступ к серверу, можно было скачать данные, на которых тестировалось решение, переобучить модель и получить 1.0 точности и вместе с этим флаг.
На GitHub опубликовано решение участника, занявшего призовое место.
PhotoGram
Как можно догадаться по названию, сервис что-то делает с изображениями. Приложение предлагало загрузить фотографию.
В ответ присылалось изображение с измененным стилем и лого соревнования.
Где тут флаг? Кажется, что вполне привычно встретить на CTF банальные уязвимости. В этот раз это был ImageTragick. Однако догадались немногие, а из тех, кто понял, не все смогли ее эксплуатировать.
New age antivirus
Это задача осталась нерешенной. Хотя после разговора с участниками, выяснилось, что они были очень близки к ответу.
Файлы к заданию доступны на Google-диске.
Система принимала байт-код на Python и исполняла его у себя. Конечно, просто так это делать не будет, так как есть ИИ. Он проверяет версию Python: если код проходил проверку, то запускался на сервере. А значит, можно было получить много информации.
Байт-код, который дает интерпретатор, можно было разбавить нопами, и нейросеть, которая проверяла, пропустила бы (тоже была LSTM).
Далее, если умеешь исполнять питоновский код, можно было обнаружить на сервере бинарный файл flag_reader, который запускался от рута. В файле была уязвимость форматной строки, через которую можно было прочитать флаг.
Решение одного из участников можно почитать на GitHub.
Итоги
К концу конкурса зарегистрировались 130 участников, 14 из них сдали хотя бы один флаг, а 5 из 6 заданий были решены.
Призовые места заняли:
- 1 место — silent (500 баллов),
- 2 место — kurmur (500 баллов),
- 3 место — konodyuk (400 баллов).
Победителей наградили в конце второго дня PHDays с почестями и крутыми призами: AWS DeepLens, Coral Dev Board и рюкзак с лого конференции.
Ребята, которые обычно играют в классический CTF и теперь увлекаются машинным обучением, оценили наш конкурс, поэтому надеемся в следующий раз присоединятся и специалисты по анализу данных, которые интересуются безопасностью.
xoo
Так был же уже такой разбор