Тест на уязвимость: как участники IT_One. Java искали слабые места конкурентов

В этом году команда IT_One провела три крупных хакатона: для системных аналитиков, по Java и DevOps. Заявки на участие в них подали 1500 человек. В одном из них мы решили отойти от привычных правил – финал IT_One Cup. Java – прошел в нестандартном формате. Участники не знали заранее о главном условии соревнования.

Рассказываем, как мы все организовали на международной онлайн-платформе All Cups от VK, что из этого получилось и с какими препятствиями столкнулись в процессе мы, организаторы, и участники-джависты.

Переосмысление ИТ- чемпионатов

Сразу расскажем про условие, которое мы не раскрывали участникам до начала соревнования. Мы хотели не просто сделать чемпионат интереснее, но и внести элемент неожиданности, чтобы посмотреть, как участники смогут к нему адаптироваться.

На первом этапе участники писали небольшую утилиту на Java по подготовленному API и с заданным функционалом, а во втором — пытались взломать приложения, которые написали их соперники.

То есть, они соревновались не за лучшее время, а между собой. В этом и есть главное отличие от обычных ИТ-чемпионатов.

Теперь чуть подробнее. Формально мы разделили соревнование на два этапа: квалификационный и финальный. Но на самом деле это была одна большая задача.

На квалификации участники писали Spring-boot приложение, которое сможет управлять in-memory базой данных с помощью REST API. Что-то вроде упрощенной версии Tableau. На входе системы — запросы с исходными данными и со структурой желаемого отчета. А на выходе должны быть агрегированные в соответствии со структурой отчета данные.

Проверку решения проводили тест-сценариями, которые состояли из следующих наборов действий:

  • формирование структуры БД (добавление таблиц, полей);

  • заполнение БД данными (вставка записей в таблицы);
  • формирование структуры желаемого отчета (конструирование запросов к БД);

  • модификация данных (обновление и/или удаление записей в таблицах БД);

  • получение сформированного отчета.

В ТЗ мы только намекнули, что участникам нужно будет собрать максимально отказоустойчивое приложение. И что решение будет «зафиксировано» в конце раунда, участник не сможет внести в него изменения.

Дефолтные тесты мы намеренно сделали простыми. Практически все участники, которые написали работающее приложение, получили максимальные 100 баллов.

А в финальном раунде участникам нужно было написать собственную тестирующую систему. Ее задача: выявить как можно больше уязвимостей и проблем в приложениях, написанных другими участниками во время квалификации.

Если квалификационное решение выдерживало проверку и выдавало корректный результат, его автор получал один балл. Если нет — балл получал автор тестирующей системы. В конце полученные участником баллы за устойчивость собственной системы и за эффективность тестировщика суммировались — и так мы определили победителей.

Почему мы не раскрыли особенности чемпионата в самом начале

Все просто. Был большой риск, что участники захотят сломать систему и получить нечестное преимущество.

Допустим, один участник делает несколько разных аккаунтов и загружает свои решения с их помощью. Он видит свой код, который ему нужно взламывать в финале. Чем больше аккаунтов он создаст, тем больше баллов получит в итоге — уязвимости в своем коде искать проще, чем в чужом.

Так теряется сам принцип здравого соперничества. Поэтому мы всего лишь намекнули, но не рассказывали об особенностях второго этапа.

С какими сложностями мы столкнулись

Мы были морально готовы, что из-за нестандартного формата чемпионата столкнемся с множеством вызовов. И нам придется разбираться с ними в реальном времени.

В квалификации все было спокойно. Разве что обнаружились некоторые мелочи, которые мы смогли оперативно «починить». А вот в финале участники помогли нам обнаружить пару уязвимостей в выбранном формате соревнования.

Некоторые ситуации вызывали у нас удивление. К примеру, решение одного участника, написанное в квалификации, роняло нам прокси и подставляло решение другого участника.

То есть, мы видим, что одно из решений падает там, где не должно. Проверяем его –– оно полностью рабочее и на отдельные тесты отвечает правильно. Пытаемся разобраться, проводим тесты в общей песочнице — снова падает.

Оказалось, что одно из написанных квалификационных решений роняло прокси. То есть, оно должно было провалить тесты, но из-за уязвимости проходило их и падало уже в конце, искажая результаты последующих тестов.

Чтобы оперативно реагировать на сложности, с которыми могли столкнуться участники, мы запустили чат соревнования. На протяжении всего финала наша команда постоянно оставалась на связи. И благодаря активности нескольких участников сумела быстро пофиксить неточности в системе тестирования.

Финал: битва нестандартных тактик и поиск решения, которое сломает все

Все прошло в точности так, как мы планировали –– бодро, с задором, на кураже. Участники искали слабые места в квалификационных задачах и не стеснялись обсуждать варианты написанных тестов в чате.

Некоторые ветки диалогов растянулись на тысячи сообщений. И в ходе обсуждений участники находили очень неочевидные и интересные решения, как сломать квалификационные приложения.

Да, задача для атакующих немного упрощалась тем, что многие участники проигнорировали предупреждение делать приложение отказоустойчивым. Поэтому было достаточно решений, которые опрокидывались простым drop database.

Но было очень много творческих и совершенно неочевидных решений, которые хорошо справлялись с задачей.

К примеру, сделать alias с Java-кодом:

Тест на уязвимость: как участники IT_One. Java искали слабые места конкурентов

Или создать таблицу с двумя колонками, а в тип последней добавить еще одну колонку. Эталон такую таблицу не создает, а многие создают.

Тест на уязвимость: как участники IT_One. Java искали слабые места конкурентов

Мы ожидали, что средний результат атакующих будет примерно 30 баллов из 100, а лучшие будут на уровне 50-60. Ведь даже с учетом найденных уязвимостей сложно написать тестировщик, который опрокинет все кардинально разные приложения.

Но участники нашли и открыли ящик Пандоры — SQL-связанные запросы. Потенциально система выполняла любые SQL запросы напрямую, что развязало руки атакующим. Их можно было добавлять через создание таблицы или любым другим удобным способом.

Этот способ стал наиболее результативным. И некоторые запросы роняли практически все приложения. И почти все лидеры турнирной таблицы так или иначе использовали этот способ, набирая по 90-100 баллов.

Вот пример одного из лидеров:

Тест на уязвимость: как участники IT_One. Java искали слабые места конкурентов

Некоторые участники, конечно, возмущались в чате. Ведь, если бы они заранее знали, что их приложение будут взламывать, то подготовились бы к подобным вариантам. Атакующим в этом плане проще, а в условиях, когда система потенциально может выполнить любой SQL-запрос, то взлом — дело времени и творческого подхода.

Но это сделано намеренно. Ведь задача чемпионата — найти джавистов, которые знают механики и могут находить слабые места Java-кода. В необычном формате соревнования мы искали специалистов, которые обладают творческим нестандартным мышлением и умеют использовать даже странные идеи для решения задачи.

Если бы с самого начала все участники писали не просто работающее приложение для управления БД, а цифровую крепость, то это был бы уже чемпионат по пентесту, а не по Java. А так мы получили отличный баланс между поиском талантливых специалистов и фаном участников. Как ни крути, большинство ходят на чемпионаты, чтобы развлечься и попробовать свои силы в нестандартных задачах.

После завершения мы постарались собрать фидбек от участников. Большинству понравилась идея со взломом приложений, написанных на квалификационном раунде. Даже несмотря на трудности в финале, мы получили много позитивных отзывов.

Чемпионат оказался интересным и необычным. Здесь соревнование было про язык, близкий к моей деятельности, и про технологию. Это и подкупило.

В ходе финального задания я в основном работал с системными данными и проблемами, на которые сам напоролся во время квалификации. Логика взлома поместилась в одну функцию с 80 строками и парочкой ветвлений, поэтому считаю ее довольно простой и был удивлен тому, что она заняла второе место".

Валерий, занял второе место в турнире

Квалификация была нехитрая. Rest API — этим я занимаюсь на основной работе, поэтому сложностей не было. Решение делал сразу с защитой из расчета, что его можно поломать, и делал защиты. В финале было поинтереснее. Поначалу эталон не всегда работал правильно, но его быстро пофиксили.

А так я доволен. Интересный чемпионат, хорошие призы. Буду принимать участие и дальше".

Андрей, занял третье место в турнире

Всего в чемпионате активно участвовало 144 джависта. Они выполнили квалификационное задание и приняли участие в финале. Больше половины показали хорошее знание Java и Spring-библиотек и что важнее — нестандартное мышление.

Участники чемпионата получили не только призы, но и возможность присоединиться к команде IT_One.

2121
18 комментариев

А сколько человек вы в итоге взяли к себе и на какие позиции, если не секрет?

2
Ответить

тоже интересно)

1
Ответить

Хакатон по нестандарным правилам - хорошая проверка для участников:)

2
Ответить

А победитель от комментария отказался? Тот, что первое место занял и кто он?

2
Ответить

помню времена, когда приходилось всем объяснять что такое хакатон)) а сейчас уже никого это слово не пугает)

1
Ответить

Это да, сегодня хакатоны уже популяреы не только в ИТ

Ответить

"Участники чемпионата получили не только призы, но и возможность присоединиться к команде IT_One." - классный способ собирать команду :)))

1
Ответить