Привет, Хабр! Меня зовут Роман, я занимаюсь безопасностью IOT-устройств.
Мы в Бастион регулярно отрабатываем те или иные сценарии атак и устраиваем эксперименты. Об одном из них я расскажу прямо сейчас.
Представьте приемную крупной компании. Диван, низенький столик, подключенный к ТВ-приставке телевизор беззвучно крутит очередной выпуск новостей. Великолепный шанс для хакерской атаки. Нужно только получить доступ к устройству.
Мне предстояло найти способ отравить приставку и превратить ее в плацдарм для будущих атак на другие элементы сетевой инфраструктуры.
Разведка
Для эксперимента мы кинули жребий и приобрели одну из приставок, которые продают многочисленные онлайн-кинотеатры и операторы IPTV.
В результате на мой рабочий стол попало устройство на платформе Amlogic S905X, очень похожее на Mecool M8S PRO+.
Большинство подобных приставок основано на референс-дизайне Droidlogic A95X. AliExpress завален такими устройствами. Они отличаются по внешнему виду, но почти идентичны в своей начинке. Варьируется разве что расположение элементов на плате.
Первым делом я решил взглянуть на плату поближе и вскрыл корпус. Как правило, я сразу демонтирую память, подключаю к программатору и снимаю дамп. Но на этот раз у меня не нашлось нужного трафарета, чтобы припаять чип назад. Так что пришлось отложить эту операцию и заказать трафарет. Появилось время погуглить.
Производители узкоспециализированных процессоров редко публикуют техническую документацию. Но на чип S905X утекло некоторое количество документации. К тому же, на этом чипе основаны Khadas VIM1 и одна из плат ODROID.
Это платформы типа Raspberry Pi, только ориентированные на медиафункционал. В сети по ним много информации.
Выяснилось, что на платы этого типа устанавливается либо eMMC, либо NAND-память. Причем пины eMMC подключаются к той же линии, что идет к посадочному месту для NAND-памяти. Поэтому удалять чип вовсе не обязательно. Вместо этого, я подпаялся программатором на место NAND-памяти и снял дамп с eMMC. Так что трафарет в итоге не пригодился.
С помощью документации Khadas мне удалось найти чип сброса контроллера на плате приставки. Параллельно я подпаял хардварную кнопку Reset. Затем нашел отладочный интерфейс JTAG.
Плата нашей приставки. Желтым цветом подписаны штатные элементы, красным ― точки подключения отладочных интерфейсов и дополнительно установленные элементы
В инструкциях нашлось описание процесса загрузки чипа. Оказалось, что, если eMMC по какой-то причине не работает, загрузчик ищет альтернативу ― SD-карточку или USB-флешку.
Чтобы эксплуатировать эту особенность загрузчика, я установил на одну из ножек чипа памяти кнопку, прерывающую считывание, и получил альтернативный вариант загрузки. Появилась возможность залить бекап и вернуть плату к заводскому состоянию. К тому же, теперь дамп eMMC можно было залить на внешнюю флешку и экспериментировать уже с ней, без перезаписи содержимого чипа.
Пришло время переходить к софту.
Исследование загрузчика
В Amlogic S905X встроено расширение ARM Trust Zone. Оно нужно, чтобы выделить защищенную область памяти, которая доступна только для доверенного кода.
Trust Zone работает следующим образом.
Производитель подписывает легитимный загрузчик закрытым ключом. Масочный загрузчик (RomBOOT) при каждом запуске считывает код из основной энергонезависимой загрузочной памяти и проверяет корректность подписи. Если подпись корректна ― код выполняется.
Открытые ключи прошиваются в eFUSE. Эта область памяти представляет собой набор перемычек, которые пережигаются еще во время производства. Такой подход защищает RomBOOT от подмены ключей.
Довольно надежная штука, так что столкнувшись с ней я решил сначала изучить загрузчик нулевого уровня.
Бинго! Оказалось, что в приставке использован U-Boot. Это проект с открытым исходным кодом, который используют повсюду от продуктов Cisco до безымянных китайских датчиков.
Вот только популярность U-Boot не означает, что все понимают, как правильно его сконфигурировать.
U-Boot не просто загрузчик, в него встроены инструменты для отладки. Они доступны через консоль на одном из портов UART сразу после прерывания загрузки. По-хорошему, перед выходом на прод разработчикам необходимо заблокировать доступ к прерыванию загрузки и перевести консоль в режим Read-Only, а также исключить большую часть команд, которые позволяют работать с памятью на низком уровне.
Это стоило проверить. Я нашел контакты UART-порта по надписям RX/TX на плате, подключил консольный кабель, подобрал скорость и увидел стандартное приглашение:
Hit Enter or space or Ctrl+C key to stop autoboot -- : 0
Разработчики выставили таймер на 0, и это должно было заблокировать перехват загрузки.
Тем не менее загрузка прерывалась, если сразу при старте слать в консоль большое количество <CR>.
Прервав загрузку, я получил доступ к командной строке. По запросу «?» она выдала длинный список доступных сервисных команд.
Среди них нашелся еще один способ создать полный дамп eMMC, но главное, там была команда efuse read. На проверку, область efuse оказалась пуста ― все значения skb равны 0x00.
Так я понял, что доверенная загрузка просто не работает. На приставке выполняется произвольный код, любые загрузчики. Хорошая новость для энтузиастов с XDA, и не очень хорошая для производителя. Оригинальный софт сносится по мановению руки.
Чтобы проверить гипотезу на практике, я взял образ Ubuntu, предназначенный для установки на Khadas и записал на SD-карту, как есть. Затем заблокировал работу eMMC кнопкой и вынудил RomBOOT загрузиться с SD-карты.
Вместо Android запустилась Ubuntu.
Еще, ради интереса, я собрал из исходников U-Boot и также загрузил с SD-карты. Он стартовал, но падал на этапе BL2=>BL3. Вероятно, мне попалась сборка с некорректными конфигами DDR-памяти.
Исправлять их я уже не стал. Для демонстрации уязвимости этого было достаточно, так что я решил поработать с оригинальной операционной системой и получить там привилегированные права.
Получаем привилегии
На приставке крутился AOSP сборка Android 9 без сервисов Google. Вместо лаунчера запускается фирменное приложение, собранное таким образом, что оно выдает себя за лаунчер. Такой подход должен препятствовать установке сторонних приложений, но это было бессмысленно, так как на UART обнаружилась открытая консоль. Причем сразу c правами администратора и без аутентификации.
Чтобы не тратить время на ручную модификацию файлов, я получил Root с помощью Magisk, а затем настроил удаленную отладку. Производитель отключил ее вместе со всем меню разработчика, но ADB-интерфейс поднимается и руками:
setprop persist.sys.usb.config mtp,adb
/system/bin/mount -o rw,remount /
sed -i 's/ro.debuggable=0/ro.debuggable=1/g' /system/etc/prop.default
sed -i 's/ro.secure=1/ro.secure=0/g' /system/etc/prop.default
sed -i 's/ro.adb.secure=1/ro.adb.secure=0/g' /system/etc/prop.default
settings put global development_settings_enabled 1
/system/bin/mount -o ro,remount /
reboot
После выполнения этих команд, ADB-сессия без проблем открылась на удаленной машине. Дальше стало проще. Теперь я мог работать с ПК, а не набивать команды на клавиатуре, подключенной к приставке.
Исследуем файловую систему
Пришло время посмотреть на файловую систему. Хорошая новость ― пользовательский раздел зашифрован. Плохая ― все остальное ― нет. Разделы, относящиеся к системным, полностью открыты и даже не подписаны, хотя для этого существует Android Verified Boot.
Из-за этого все изменения, которые я провел через консоль или ADB, без проблем проделываются через прямую модификацию файловой системы и заливаются снаружи через U-Boot. Это готовый вектор для атаки, однако здесь нужен физический доступ. Мне же хотелось найти вектор для удаленной атаки. Надо было посмотреть трафик.
Подслушиваем за приставкой
Приставка осуществляет обмен с инфраструктурой провайдера при помощи HTTP запросов поверх SSL. Для снятия SSL необходимо было направить трафик приставки на proxy-сервер и подменить корневые сертификаты.
В качестве инструмента для мониторинга HTTP я использовал Charles. Основной сценарий использования Charles ― мониторинг SSL трафика на локальной машине, но ничто не мешает перенаправить на нее трафик с удаленной машины, то есть, с приставки. В Android корневые сертификаты хранятся в папке /system/etc/security/cacerts/. Название файла должно соответствовать хэшу сертификата.
Подготовленный сертификат необходимо скопировать на флешку и далее записать в соответствующую директорию.
/system/bin/mount -o rw,remount /
cp /mnt/media_rw/6539-6535/9a5ba575.0 /system/etc/security/cacerts/
chmod 644 /system/etc/security/cacerts/9a5ba575.0
chown root:root /system/etc/security/cacerts/9a5ba575.0
/system/bin/mount -o ro,remount /
Проконтролировать корректность установки сертификата можно, вызвав системные настройки
am start -a android.settings.SETTINGS
и далее проверить наличие добавленного сертификата в меню «Security & location» => «Encryption & credentials» => Tap «Trusted credentials».
Перенаправить трафик можно либо на маршрутизаторе, либо задав системный прокси командой
settings put global http_proxy 10.2.100:8888
Выяснилось, что приставка регулярно запрашивает у производителя обновления операционной системы и приложений.
Обновление ОС запрашивается корректно, через SSL, а запросы на приложения отправляются без шифрования. Это возможность для MiTM-атаки.
Векторы атак
В итоге найденные уязвимости сложились в два вектора атак:
1. Установка отравленного системного обновления
Злоумышленнику нужно взять оригинальную прошивку, внести модификации в файловую систему, установить необходимый ему софт, собрать образ и сохранить на флешке.
Затем ему придется прийти в фойе, вставить флешку в приставку и зажать на 10 секунд стандартную кнопку перезагрузки.
Приставка уйдет в ребут и стянет с флешки новый образ. Системные разделы перезапишутся, и устройство получит новую, зловредную функциональность.
2. MiTM атака через обновление приложения
Второй сценарий сложнее технически, но не требует физического доступа к устройству. На этот раз, злоумышленнику понадобится доступ к интернет-каналу, через который приставка общается с внешним миром. Он может взломать или подменить Wi-Fi или найти щиток и подключиться в разрыв интернет-кабеля.
Главное — перехватить запрос на обновление софта от приставки и залить на нее отравленное приложение. А оно уже выполнит работу по повышению привилегий в ОС, поднимет VPN и настроит удаленный доступ, даже если приставка находится за роутером или NAT.
В обоих случаях приставка превращается в настоящий зомбоящик ― полноценный плацдарм для атак на сетевую инфраструктуру компании.
Вместо заключения: почему так вышло
Хочется найти конкретного виновника всех проблем, но, обычно уязвимость подобных устройств объясняется целым набором факторов. Этот случай ― не исключение.
Google уже давно предъявляет требования к железу, на котором выполняется Android. Например, среди них наличие многоуровневого безопасного загрузчика. Но Google не всемогущ, что бы ни говорили конспирологи. Компания не способна оценить реальную безопасность каждой железки.
В то же время, китайские вендоры довольно формально подходят к безопасности. Ведь если бы они дотошно все проверяли, их чипы уже не стоили так дешево.
Заказчики и разработчики софта, тоже не безгрешны. Первые порой и не вспоминают о безопасности и не закладывают ее в бюджет. Вторые не всегда подчеркивают, что безопасность стоит отдельных денег, допускают ошибки и остаются без времени и средств на их поиск и устранение.
В случае с приставкой, которую я тестировал, ошибки допустили по чуть-чуть на всех этапах разработки. В итоге, хотя чип и платформа имеют достаточно развитую функциональность для обеспечения безопасности, она не используется.
Производительных устройств, подключенных к сети, становится все больше, но их защищенность очень низкая. Это касается и потребительской электроники, и промышленной, автомобильной. Это общая проблема интернета вещей, который с каждым днем становится все больше, разнообразнее и умнее.
При этом средний уровень компьютерной грамотности был и остается достаточно невысоким, так что защита IoT ― задача и ответственность производителей. Причем для этого существуют готовые инструменты, просто ими необходимо правильно воспользоваться.
Хотелось бы, чтобы бизнес обращал на это больше внимания. Да, за защиту надо платить, но за ее отсутствие приходится расплачиваться. Зачастую, простым пользователям.
Что может изменить сложившуюся ситуацию? Какие технологии и подходы к разработке способны обеспечить безопасность IoT? Давайте обсудим это в комментариях.