Frontend CTF, или Как связаны Мона Лиза и искусственный интеллект. CTF.. CTF. frontend.. CTF. frontend. Блог компании Яндекс.. CTF. frontend. Блог компании Яндекс. Веб-разработка.. CTF. frontend. Блог компании Яндекс. Веб-разработка. загадки.. CTF. frontend. Блог компании Яндекс. Веб-разработка. загадки. игры для программистов.. CTF. frontend. Блог компании Яндекс. Веб-разработка. загадки. игры для программистов. Конференции.. CTF. frontend. Блог компании Яндекс. Веб-разработка. загадки. игры для программистов. Конференции. Программирование.. CTF. frontend. Блог компании Яндекс. Веб-разработка. загадки. игры для программистов. Конференции. Программирование. Разработка игр.. CTF. frontend. Блог компании Яндекс. Веб-разработка. загадки. игры для программистов. Конференции. Программирование. Разработка игр. Спортивное программирование.

Меня зовут Никита, и я один из тех, кто каждый год делает Frontend CTF в рамках конференции «Я 💛 Фронтенд». Сегодня хочу с вами поделиться, как и зачем мы ежегодно делаем соревнование для тех, кто любит пробираться сквозь загадки, секреты и спрятанные подсказки в браузерной игре.

Но сначала история

2021. Истоки

Frontend CTF, или Как связаны Мона Лиза и искусственный интеллект - 1

В далёком 2020 году, когда GPT-3 ещё только будоражил умы исследователей, а биткоин был по 10 000 $ за штуку, мы начали готовиться к конференции «Я 💛 Фронтенд — 2021». Помните, был такой COVID-19? Конференции и митапы тогда резко ушли из офлайна, но мало кто ещё умел делать классный онлайн. Нам хотелось сделать что‑нибудь запоминающееся и выделяющееся.

И тут Андрей @melikhov_dev Мелихов принёс ссылку на FCTF #3, который Сергей @ufocoder делал для фронтендерского сообщества RND.JS. Он предложил заколлабиться с Сергеем, сделать что‑нибудь похожее.

Так и решили. В итоге небольшая команда из трёх человек (Андрей Мелихов, Сергей Ufocoder и Евгений Телегин) за две недели собрала полноценную CTF‑игру с различными по сложности заданиями. У Андрея про это есть целый доклад.

Итого: 17 флагов, 8 уровней, 384 прохождения игры. Мы собрали уютный чатик в Telegram для всех играющих, чтобы можно было делиться намёками, но не подсказывать совсем уж явные решения. И было радостно смотреть, как из первой же игры рождаются локальные мемы, появляется узнаваемость игры.

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

CTF расшифровывается как Capture the Flag. Такие соревнования ещё в 1993 году придумали для конференции DEFCON, чтобы проверить знания участников в области кибербезопасности. Флаги — это то, что нужно найти. Либо «украсть» у соперников, либо отыскать в исходниках от организаторов.

Наш Frontend CTF — второго типа. Есть веб‑сайт в виде игры. В различных местах этого сайта или на сторонних сайтах спрятаны строки вида {flag_something}, где something — искомый флаг. Слово Frontend в названии нашего CTF намекает, что для решения большинства задач пригодятся знания фронтенда, сетей, инструментов разработки.

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

Кстати, именно в первой игре зародился локальный мем про Мону Лизу — задание с ней было одним из самых сложных в игре.

Frontend CTF, или Как связаны Мона Лиза и искусственный интеллект - 2

О чём мы сразу договорились между собой: мы уважительно относимся к анонимности участников. В игре нет регистрации, из‑за чего перенести «сохранения» на другое устройство затруднительно (хотя всё ещё можно при большом желании самого участника). Никаких метрик, трекерных пикселей. При желании победители могли оставить свои контактные данные в форме, которая выводилась на финальном уровне, — призы самым быстрым нам всё‑таки нужно было вручить.

2022. Новый движок

В 2022 году я присоединился к проекту уже не только как редактор, но и как разработчик и автор заданий.

В этот раз решили почти полностью переписать фронтенд («Никогда такого не было, и вот опять»). Валерий Сидоренко написал движок, который позволял сделать на плоской карте кликабельные интерактивные объекты. Таким образом можно было превратить игру в путешествие по псевдо-3D‑помещениям некой вымышленной корпорации UniCorp (все совпадения с реальными компаниями случайны).

Frontend CTF, или Как связаны Мона Лиза и искусственный интеллект - 3

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

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

Добавили номинации:

  • Спидранер — тот, кто нашёл все обязательные флаги самым первым.

  • Исследователь — тот, кто нашёл вообще все флаги самым первым.

  • Счастливчик — рандомно выбранный из тех, кто нашёл все обязательные флаги за неделю.

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

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

2023. Игровая вселенная

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

Frontend CTF, или Как связаны Мона Лиза и искусственный интеллект - 4

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

Задания становилось делать всё сложнее. Не хотелось повторяться, при этом уходить от фронтенда тоже было нельзя. Приходилось применять всю мощь самых современных на то время API браузера и искать что‑то древнее, что браузеры всё ещё поддерживают.

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

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

2024. Космическое путешествие

По сюжету те же персонажи, которые участвовали в эксперименте из прошлой игры, на корабле «Гермес-4» отправляются на Луну. Экипаж пытается разобраться, что произошло на лунной станции «Хронос» и что за таинственный артефакт скрыт в её недрах.

Frontend CTF, или Как связаны Мона Лиза и искусственный интеллект - 5

На продумывание сценария игры уходит всё больше времени. Если в первых играх можно было придумать что угодно, то теперь нужно аккуратно учитывать события прошлых игр, не путаться в именах и характерах персонажей, отслеживать сюжетные нестыковки. Но это не мешает расставлять пасхалки на всех уровнях, ссылаться на известные произведения писателей‑фантастов, фильмы, сериалы и даже мемы. При этом каждый раз нужно придумывать, как вписать Мону Лизу в задания или в окружения локаций игры. Да, мы каждый год отдаём дань уважения той самой первой Моне Лизе из задания Андрея Мелихова — она с нами надолго.

Добавили в движок игровую карту. Теперь после прохождения игры не нужно начинать всё сначала, чтобы найти опциональные флаги. Можно перейти на конкретный уровень и продолжить исследование там.

Задания тоже становятся интереснее. Добавили больше заданий с сервером на Node.js. Теперь важно ещё и не давать участникам положить задания неаккуратным дудосом.

Кстати, тогда у нас впервые появились задания от комьюнити. В чатике сообщества кинули клич, спросили, у кого есть интересные идеи, которые можно превратить в задания в CTF. И несколько человек откликнулось.

2025. «Афина Б»

По сюжету инженер по кибербезопасности Виктор отправляется на исследовательскую станцию «Афина Б» для расследования утечек данных из локальной сети. Он знакомится с сотрудниками станции и узнаёт, что на ней изучают упавший с Луны (буквально) летательный аппарат.

Frontend CTF, или Как связаны Мона Лиза и искусственный интеллект - 6

Было бы скучно совсем не трогать движок игры. Мы прокачали терминал, чтобы можно было вызывать разные команды с пасхалками и без. А на некоторых уровнях добавили возможность поиграть в компьютерные игры (игра в игре, ну великолепно же!).

Особая моя гордость как сценариста — сообщение в чате комьюнити «Этому персонажу хочется втащить через экран». Значит, не зря я потратил несколько дней на проработку характеров персонажей, в том числе второстепенных. Всё‑таки хочется, чтобы участники CTF не просто прокликивали все диалоги в поиске флага, а вместе с нами погружались в историю, которую мы создаём.

Выросли процессно. Теперь у нас есть обязательная прорешка всех заданий внешними консультантами. До этого мы прорешивали задания друг друга и субъективно давали им оценку сложности. Но когда несколько лет занимаешься придумыванием заданий для CTF, планка занижается. Сторонние прорешиватели помогают найти косяки в заданиях заранее, что даёт нам возможность добавить больше подсказок или исправить в заданиях баги.

Однако не обошлось без казусов.

  • Казус 1. Все задания мы стараемся расставлять по игре в порядке возрастания сложности. Но одно из заданий недооценили — оно уже на третьем уровне игры не давало пройти дальше. Пришлось в срочном порядке давать подсказки и патчить задание посреди соревнования. Естественно, не без недовольства участников.

  • Казус 2. Одно из заданий попробовали сделать про реальный взлом сервера. Что хотели, то и получили: участники сломали сервер и положили игру. Много думали. Задание спрятали до лучших времён.

2026. Детективное расследование

В этом году снова захотелось добавить что‑то эдакое и в сценарий, и в движок. Чтобы мотивировать участников исследовать мир (хотя бы во время второго прохождения): искать пасхалки, читать разложенные по уровням записки, ковыряться в командах терминала.

По сюжету главную героиню Нику отправляют в головной офис UniCorp для расследования инцидента. С хакером из самой первой игры уже проведена разъяснительная работа, а вот как на него вышел искин — пока установить не удалось. У Ники есть почти полный доступ ко всему оборудованию, всем проектам и любым терминалам компании. Героиня едет на станцию «Афина Б», где пытается найти того, кто устроил саботаж.

Frontend CTF, или Как связаны Мона Лиза и искусственный интеллект - 7

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

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

Иронично, что сценарий игры про искусственный интеллект помогал писать искусственный интеллект. Если скормить LLM описание каждой локации, каждого персонажа, описать основные сюжетные повороты, то она может неплохо помочь в генерации контента для обогащения игрового мира. В нашем случае это были болванки для многих записок на игровых досках объявления, «научные» труды персонажей и серверные логи.

Кстати, после того как в 2025 году нам несколько раз положили сервер, Андрей Мелихов почти полностью переписал CI/CD, разложил каждое задание по изолированным контейнерам, прикрутил к ним автоматический рестарт. Правда, без казусов снова не обошлось.

Мне очень хотелось снова сделать задание про взлом сервера. На этот раз — про взлом Next.js. Благо в прошлом году этот фреймворк радовал нас инфоповодами про очередной CVE, который требует срочных обновлений. Вот один из таких CVE я в задании и спрятал. К сожалению, я не настоящий безопасник, а вот участники эксплойты применяли правильно. В итоге контейнер с заданием несколько раз положили намертво. К счастью, сама игра при этом не падала.

А ещё к основной команде разработки игры присоединился Андрей Тараненко, который прокачал терминалы в игре эмуляцией файловой системы, что позволило нам сделать новый тип заданий.

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

А теперь про задания

Давайте расскажу, как у нас устроен процесс придумывания и реализации заданий для CTF. И поделюсь несколькими интересными.

Как мы их придумываем

Шаг 1. Генерация идей. Идеи заданий мы собираем сильно заранее. Например, у меня есть документ, куда я в течение года складываю разное странное и интересное, что можно превратить в задание. Сюда идут особенности браузера, новые фичи CSS, необычные демки с CodePen и так далее.

Ближе к подготовке новой игры мы делимся друг с другом в чатике списком идей. Кому какая понравилась, тот ту и берёт в работу.

Шаг 2. Реализация идеи. Просто топорно реализовать идею мало. Нужно придумать подсказки для игроков, которые намекнут на ход решения. Эти подсказки могут быть как в исходном коде задания, так и в самой игре.

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

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

Шаг 3. Прорешка. Задания автоматически деплоятся в прод. Урлы псевдослучайные, закрыты паролем. Сначала делимся ими друг с другом и просим порешать. Я всегда ещё сам решаю собственные задания в проде, потому что так иногда можно поймать неприятные баги, связанные с окружением.

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

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

На каждом уровне — по 2–3 задания. На первом уровне что‑то примитивное и лёгкое, на последнем — задания уровня «Да за что вы так с нами???».

Шаг 5. Прохождение игры. В ночь перед запуском игры на всех садимся и проходим. Если мы сами можем пройти игру, значит спидранеры и исследователи тоже скорее всего справятся.

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

Примеры заданий прошлых CTF

Поделюсь с вами несколькими заданиями — их можно использовать в качестве разминки для ума. Ответы спрячу под кат, чтобы было интереснее.

Задание 1. Шифр

Дана строка: {synt_xvat_rzcrebe}. Найти флаг.

Разбор и решение

Мы знаем, что флаг спрятан в строке {flag_...}. Визуально строка {synt_xvat_rzcrebe} похожа на то, что нам нужно. Предположим, что synt — это flag. Вспоминаем про существование шифра Цезаря, гуглим онлайн‑дешифраторы, применяем смещение 13.

Ответ: {flag_king_emperor}.

Задание 2. Чекбоксы

Дана страница с чекбоксами: https://1c84c21482bbe6c894b45ddf9fa43fab.ctf-2023.ilovefrontend.ru/. Найти на ней флаг.

Разбор и решение

То самое задание, которое прикладывает браузер! В HTML‑коде страницы нет ничего интересного. Самое интересное лежит в style.css.

input {
    user-select: none;
    pointer-events: none;
}

body:has(p:nth-child(7) input:nth-child(22):checked) p:nth-child(36) input:nth-child(93) { pointer-events: initial; }
body:has(p:nth-child(25) input:nth-child(46):checked) p:nth-child(15) input:nth-child(1) { pointer-events: initial; }
body:has(p:nth-child(34) input:nth-child(53):checked) p:nth-child(60) input:nth-child(32) { pointer-events: initial; }
body:has(p:nth-child(37) input:nth-child(30):checked) p:nth-child(44) input:nth-child(3) { pointer-events: initial; }
/* и таких ещё 5996 строк */

Весь смысл этого CSS в том, чтобы кликнуть в чекбокс можно было только в верной последовательности.

Вариант 1. Ручной

В CSS найти строку с самым коротким селектором. p:nth-child(4) input:nth-child(14) { pointer-events: initial; } — например, эту. Значит, в 4-й строке можно кликнуть 14-й чекбокс.

Ищем следующий. Находим body:has(p:nth-child(4) input:nth-child(14):checked) p:nth-child(11) input:nth-child(62) { pointer-events: initial; }. Можно кликнуть 11-ю строку, 62-й чекбокс. И так далее, пока чекбоксы не выстроятся в картинку.

Вариант 2. Автоматический

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

Улучшаем скрипт, кликаем по‑умному, как в варианте 1. Профит.

Вариант 3. Алгоритмический

Парсим style.css. Формируем граф, где каждая вершина — чекбокс с координатами, а рёбра соединяют последовательные чекбоксы. Обходим один из двух подграфов, начиная с вершины с одним ребром. Где‑нибудь на канвасе рисуем точку в координатах, которые обходим.

Ответ: {flag_w1c3}.

Задание 3. TypeScript TODO

Дана страница с TS‑кодом: https://txpsnj67.ctf-2024.ilovefrontend.ru/. Найти флаг.

Разбор и решение

Скачиваем страницу при помощи curl, открываем её исходный код. В браузере он рендерится коряво, потому что дженерики очень похожи на теги.

Открываем песочницу TypeScript, вставляем туда полученный TS‑код. Редактор сходу подскажет 512 возможных значений флага.

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

Результирующий тип {flag_${Q<A>}_${F<S>}} состоит из двух динамических частей. ${Q<A>} на самом деле превращается либо в types_types_types, либо в flags_flags_flags. ${F<S>} даёт aaaa, aaaj, aaat,…, wwww. Можно заметить, что используются только символы из типа type S = "a" | "j" | "t" | "w".

Применяем ко второй части подсказку про повторения и сортировку, получаем ajtw.

Итого у нас получается всего два возможных флага: {flag_types_types_types_ajtw} и {flag_flags_flags_flags_ajtw}. Пробуем ввести оба, какой‑то точно подойдёт.

Ответ: {flag_types_types_types_ajtw}.

Остальные задания

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

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

Вызовы

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

Во‑вторых, непросто координироваться. Делаем игры мы в свободное время. В команде у нас люди из разных компаний, у всех разная нагрузка по рабочим проектам в разное время. Не получается просто собраться и разом уделить пару недель исключительно этому пет‑проекту.

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

Тем не менее для меня это всё ещё интересный пет‑проект, которому точно планирую дальше уделять своё время. Потому что кайф.

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

  • Кайф отвлекаться от рабочей рутины и делать не что‑то про бизнес‑метрики и KPI, а небольшую инди‑игру с интересным сюжетом и затягивающей механикой. Многие ведь шли в разработчики, чтобы делать игры.

  • Кайф встречать на митапах и конференциях людей, которые проходили наш CTF и благодарны нам за него.

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

  • Кайф иметь единомышленников, с которыми каждый год за сутки до релиза вы впопыхах фиксите кучу багов, чтобы потом всё просто работало как надо.

Ждите анонсов в нашем уютном чате сообществ. За неделю до «Я 💛 Фронтенд — 2027» обязательно продолжим приключения ИИ в мире господства Моны Лизы.

Автор: DarkMeFoDy

Источник