Спустя несколько дней после запуска One Million Checkboxes мне показалось, что меня взломали. Что вот это делало в моей базе?

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

Но обо всем по порядку.

Что такое One Million Checkboxes?

26 июня 2024 года я запустил сайт под названием One Million Checkboxes (OMCB). На нем был расположен миллион общих чекбоксов: установка или снятие галочки одним пользователем моментально отображались у всех остальных.

Мои ожидания были довольно низкими и оказались абсолютно неверными. Я думал, что несколько сотен игроков нажмут несколько тысяч чекбоксов - вместо этого за две недели, что я держал сайт запущенным, 500 тысяч игроков прощелкали более 650 миллионов чекбоксов. Сайт попал на полосы New York Times и Washington Post, упоминания о нем есть в Know Your Meme и Википедии. Это было сумасшедшее приключение!

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

Чтобы смысл истории был понятен, необходимо поделиться с вами двумя важными деталями.

Деталь 1: в OCMB сложно рисовать

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

Примечание автора 1: статистика из игры Talk Paper Scissors говорит о том, что примерно в 4.5% игр игроки пытались напакостить.

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

Простите за корявый кернинг
Простите за корявый кернинг

Здесь я написал слово EXAMPLE ("пример" - прим. пер), но его видно только на определенной ширине экрана. Как только ширина окна меняется, сообщение исчезает.

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

Я получил огромное количество комментариев с просьбой "починить" это поведение, чтобы люди могли рисовать, однако это было сделано вполне сознательно.

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

Деталь 2: как я хранил состояние

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

У чекбокса есть 2 состояния - он либо включен, либо выключен. Прямо как один бит - либо 1, либо 0. Поэтому я хранил состояние каждого чекбокса в виде соответствующего бита информации: если чекбокс 3 проставлен, бит 3 имеет значение 1, и так далее.

Это миллион битов. В одном байте 8 бит, а значит все состояние занимает 125 КБ - даже меньше, чем MP3-файл! С этим можно работать.

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

Я хранил данные в Redis (его легко использовать в качестве базы данных) и кодировал их в base64 при передаче на клиент.

Примечание автора 2: это простой способ передавать бинарные данные через интернет. Есть и более эффективные способы, но я не особо парился по этому поводу во время разработки, в первую очередь потому, что не ожидал такой популярности.

Честное слово, это важно! А теперь вернемся к самой истории.

Меня взломали?

Через несколько дней после запуска OCMB я переписал бэкенд на Go (при содействии моего друга Элиота), чтобы справиться за растущей нагрузкой. А потом я вывел данные из базы в виде ASCII-символов - не знаю зачем, просто так.

И данные, которые я увидел, выглядели вот так:

что тут у нас?
что тут у нас?

Моя реакция была примерно такой:

настоящий кошмар
настоящий кошмар

Я запаниковал. В моей базе данных были ссылки! Более того, ссылки на какой-то домен с подозрительным названием catgirls.win! Что-то пошло совсем не так.

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

Ничего не было. Логи доступа выглядели нормально. Мой (элементарный) код был в порядке. У меня подскочил пульс. Моя подруга терпеливо ждала, когда я приду ужинать. И тогда я - подождите...

Подождите!

До меня дошло.

Скрытое послание

Я посмотрел на чекбоксы, которые соответствовали палевным ссылкам в базе.

буква h это один байт, 8 бит, 8 чекбоксов. вот эти 8 чекбоксов
буква h это один байт, 8 бит, 8 чекбоксов. вот эти 8 чекбоксов

Эта буква H представляла собой 1 байт. Байт состоял из 8 бит. Эти 8 бит соответствовали 8 чекбоксам.

Эти блоки по 8 чекбоксов формировали повторяющийся паттерн, по которому было выравнены ссылки. И если я что-то менял - снимал галочку с чекбокса - паттерн моментально появлялся снова.

стрёмно
стрёмно

Меня не взломали.

Кто-то писал мне послание в бинарном виде.

Что это значит:

Когда я вывел содержимое базы в консоль, Redis сконвертировал его в ASCII.

Для этого он считывает данные по одному байту. Он конвертируется в число от 0 до 255, и если оно соответствует коду печатного символа ASCII (32-127), то печатается как есть, в противном же случае выводится шестнадцатиричное представление (\x00 для 0).

104 означает букву h, а 116 - букву t
104 означает букву h, а 116 - букву t

Значит, кто-то:

  • Проставлял галочки

  • Чтобы переворачивать биты

  • Чтобы формировать числа

  • Которые представляли собой буквы

  • Которые складывались в URL

И они делали это при наличии тысяч других пользователей на сайте.

Я был впечатлен.

Глубже в кроличью нору

Итак.

https://catgirls.win/omcb

кошкодевки точка вин

Я долго сомневался. Погуглил. А потом просто нажал на ссылку.

интересно
интересно

Ссылка вела на Discord. А канал назывался "Нажимаем галочки". Я зашел.

Примечание автора 3: оригинальный канал заблокирован, а ссылка перенаправляет куда-то еще.

здороваюсь
здороваюсь

Кто-то был очень рад меня видеть! Мы немного пообщались. А потом они задали мне вопрос, который взорвал мне мозг:

Ты уже смотрел на чекбоксы в виде квадрата 1000x1000?

Я ответил отрицательно. Тогда они показали мне, чем они занимаются:

о господи
о господи

Они скачивали состояние всех чекбоксов и отрисовывали их в виде картинки 1000x1000 пикселей, где пустые чекбоксы представлены белыми пикселями, а проставленные - черными.

Тут много чего происходит. Легко читается фраза "be gay do crime" ("будь геем, совершай преступления" - относительно известный мем, прим. пер.) - угарно - но более интересным для меня были технические детали.

о господи x2
о господи x2

Повторяющийся шум внизу - это то сообщение в бинарном виде, которое я обнаружил. Над ним то же сообщение в виде base64 - помните, что я использовал этот формат для передачи данных. А слева была QR-код (с полной коррекцией ошибок!). Все эти ссылки вели на этот Discord-канал.

В нем сидела компания очень прошаренных подростков, и они писали эти тайные послания, чтобы собрать других прошаренных посетителей и обсуждать написание ботов для сайта. Человек, пишущий бота, скорее всего разглядывал бы сайт в виде base64, или в бинарном виде, или в виде картинки 1000x1000 - они покрыли все варианты.

Примечание автора 4: ну, не только подростков. Но "прошаренных людей моложе меня".

И это сработало. Канал вырос с менее чем 20 человек в момент, когда я туда попал, до более 60 на момент закрытия сайта.

Так что они делали?

Ну, они много рисовали! По мере того, как они усовершенствовали алгоритмы рисования (и разобрались с параметрами моего анти-DDoS-механизма), изображения стали более сложными.

Синий экран смерти Windows - еще до инцидента с CrowdStrike!
Синий экран смерти Windows - еще до инцидента с CrowdStrike!

Примечание автора 5: в один момент я предложил сказать им параметры rate limiter'а, но лидер канала ответил, что они хотят угадать их самостоятельно!

Со временем они стали экспериментировать с анимацией и даже добавили протокол для передачи цвета - например, использовать соседние пиксели в качестве красной, зеленой и синей составляющей цвета и рисовать на сетке с меньшим разрешением:

момент максимального хаоса - кто-то угорал по Джейку Джилленхолу
момент максимального хаоса - кто-то угорал по Джейку Джилленхолу

Я отправил в Discord предупреждение перед закрытием сайта. За ночь до этого я убрал все ограничения на частоту запросов чтобы посмотреть, сколько трафика сайт сможет переварить, и что они смогут сделать. В результате получились довольно крутые анимации - мне больше всего понравился рикролл (этот клип не ускорен):

смотри, как Рик пляшет
смотри, как Рик пляшет

Использовать ботов - хорошо?

Множество людей бесились от наличия ботов на OMCB. Не буду давать прямых ссылок, чтобы не привлекать негативное внимание к кому-либо конкретному - но мне присылали сотни сообщений про ботов. Самый популярный связанный с OMCB твит содержал жалобу на ботов. Боты людям очень не нравились.

И я отлично это понимаю! Обычно люди - особенно те, кто не программирует - сталкиваются с ботами в ситуациях, когда те сметают все доступные билеты или места в ресторанах. Эти боты эгоистичны, бесчестны и антисоциальны.

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

ок!
ок!

Я этого ждал - я же программист! - но люди говорили, что это испортило им все впечатление от сайта, и наверное я могу это понять.

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

всем привет, сайт попал в washington post (бугага), если вы ботоводите в верхней части сетки, куда будут приходить люди и кликать на случайные галочки, приостановите это на какое-то время чтобы нормальные люди могли повеселиться хехе (думаю что большинство людей эту часть не трогают, просто напоминание)

Насколько хорошо это сработало - вопрос открытый.

Так что проблемы были. Я понимаю, почему люди не любят ботов, может это и правда не было неоспоримым благом, но честное слово...

Это было так трогательно!

В старшей школе я написал рекурсивное правило перенаправления почты, которое в шутку отправило моему другу миллионы сообщений. Я (совершенно случайно!) несколько раз ронял школьный почтовый сервер.

Примечание автора 6: про это я когда-нибудь напишу отдельный пост.

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

Примечание автора 7: одним из таких взрослых был мой учитель информатики - замечательный Ричард Айзенберг, который впоследствии стал блестящим исследователем в области функционального программирования и моим будущим коллегой в Jane Street.

То, что народ сделал в этом дискорде было очень круто - очень неожиданно - очень креативно. Они напомнили мне самого себя - с оговоркой, что они в десять раз круче, чем я был тогда (и, если по-честному, наверное круче чем я сейчас). Иметь возможность наблюдать это вживую - возможность поощрить, увидеть их действия и ответить похвалой и гордостью вместо гнева - было для меня очень важно на каком-то глубоком уровне. У меня до сих пор наворачиваются слезы, когда я об этом думаю.

Я горжусь тем, что сделал нечто, заинтересовавшее этих ребят. Еще больше я горжусь тем, что они в итоге построили.

И очень хочу узнать, что еще они придумают в будущем.

Комментарии (0)