
Доказательство концепции эксплойта для CVE-2020-12124, нацеленного на маршрутизатор Wavlink AC1200, демонстрирующее неаутентифицированную инъекцию команд и переполнение буфера стека в CGI-интерфейсах.
изначально на https://www.klogixsecurity.com/scorpion-labs-blog/anatomy-of-an-iot-exploit-from-hands-on-to-rce
автор: David E. Baker, опубликовано 1 июня 2023 года
Данное исследование касается прошивки беспроводного гигабитного роутера Wavlink Wireless-AC1200 по состоянию на июнь 2020 года. Обсуждаемые здесь уязвимости могли быть или не быть исправлены производителем, но это пример исследования уязвимостей, где главная ценность — сам процесс, а не его результат. Автор провёл это исследование до публичного раскрытия уязвимостей, но после того, как они были независимо обнаружены другими исследователями и сообщены производителю.
Производитель предоставляет прошивки для своих продуктов в разделе поддержки на своём веб-сайте; это распространённый способ получения IoT-прошивок и полезная альтернатива извлечению их из памяти устройства. Прошивка не зашифрована, поэтому её можно легко извлечь с помощью binwalk. Динамический анализ проводился при наличии физического образца устройства, а статический анализ — через Ghidra.
Веб-интерфейс беспроводного гигабитного роутера Wavlink Wireless-AC1200 содержит несколько уязвимых конечных точек, которые позволяют неограниченно копировать предоставленные пользователем данные в стек приложения или даже напрямую в командную строку для выполнения произвольных команд.
Первоначальное сканирование устройства показало, что единственным открытым ресурсом была административная веб-консоль, доступная аутентифицированным пользователям в локальной сети через HTTP на TCP-порту 80. Устройство может предоставлять и другие услуги, но они не включены по умолчанию. Поэтому данное исследование сосредоточено только на веб-интерфейсе.
Результат nmap-сканирования образца устройства, показывающий только
прослушивание веб-интерфейса.
Обычные тесты — такие как типичные инъекции команд на диагностических
панелях устройств, позволяющие внедрить команду в параметры ping
или traceroute, — не дали немедленно интересных результатов,
что было разочаровывающе.
Доступные опции управления после аутентификации в
административной веб-панели. «USB Storage» виден как второй пункт.
Первый (в конечном счёте эксплуатируемый) интерфейс, который был исследован, находился на панели «USB storage» (второй пункт на скриншоте выше). Устройство имеет порт USB рядом с разъёмами 802.2 Ethernet, что предполагает возможность работы в качестве сетевого хранилища (NAS).
Фотография задней панели реального образца, показывающая
наличие USB.
Простой принцип исследования уязвимостей: чем больше компонентов взаимодействует с кодом и чем больше движущихся частей, тем вероятнее наличие эксплуатируемого кода. Наличие функций NAS многообещающе, поскольку указывает на код, который одновременно взаимодействует с программным уровнем устройства, аппаратным уровнем и подключённой периферией (самим USB-накопителем).
Интерфейс управления консолью USB Storage показан ниже.
Одно только поле «Workgroup» обнадёживает, так как предполагает,
что этот WiFi-роутер может даже пытаться взаимодействовать через
Server Message Block (SMB) — большая задача для IoT-роутера.
Я не могу сосчитать, сколько раз видел, как пользовательский ввод
напрямую передавался в командную строку в качестве аргумента
функции Unix smbpasswd.
Опции USB-накопителя, доступные аутентифицированным пользователям.
Первоначальные попытки изменить эти настройки не удались из-за того, что устройство не обнаружило USB-диск, как показано ниже.
Изменения конфигурации параметров USB Storage не будут
сохранены, пока в USB-порт устройства не будет вставлен
отформатированный соответствующим образом диск.
Однако, как только правильно отформатированный диск был вставлен, устройство позволило задать FTP-имя пользователя и пароль. Как и предполагалось, оно поместило этот пользовательский ввод в командную строку:
Инъекция команды в поле «password» даёт первый доступ к
оболочке непосредственно к операционной системе устройства.
Хотя это и интересно, но данная уязвимость не вызывает чрезмерного восторга: она требует не только аутентифицированного доступа к административному интерфейсу устройства, но и физического доступа к устройству для манипуляций с USB-диском. Описанный выше эксплойт позволяет исследователю взаимодействовать с отдельными компонентами операционной системы (и извлекать их для целей обратной разработки).
Устройство работало на базе Linux с BusyBox, веб-интерфейс
обеспечивался Lighttpd. Функциональность Common Gateway Interface (CGI)
предоставлялась отдельными бинарными файлами в /etc_ro/lighttpd/www/cgi-bin/,
причём веб-запросы к CGI URI запускали эти бинарники напрямую.
Быстрый взгляд на nas.cgi в Ghidra показывает инъекцию команды
на строке 38 ниже, которая отправляет предоставленный пользователем
пароль напрямую в функцию do_system (сама по себе это просто
обёртка вокруг стандартного системного вызова libc).
Пользовательский ввод помещается в командную строку как аргумент
скрипта chpasswd.sh на строке 38, что приводит к инъекции команды
и доступу к оболочке непосредственно к операционной системе устройства.
Просмотр каталога /cgi-bin/ сводит задачу поиска более
интересного эксплойта к перечислению доступных пользователю
CGI-интерфейсов, показанных ниже:
Полный список CGI-бинарников, доступных на устройстве,
полученный из оболочки, установленной с помощью эксплойта, описанного
в этом разделе. Пользовательский ввод помещается в командную строку как аргумент
скрипта chpasswd.sh на строке 38, что приводит к инъекции команды
и доступу к оболочке непосредственно к операционной системе устройства.
При первоначальном рассмотрении выделяются несколько моментов.
Первое важное замечание: CGI-бинарники часто вызывают функцию
check_valid_user. Этот метод проверяет, сохранён ли IP-адрес,
с которого поступает запрос, в определённом временном файле в
файловой системе. Минимальное тестирование показывает, что статус
аутентификации клиента не проверяется до вызова этого метода,
поэтому вся поверхность кода в каждом CGI-бинарнике до вызова
этой функции доступна без аутентификации.