Как много из вас обращали внимание на то сколько сейчас появилось на улицах камер наблюдения? Просто пройдясь от дома до работы недавно я насчитал их почти пол сотни. А на сколько они безопасны задал себе вопрос я.. Оказывается не так чтобы очень… Проведя несколько дней за изучением вопроса, мы подготовили материал который раскажет как взломать веб камеру видеонаблюдения многих современных моделей.
Итак, моей задачей было выбрать такого производителя, который, с одной стороны, давно присутствует на российском рынке, с другой — еще не привлекал внимание специалистов по безопасности. Мой выбор пал на корейскую фирму Microdigital, которая производит IP-камеры.
Сайт компании обещает нам широкий ассортимент: «свыше 30 моделей регистраторов, свыше 150 моделей видеокамер». Отлично!
Компания существует на рынке (в том числе и российском) уже больше двенадцати лет, а это значит, что ее продукция распространена. Оказалось даже, что в 2011 году был заключен договор на оснащение более 30 тысяч российских автобусов камерами этой фирмы.
В первую очередь меня заинтересовали устройства серии N, они достаточно продвинутые, но при этом пока что не стали объектом тестирования кого-то из исследователей. Пора исправить это! Я выбрал модель MDC-N4090W, которая предназначена для использования внутри помещений. Подробную информацию об устройстве можно почерпнуть на сайте производителя.
Изучение камеры
Начинать любое исследование железа лучше всего с изучения доступной документации.
Открываем PDF, полученный на сайте 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 тоже не составило проблем нагуглить документацию (PDF). Оказывается, архитектура чипа — 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). Ее суть заключается в том, что можно применить социальную инженерию и заставить администратора перейти по вредоносной ссылке. Это дает возможность выполнить почти любую команду из админского интерфейса. Например, можно сделать вот такую ссылку:
/webparam?user&action=set¶m=add&id=tester&pass=cGFzc3dvcmQ=&authority=0&t=1552491782708
Она будет создавать пользователя 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.
Update Network set DDNSUsage=1, DDNSHostname='', DDNSName=(select/*', DDNSName='*/Password from/*', DDNSUserName='*/User limit 1) -- ', DDNSPassword='***'
Этот запрос запишет пароль открытым текстом в поле в поле 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-камеры.
Этим же списком рекомендаций можно руководствоваться при настройке любого другого умного устройства.