Jump to content
Search In
  • More options...
Find results that contain...
Find results in...
Sign in to follow this  
mr.save

Вскрытая камера. Как искать уязвимости в «умных» гаджетах на примере популярной IP-камеры

Recommended Posts

За последние несколько лет все чаще обсуждается проблема безопасности домашних гаджетов. На слуху атаки ботнетов типа Mirai, которые поражают миллионы устройств и вредят как домашним пользователям, так и бизнесу. Этичные хакеры тоже исследуют все больше девайсов — обычно с неутешительными выводами. В этой статье я покажу все этапы проверки хардверной безопасности на примере распространенной в России модели IP-камеры. Спойлер: уязвимостей будет много.

Итак, моей задачей было выбрать такого производителя, который, с одной стороны, давно присутствует на российском рынке, с другой — еще не привлекал внимание специалистов по безопасности. Мой выбор пал на корейскую фирму Microdigital, которая производит IP-камеры.

Сайт компании обещает нам широкий ассортимент: «свыше 30 моделей регистраторов, свыше 150 моделей видеокамер». Отлично!

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

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

В первую очередь меня заинтересовали устройства серии N, они достаточно продвинутые, но при этом пока что не стали объектом тестирования кого-то из исследователей. Пора исправить это! Я выбрал модель MDC-N4090W, которая предназначена для использования внутри помещений. Подробную информацию об устройстве можно почерпнуть на сайте производителя.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Изучение камеры

Начинать любое исследование железа лучше всего с изучения доступной документации.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Открываем 

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.
, полученный на сайте Microdigital, и узнаем, что у камеры есть веб-интерфейс с пользователями root (пароль root) и anonymous.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

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

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

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

 

Подготовка устройства к тестированию

Приступим к изучению аппаратной составляющей. Для этого разбираем устройство (ничего сложного, четыре винта по периметру) и получаем печатную плату.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Также видим следующее:

  • память S34ML01G100TF100;
  • чип DM368ZCE;
  • интерфейсы: четыре пина UART, USB, MicroSD, Ethernet.

Пины, отмеченные как BLE, я не рассматриваю, так как это, скорее всего, контакты для подключения модуля Bluetooth. Нас это в данный момент не интересует.

Модуль S34ML01G100TF100 — энергонезависимая NAND-память в корпусе TSOP-48. Datasheet легко гуглится. Из него узнаем подробнее о типе корпуса (NAND08) и размере хранилища — 128 Мбайт.

Для дальнейшей работы потребуется сделать бэкап данных, чтобы в случае «окирпичивания» камеры можно было вернуть ее в изначальное состояние. Для этого идеально подходит программатор ProMan TL86 или TL866 с переходником NAND08 → DIP48.

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

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Для чипа DM368ZCE тоже не составило проблем нагуглить документацию (

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.
). Оказывается, архитектура чипа — ARM. К тому же из документации можно достать его распиновку, но нам она не потребуется.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Пройдемся по интерфейсам. Из документации очевидно, что USB и MicroSD нужны в основном для того, чтобы подключать к устройству внешние носители и использовать их в качестве хранилища. Для полноты картины можем подключить к устройству USB-фаззер facedancer21 и, используя утилиту umap2scan, получить список поддерживаемых устройств.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

К сожалению, камера не поддерживает ни одно из известных нам устройств.

Как насчет UART? Тут предстоит определить, за что отвечает каждый пин и какова скорость передачи данных. Для этого воспользуемся логическим анализатором Saleae Logic. Для удобства я подключился через проводок, который соединяет плату устройства и инфракрасные лампочки.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Пронумеруем пины для удобства.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Прежде чем включать логический анализатор, подключаем заземление к пину GND интерфейса для подключения BLE.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

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

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

После включения устройства на пине номер 3 (в программе отсчет идет с нуля и пин нумерован как 2) передаются бинарные данные. Этот пин интерфейса UART отвечает за передачу данных (TX). Просмотрев длину одного бита, получаем текущую скорость передачи — 115 200 бит/с. При корректных настройках мы даже можем разглядеть часть текста.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

У пина под номером 1 постоянное напряжение 3 В — следовательно, он предназначен для питания. Пин номер 4 связан с пином GND интерфейса для подключения модуля BLE. Значит, этот пин тоже «земля». И остается последний пин под номером 2, он отвечает за прием байтов (RX). Теперь у нас есть вся информация для общения с камерой по UART. Для подключения я воспользуюсь Arduino UNO в режиме переходника TTL.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Начинаем мониторить порт UART и получаем следующее.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

При старте устройства первым делом подгружается загрузчик системы U-Boot. К сожалению, на уровне загрузки пин TX отключен в настройках камеры, поэтому мы можем наблюдать только отладочный вывод. Через какое-то время подгружается основная система, позволяющая ввести логин и пароль для доступа в администраторскую консоль. Пара root/root (аналогичная той, что используется для веб-админки и указана в документации) прекрасно подошла.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

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

Для перехвата трафика я буду пользоваться устройством Lan Tap Pro.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

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

 

Сетевая часть

Просканируем порты утилитой Nmap и получим список открытых портов.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Пройдемся вкратце по доступным нам сервисам.

 

FTP

При подключении сервис запрашивает логин и пароль. Анонимный вход отключен. Но и тут подошел вариант root/root!

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Теперь мы можем заходить в любую директорию и получили удобный способ закидывать файлы на удаленный хост.

 

Telnet

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

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

RTSP

Для подключения к RTSP опять же нужно авторизоваться как root/root. Ссылка для подключения принимает вид rtsp://root:root@192.168.1.151:554/Primary.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Веб

Изучив устройство веб-сервера камеры, я составил вот такую схему.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

На сервере находятся скрипты на PHP и CGI-приложения, которые общаются с исполняемыми файлами из директории /usr/local/ipsca/ (преимущественно общение идет с MainProc). Для хранения всех настроек используется база данных SQLite 3.

С нее-то мы и начнем искать уязвимости. База данных хранится в /usr/local/ipsca/mipsca.db. В ней лежит все — от логов системы до настроек автоматической загрузки записей камеры на удаленный сервер. Структура базы данных видна на скрине ниже.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Мое внимание привлекла таблица User. Она отвечает за работу с данными пользователей: логин, пароль, привилегии.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

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

Переходим к скриптам на PHP. В веб-директории /root/httpd/htdocs/Web лежит три скрипта: download.php, login.php, upload.php.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Файл login.php не особенно интересен, так как PHP тут используется только для настройки компонента ActiveX, нужного для браузерных дополнений, которые стримят видео на сайте.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Файл download.php принимает на вход название файла для скачивания, проверяет его расширение и, если такой файл найдется в папке updownload, отправляет в ответ его содержимое.

В скрипте нет проверки названия файла, так что если кто-то вдруг решит положить в этот каталог исполняемый скрипт на PHP, то его содержимое при запросе будет скачиваться (обрати внимание на переменную $file_type, которая будет пустой в случае неизвестного расширения).

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Последний файл — upload.php тоже оказался не без багов: в нем есть возможность отправлять файлы не только с расширением из белого списка (.dat и .DAT), но и с пустым расширением.

Вайтлист расширений задается следующей строкой.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Теперь, если значение расширения не пустое, проводится проверка на наличие расширения в массиве, который получен из $allowExt. В качестве разделителя используется запятая.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Но если расширение пустое, исполнение не дойдет до этого условия и проверка не выполнится. Однако для эксплуатации этот баг бесполезен.

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

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Он очищает директорию updownload от ранее загруженных туда файлов, а в интерпретаторе Bash, который входит в BusyBox, стоит ограничение на длину названия файла в 256 символов. Получается, что скрипт не сможет удалить файлы, названия которых длиннее этого значения.

Так как у upload.php нет никакой авторизации, любой пользователь может загрузить сколько угодно файлов с именем длиннее 256 символов, и это приведет к заполнению всей памяти устройства. Другими словами, Denial of Service.

Пример загрузки файла.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

И получение списка файлов в директории /updownload/ через консоль Bash.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

На этом мы можем завершить изучение скриптов на PHP и перейдем к самой большой части исследования — CGI-приложениям.

Приложения CGI на IP-камере отвечают чуть ли не за все действия в администраторской веб-панели, начиная с авторизации и заканчивая обновлением устройства.

Я разделю описание работы на тестирование «невооруженным глазом» (уязвимости, для нахождения которых не нужно реверсить исполняемые файлы) и собственно реверс этих самых бинарей.

При тестировании «невооруженным глазом» нашлись две уязвимости. Первая позволяет проводить атаки подделки межсайтовых запросов (то есть CSRF). Ее суть заключается в том, что можно применить социальную инженерию и заставить администратора перейти по вредоносной ссылке. Это дает возможность выполнить почти любую команду из админского интерфейса. Например, можно сделать вот такую ссылку:

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Она будет создавать пользователя tester с паролем password.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Когда я изучал трафик в Burp Suite, я долго не мог найти ответ сервера, где браузеру высылаются cookie с данными авторизации (username, auth и password). Оказалось, что искал зря: эти данные выставляются на стороне клиента через код на JavaScript в файле /inc/js/ui.js.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

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

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Тут-то и появляется вторая уязвимость: даже если мы не отправим cookie-переменную password, сервер все равно успешно обработает наш запрос!

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

То есть достаточно знать логин админа (который по умолчанию — root), чтобы обойти авторизацию и совершать любые вызовы, доступные администратору в административной веб-консоли камеры! И это мы нашли, даже не изучая код приложения. Посмотрим, что же будет в самом коде.

 

Изучение бинарных приложений

Для изучения исполняемых файлов потребовались некоторые приготовления. А именно:

  • установка статически скомпилированного отладчика GDB из публичных репозиториев на GitHub;
  • установка карточки MicroSD с файловой системой VFAT (что позволяет получить дополнительное место).

Сам процесс исследования скомпилированных приложений выглядит так.

  • Изучение приложения в IDA Pro.
  • При необходимости — отладка приложения в GDB на самой камере через Telnet. Кстати, поскольку приложение многопоточное, пришлось каждый раз проверять нужный process id для взаимодействия с определенным потоком (поток создается до обработки запроса).
  • Написание proof-of-concept для демонстрации уязвимости.

Почти все командные веб-запросы отправлялись по адресу /webparams. Изучив настройки httpd, которые хранятся в файле /usr/local/httpd/conf/httpd.conf, определяем, что все запросы на /webparam перенаправляются в исполняемый файл FCGI по пути /usr/local/httpd/fcgi/webparams.fcgi.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Это исполняемый файл для 32-битного ARM. На нем-то я и решил сконцентрироваться.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Произвольные команды FTP

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

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Далее можно нажать на кнопку Test и проверить соединение. Будет вызвана функция по адресу 0xaeb0. Для удобства будем изучать псевдокод функции, полученный при помощи Hex-Rays Decompiler.

Создание подключения.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Авторизация на FTP-сервере.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Смена текущей директории значением, переданным аргументом.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Создание временного файла.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Проблема безопасности обнаружилась уже на третьем пункте. Функция ftp_CWD, находящаяся по сдвигу 0xA9F0, не проверяет наличие в строке-пути некорректных символов, таких как перенос строки.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Это позволяет отправлять произвольные команды FTP — достаточно добавить байты \r\n в значение директории для загрузки файлов. Значит, мы нашли SSRF.

Например, можно сделать запрос к FTP-серверу камеры и добавить к нему команду, которая создает директорию /tmp/123 (GET-переменная uploadpath как раз отвечает за путь до требуемой директории).

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Переходим в /tmp/ на камере и видим созданную папку 123.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Path Traversal и проверка наличия файлов

Следующая интересующая нас возможность веб-сервера — синхронизации часов по протоколу NTP.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

За изменение параметров отвечает функция по сдвигу 0x12564. Не будем вдаваться детально в принцип ее работы, обратим лишь внимание на переменную TZ (Time Zone).

Первые 32 байта GET-параметра TZ заносятся в переменную get_TZ_32b.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Значение конкатенируется с путем до директории, где хранятся настройки временных зон, и проверяется наличие такой директории (или файла) в файловой системе устройства.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

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

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Если объединить все три пункта, то получится, что мы можем не только манипулировать полным адресом директории (Path Traversal), но и определять по ответу от сервера наличие файла в файловой системе. Чтобы удостовериться в этом, отправляем запрос, который проверит, существует ли файл /etc/passwd.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

И посмотрим, что будет, если файла нет.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

SQL-инъекция

Переходим к более серьезным уязвимостям. Конфиги камеры хранятся в базе SQLite 3, и почти все действия на веб-сервере приводят к взаимодействию с ней. Так вот, оказалось, что почти все запросы к базе данных со строковыми параметрами могут проходить с некорректно форматированным вводом. А это, как ты мог догадаться, SQL injection! Для примера разберем одну из уязвимых форм — форму редактирования настроек DNS.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

При редактировании этих параметров отправляются два запроса на сервер — запрос на модификацию информации и запрос на получение текущих настроек.

Пример запроса на модификацию информации.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

За обработку такого запроса отвечает функция по сдвигу 0x18374. В начале идет считывание GET-параметров запроса (до 32 байт каждый) и проверка того, заполнены ли они.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Далее — вызов функции strip, которая убирает символы «пробел» и «табуляция» в начале и в конце строк.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Теперь полученные строки отправляются в функцию, которая делает SQL-запрос Update к базе данных SQLite 3.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Проблема в том, что при передаче строк используется не %q (безопасный вариант), а %s, в связи с чем мы можем выйти за пределы строки и добавить свои SQL-инструкции в запрос (кстати, если отправляется целочисленный параметр, то лучше всего использовать %d).

Ниже — пример эксплуатации.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Во время обработки этого запроса создается следующая команда SQL.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Этот запрос запишет пароль открытым текстом в поле DDNSName первого аккаунта из таблицы User. Остается запросить текущие настройки DDNS.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

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

Аналогичную проблему можно наблюдать еще у 25 различных GET-параметров, разбросанных по всему веб-серверу (часть параметров требуется предварительно кодировать в Base64).

 

Переполнение стека

Когда я перебирал параметры, подверженные атакам типа SQL injection, мое внимание привлекла функция, которая обрабатывает переменную action, расположенную по смещению 0x155D0. Начало псевдокода функции — на скриншоте.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

На 78-й строке вызывается функция GET_val. Она в качестве аргумента принимает строку — название GET-переменной и возвращает строку — значение этой переменной.

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

Первый аргумент функции был объявлен на 53-й строке.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Для этой строки выделяется четыре байта, а потом в первую ячейку помещается нулевой байт, обозначающий ее окончание.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Выходит, что для переполнения стека потребуется в аргументы функции strcat отправить две строки. Тогда длина второй строки будет больше трех байт (четвертый байт нулевой и выставляется автоматически).

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

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Флаг NX отключен, а это значит, что можно исполнить код, расположенный в любой области памяти, — в том числе тот, который мы разместим в процессе работы.

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

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Флаг 1 означает, что адрес стека будет случайным при каждом запуске. Но изначально второй аргумент функции strcat (то есть аргумент GET-переменной action) записывается в кучу, а значит, мы можем им воспользоваться.

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

Удостовериться в этом можно, отправив следующий запрос.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

При отладке процесса исполняемого файла webparam.fcgi получаем ошибку программы, которая пытается перейти по адресу BBBB.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Теперь остается дописать исполняемый код (шелл-код) после адреса возврата и перезаписать адрес возврата на адрес нашего вредоносного кода, который хранится на куче. В примере используется исполняемый код, который открывает порт 10240 и дает доступ в командную оболочку без авторизации (Bind Shell).

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Проверяем сетевую активность на устройстве.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Процесс 1263 программы webparam.fcgi начал прослушивать порт 10240 на всех интерфейсах. Подключимся к нему через netcat.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Нам доступен шелл с привилегиями пользователя nobody.

Аналогичная проблема переполнения буфера и у переменной params. Способ эксплуатации не сильно отличается от описанного, поэтому не будем на нем останавливаться.

 

Подмена файла прошивки

Одна из самых популярных проблем у устройств IoT — это отсутствие подписи у файла прошивки. Конечно же, она не обошла и эту камеру. Что это нам дает? Все просто: мы можем добавить свой код в прошивку устройства и таким образом заразить его, причем так, что восстановление будет возможно, только если имеется дамп памяти, а есть он (и необходимые навыки) далеко не у любого владельца.

Администраторам устройства доступен интерфейс для обновления прошивки (внизу страницы).

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

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

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Это .tar, в котором лежат файлы PackageInfo.txt и UpdatePackage_6400.0.8.5.bin. Второй, в свою очередь, оказался архивом.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

После распаковки нам стала доступна следующая файловая иерархия.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

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

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

На восьмой строке указывается контрольная сумма файла .bin. То есть это поле тоже потребуется отредактировать при отправке кастомной прошивки, иначе камера посчитает файл поврежденным и система обновлений проигнорирует его. Эту уязвимость можно отнести к типу RCE — удаленное исполнение произвольных системных команд.

 

Повышение привилегий

Напоследок — еще одна уязвимость того же типа, но уже с повышением привилегий до root! Если вставить в камеру карточку MicroSD, то из веб-интерфейса можно удалять файлы с нее.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

При удалении файла браузер отправляет по HTTP вот такой запрос.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

За обработку запроса на стороне сервера отвечает все то же приложение webparam.fcgi, но в данном случае оно передает его в другую программу — MainProc. Это тоже бинарное приложение.

Изучив MainProc, я определил, что GET-переменная filename объединяется со строкой и передается в функцию system без какой-либо фильтрации. А это означает, что можно исполнять произвольный код от имени пользователя, который запустил MainProc, то есть root.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Proof-of-concept: создаем файл /tmp/test.txt со строкой hacking.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.

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

 

Подводим итоги

Во время исследования было обнаружено более десяти разных, в том числе и критических уязвимостей IP-камеры Microdigital. Полный список из двенадцати CVE ты можешь найти 

Скрытый контент

    Дайте реакцию на этот пост, чтобы увидеть скрытый контент.
.

Важный момент в том, что файл прошивки, предоставленный производителем на сайте, общий для всех шести IP-камер серии N. И вероятнее всего, часть найденных уязвимостей присутствуют и в других устройствах Microdigital, которых, как говорилось в начале статьи, «свыше 150 моделей»!

Также стоит упомянуть, что на конференции Positive Hack Days 8 был конкурс на взлом IP-камер — CAMBreaker. Среди подопытных числилась и эта модель. Одним из призеров конкурса был Иван Анисеня, который, как оказалось, еще в прошлом году нашел уязвимость внедрения произвольных SQL-запросов и с ее помощью обошел авторизацию на этой камере.

Остается животрепещущий вопрос: как защитить периметр от злоумышленников, если в нем есть подобная камера? Для обеспечения безопасности нужно:

  • установить камеру в физически недоступном для злоумышленника месте;
  • внимательно изучить документацию;
  • отключить невостребованные сервисы, например FTP;
  • сменить все пароли и, желательно, имена пользователей устройства;
  • закрыть на стороне шлюза (чаще всего в роли шлюза выступает роутер) port-forwarding до IP-камеры.

Этим же списком рекомендаций можно руководствоваться при настройке любого другого умного устройства.

Share this post


Link to post

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

×
×
  • Create New...