Всё о CTF в России

Как была устроена система на NSK CTF 2017

2017-03-28 11:17:25

Соревнования NSK CTF 2017 в Новосибирске прошли в формате attack-defense. Но с некоторым усложнением — командам предстояло защищать систему умного дома с множеством датчиков и сенсоров. Предлагаем инсайдерский взгляд команды разработчиков Life на то, как была устроена эта система.

Введите описание изображения

Все «мозги» с уязвимыми сервисами разместились на Orange Pi — микрокомпьютере с огромным количеством устройств ввода-вывода и отдельными разъёмами для управления. У него есть HDMI, Audio Jack, USB, micro-sd слот, Ethernet, WiFi, Bluetooth, IR, микрофон и разъём для CSI-камеры. Всё управление периферийными устройствами и считывание показаний с датчиков шло через PIN’ы.

Введите описание изображения

Вот какие сенсоры были: датчик температуры/влажности DHT11, датчик уровня воды и освещённости. Из источников повышенного потребления энергии (ака электроприборов) были: водяная помпа, элемент Пельтье и освещение (освещение мы выпилили в последний момент, так как не удалось его завести). Замыканием/размыканием контактов на водяной помпе и нагревательном элементе управлял блок реле. При подаче на него напряжения с Orange Pi включается магнит, на который «налипает» металлический контакт. Таким образом, цепь замыкается.

Для сопряжения железа с софтом существует специальная библиотека — WiringPi. Она предоставляет пользователю лёгкий интерфейс для управлением всеми pin’ами ввода-вывода, шиной i2c и т.д.

Введите описание изображения

Вот так выглядела схематичная схема расположения датчиков (в бета-версии).

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

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

  1. зайти на Orange Pi;

  2. найти папку с сервисами;

  3. рассмотреть сервисы и найти уязвимости;

  4. закрывать баги и атаковать другие команды.

С третьим пунктом произошла накладка: не было принципиальной схемы соединения сенсоров и блоков реле. В Orange Pi это делается через библиотеку WiringPi по команде gpio readall. Команды могли увидеть распиновку и понять, что практически все порты не назначены (ALT), порты 21-23 поставлены в режим вывода (OUTPUT), 24 порт — на вход (INPUT). Также были подключены порты 27-28. Из данной схемы видно, что это SDA и SCL-порты (смотри ссылку. В данном случае их использовал АЦП-преобразователь PCF8591, к которому в свою очередь подключался датчик уровня воды и освещённости. Особенностью подключения PCF8591 было то, что их было всего 10 на 18 команд. Нам пришлось расшарить один АЦП на 2 команды. Одна команда могла считывать показания с этих сенсоров другой команды и наоборот. А можно было просто подать напряжение на данный выход и тем самым сжечь датчики команды-близнеца (с последующим зависанием Orange Pi). Для данного вида атаки достаточно было нагуглить спецификацию по модулю . Вариант 2 — один из сервисов принимал команды от жюрейской системы и контролировал все датчики. Перехват трафика + реверс-инжиниринг могут вам сильно в этом помочь.

Введите описание изображения

Таким образом, выяснилось, что 21 пин отвечает за контроль водяной помпы, 22 — за свет, 23 — за нагревательный элемент. 24 — датчик температуры/влажности, 27/28 — порты для общения с АЦП (освещённость и уровень воды). Помпа перекачивала воду с одной ёмкости в другую. Во второй ёмкости находился датчик температуры/влажности и уровня воды. Под бутылкой находился нагревательный элемент. Чем выше уровень воды — тем хуже. От показания сенсора уровня воды зависело количество очков, начисляемое команде за 1 раунд. Команды же, наоборот, стали сливать воду по максимуму.

Как же было понять, что перекачка воды — плохое действие? Методом реверс-инжиниринга кода сервиса Core. Также это можно было понять, логически размышляя: зачем вам переливать воду другим командам, если у них при этом улучшался показатель работоспособности?

Итак, вода поступала в нижнюю ёмкость, затем шёл в ход элемент Пельтье — он нагревал данный сосуд. При повышении температуры увеличивается количество испаряемой воды — физика! Показания датчика влажности и температуры, который расположен также в этой бутылке, начинают меняться, большая влажность уменьшает количество получаемых командой очков, ровно как и увеличение температуры. Где логика, спросите вы? Отклонение показаний датчиков от нормы (начального состояния игры) у обычного человека вызывает дискомфорт (это примерно так же, как и пользоваться отоплением в летний период). Освещённость шла в отдельном логическом звене, где за изменение этого показателя также выставлялся коэффициент начисления баллов (как выяснилось, датчик освещённости реализован также не был).

Введите описание изображения

Введите описание изображения

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

Изначально планировались 4 сервиса: голосовое управление умным домом Voice Control (Node.js + Vue.js), сервис для работы с камерой CamShot (Python), сервис для просмотра погоды Trial Weather (PHP) и центральный агрегирующий сервер Core (C), который работал в WiFi-mesh сети. В результате тестирования и сборки домиков нам не удалось корректно завести камеру (от слова вообще), поэтому сервис CamShot был представлен в виде обычного загрузчика фотографий. Voice Control отсутствовал по причине дефицита времени у главного deploy-мастера нашей команды разработчиков.

**¯ _ (ツ) _ /¯**

В процессе написания встал вопрос корректной обработки запросов: изначально 3 сервиса асинхронно работали с библиотекой WiringPi, которая не успевала обрабатывать информацию с железок и в итоге вырубалась. Было принято решение сделать сервис Core центральным и синхронно обрабатывать запросы к WiringPi. Все остальные сервисы общались с ним по tcp-протоколу, принимая и получая запросы. На сервисе Core также не были предусмотрены флаги и их заливка. Это ещё одно пробное нововведение под названием «Живучий сервис». Задачей команд являлось поддержание работоспособности сервиса и его регулярный аптайм. Чекер приходил на сервис по tcp-соединению и опрашивал все датчики, управлял всеми реле. По результатам опроса и проверки корректности показателей сервис выносил решение о состоянии системы в целом: какие датчики работают, как реагирует умный дом на запросы, доступны ли датчики. Если у команд всё работало — сервис горел зелёным. Отсутствие одного датчика давало командам синий цвет, двух/трёх — жёлтый, всех — красный.

Также чекер отправлял заведомо неверные запросы, проверяя тем самым закрытие уязвимостей, приводивших к нарушению этой работоспособности: отключению пинов, крашу сервиса, заливке шелл-кода. Это помогало командам разобраться с работой сервиса посредством анализа сетевого трафика. Мы считаем, что это более реальный жизненный пример работы сервиса, который критичен и который должен регулярно быть «живым». Более того, сервисы Voice Control и Trial Weather также зависели от Core, так как общались с ним по tcp.

Введите описание изображения

Сервис Trial Weather логировал показания с датчиков в БД PostgreSQL, а затем предоставлял пользователю интерфейс для просмотра показаний. Фишка данного сервиса — по умолчанию создаётся Trial Account с ограниченным функционалом. Для покупки Premium с возможностью просмотра дополнительных возможностей у вас на балансе недостаточно денег. Повышение типа аккаунта возможно было несколькими способами: по скрытому полю value при регистрации, при конвертации валют из рублей в доллары, при SQL-инъекции в коде, а также при дефолтном юзере CSI-Spy, который всё время создавался в базе по триггеру. Скрытое поле было comment.

Сервис CamShot предполагал наличие камеры, но в итоге работал с простой загрузкой изображений. Если вы могли заметить, в коде была интересная закладка: User-agent пользователя записывается в EXIF JPEG-картинки по частям (делится на несколько блоков). Для каждого пользователя создавалась отдельная папка с id сессии, который можно было узнать. Ещё одной из уязвимостей была плохая проверка типов: можно было загрузить свой shell-скрипт.

Введите описание изображения

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

Введите описание изображения