Приветствую!
В этот раз я хотел бы рассказать о своём первом проекте в компании BI.ZONE. Дело было давно, девайс (Wisenet HRX-1620
) уже не выпускается и не обслуживается, поэтому за давностью лет можно и поделиться. Заодно это предостережёт вас от использования этого устройства на объектах и поможет защититься.
Где-то на третий день работы мне вручили «посылку» с надписью «Wisenet». Внутри лежало несколько камер видеонаблюдения и одна большая коробочка:
Загуглив название железки, я нашёл сайт с прошивками, скачал самую свежую и полез распаковывать.
Содержимое прошивки
Основной файл с расширением .img
на деле оказался обычным .tar.gz
. Если его распаковать, вашему взору предстанут следующие файлики:
Большая часть файлов зашифрована (пока непонятно как), но вы обязательно заметите один интересный ELF-файл: swupgrader
.
Такая схема достаточно часто используется во всяких файлах обновлений: в архив кладутся какие-то бинари, а с ними — программа или скрипт для установки.
Конечно, первым делом я открыл этот самый swupgrader
в надежде найти ключ, которым была зашифрована прошивка.
Ключей там не нашлось, но обнаружилась очень подробная система логирования (классика), где у всех важных функций были указаны имена:
Таким образом мне удалось найти функции, которые назывались DecryptFile
и DecryptImageFiles
. В последнюю, кстати, передавалось имя какого-то странного бинаря protector
, в сочетании с которым во второй функции формировалась команда следующего вида:
protector bin_file 1
Судя по всему, этот скрипт или программа как раз таки и расшифровывали все нужные файлы. Но, очевидно, доступа к «протектору» у меня не имелось (пока что).
Раз уж в swupgrader
больше ловить нечего… Так, стоп! А как же классическая тема с подменой бинаря на свой с целью его запуска? Да, это сработало, но не сразу — процесс апгрейда почему-то падал.
Причину падения удалось выяснить немного позже (спойлер: криво собирался армовский «эльф»), поэтому я решил пойти немного другим путём: попробовать расшифровать бинари по-тупому — а вдруг там простейший XOR?
Внимательный реверсер обнаружит здесь повторяющийся паттерн, который может говорить только об одном: да, используется тупой XOR с одним и тем же ключом для каждого блока. Длина ключа оказалась 16
байт. Далее я сделал предположение, что в конце прошивки идут либо нули, либо FF
. Соответственно, чтобы получить сам ключ, нужно поксорить повторяющиеся байты на 0xFF
или взять как есть. Оказалось, первое. Так я и получил файлы прошивок.
Ну а дальше дело техники: замаунтить обнаруженную внутри JFFS2
(Journaling Flash File System version 2) и другие файлы (ext2
), извлечь содержимое и провести полноценный анализ.
Что обнаружилось внутри
Конечно же, первым делом я полез смотреть, что из себя представляет protector
и насколько плохо он расшифровывает файлы (спойлер: очень плохо!).
Попробуйте найти здесь ошибку:
Далее нужно было получить persistence (закрепиться на системе), чтобы отлаживать встроенные приложения в динамике и баловаться с возможными переполнениями (да, они тут тоже есть). Казалось бы, достаточно просто добавить в автостарт нужные telnet
и GDB
(я использовал IDA debug server
), запаковать и зашифровать всё обратно — да и готово. Но нет. В самом начале, при распаковке .tar.gz
, архиватор сообщил мне, что в конце архива имеются неиспользуемые данные. Посмотрим на них:
Видим структуру, которая начинается на AA CC BC BB
и заканчивается на BC CA AB BC
, и каких-то два дворда: 0x012A
и 0x059F29D5
. С первым удалось определиться достаточно быстро — это количество блоков по 0x80000
. Ну а второе, как можно уже догадаться, — это контрольная сумма CRC32
(полином удалось подобрать — 0x04C11DB7
).
Затем я написал пересобиралку, включил необходимые мне FTP, Telnet и отладку, после чего залил на устройство в надежде, что оно после этого заведётся. Завелось!
Ну а дальше начинается исключительно пентестерская тема. Нам понадобятся знания реверс-инжиниринга и написания ROP-цепочек, так как реверсить придётся не простой скриптец на JS, PHP или ещё на чём, а нормальный такой ELF-CGI.
Реверсим веб
Если честно, я достаточно слаб в безопасности web-приложений, но зато неплох в реверсе бинарей. Поэтому мне проще найти уязвимости именно в них. Но, «бурпом» пару раз я таки пользовался, поэтому запустил его, открыл веб-интерфейс видеорегистратора и стал тыкать во всякие менюшки и кнопочки.
Выяснилось, что всё в железке работает на CGI-скриптах, которые общаются между собой посредством линуксовых очередей сообщений. Я не буду сильно вдаваться во взаимодействие сервисов на устройстве, а сразу перейду к тому, как мне удалось найти уязвимость.
Уязвимость номер 1
Взяв самый часто используемый CGI (по мнению того же Burp), я стал передавать в его параметры длинные строки — авось что-то упадёт. И оно упало! Далее я выполнил поиск по строкам бинаря, нашёл место, где этот аргумент парсился, а там обнаружил вот такой интересный кусок кода:
Здесь содержимое параметра msubmenu
считывается между символов &
и =
, после чего записывается в буфер размером 80
байт. Эксплуатируемость этой уязвимости не очень высокая: в GET-запрос нельзя запихнуть большинство символов, а urldecode
на данном этапе ещё не происходит. Поэтому перейдём к уязвимости номер 2.
Уязвимость номер 2
Эта штука посерьёзнее: ограничений на символы практически нет, за исключением 0x00
и ещё некоторых. Взглянем на неё:
Видим, что из хедера HTTP-авторизации читается содержимое переданного в функцию имени поля в аргументе name
. Всё, что находится между символами двойных кавычек, будет скопировано по указателю dest
. Посмотрим на место вызова этой функции:
Сначала очищается буфер tmp
размером 0x800
, а потом передаётся в функцию get_http_auth_key()
. Сам же буфер лежит, конечно же, на стеке. Вот он:
Эксплуатируемость налицо (а точнее, на стек). Пиши ROP-цепочку и вперёд. Только вот есть одно НО: включённый ASLR
.
Обходил я его довольно просто. Под отладкой я заметил, что диапазон адресов, по которому грузится libc,
достаточно ограниченный, а значит, проще будет его забрутфорсить. Почему это сработает? Всё потому, что при обращении к CGI-скрипту lighttpd
его поднимает, если тот ещё не запущен. Поэтому даже если наша цепочка пойдёт не туда, всё упадёт, а потом поднимется. Звучит крайне неплохо. Так я смог выполнять любые команды по сети.
Добиваем железку
Далее мне стало интересно, как и где хранится пароль от учётки admin
. Посмотрев, какие файлы обновляются при изменении пароля, я выяснил, что мне нужен nvrConfig.xml
, который располагается на внешнем HDD (видимо, на случай восстановления). Данные зашифрованы с помощью AES-CBC
и пароля #5i#$@bmb$mf75ads89egs@#$bcx798!
плюс Base64
. Чтобы менять их удалённо, нужно было всего лишь повозиться с магией sed
и заменой по регекспу, после чего я мог менять пароль динамически.
Общение с вендором
Конечно же, мы уведомили разработчика девайса об уязвимости. Меня даже попросили прислать PoC, что я и сделал.
Спустя время мне ответили приблизительно следующее: «Спасибо, что обнаружили уязвимость. Вообще наши внутренние тестировщики уже нашли её год назад, но, так как устройство уже находится в стадии End of Life, обновления мы не выпускаем».
В общем, единственный здравый совет здесь: ограничить доступ к HTTP-портам Wisenet HRX-1620
с недоверенных MAC- и IP-адресов. А лучше вообще выключить доступ по HTTP или перестать пользоваться устройством в пользу другого.
SSLHTML
Ваши изыскания и наработки просто прекрасны и являются отличным материалом для моего обучения, без специальных знаний. Спасибо за подробное пояснение ваших шагов.
Очень хотелось бы предложить написать самоучитель для начинающих реверсёров или "палетку", т.е. мануал для действий при попадании в тупик.
Также интересно, вы реверсите в основном на Unix-системах или всё-таки на Win?
Спасибо!
DrMefistO Автор
Если вопрос про инструментарий, то IDA под виндой, Ghidra под любыми работает. Если о целевых платформах, то попадается всякое. Предпочтений нет.
Писать самоучитель желания нет, т.к. всё и так в сети: видео, статьи - брать да изучать:)
SSLHTML
Понял вас, Владимир. Просто есть специалисты, которые со скрипом "работают" под Win. Вы-универсал. Прошу прощения за глупый вопрос, а IDA не перекрывает возможности Ghidra? Я сейчас пытаюсь осваивать Radare2. Полагаю, что вы слышали о нём.
Вот, как раз я и изучаю по таким вот постам исследователей и видеороликам в youtube. Хочется, чтобы они были описаны также, как делаете вы. Это удобно и не утомляет, в отличии от занудного бубнения англоязычных исследователей.
DrMefistO Автор
У Иды нет возможности написать свой собственный процессорный модуль и декомпилировать что угодно, а у Гидры - есть. Под PE-файлы Ида конечно лучшая. Я как-то писал статью про сравнение Иды и Гидры.
SSLHTML
Спасибо! Сейчас поищу и ознакомлюсь с вашей статьёй. Буду дальше изучать хотя бы примитивные возможности IDA и Ghidra.