此为前篇,主要是静态分析。
描述
TP-Link TL-WR841N V10(固件版本 3.16.9)设备上的 httpd 中的缓冲区溢出允许经过身份验证的远程攻击者通过 GET 请求向 Wi-Fi 网络配置页面执行任意代码。
本文环境
本机环境是ubuntu20.04,建议把虚拟机放到SSD里,不然起漏洞环境的时候会特别卡
固件获取: Tải về cho TL-WR841N | TP-Link Việt Nam
漏洞环境的搭建会放在文末。
漏洞分析
程序调用链
在main函数中调用httpd()
和httpBasicRpmInit()
进行配置和初始化。
在httpd()
中调用了httpInit()
来初始化。
httpInit()
会调用httpServerCreate()
函数,以创建http Server,然后经由 httpServerCreate() -->sub_4F5CD0() --> httpDispatcher()
这条调用链调用httpDispathcer()
Dispatcher分析
当一个REQUEST提交时,httpGenListDataGet()
函数将被调用并返回一个 LIST_ENTRY
指针,其指向了一个函数指针列表,这些函数用来处理对应的URL。
然后,程序将调用httpGenListFuncGet()
函数来返回列表中的某个函数指针,
并检查该函数对应处理的URL是否出现在REQUEST中。若检查通过,则将调用该函数,否则继续从列表中取回函数指针并检查URL,重复此过程直至检查通过。
由此我们可以总结出来Dispatcher的流程图
接下来, 程序通过httpBasicRpmInit-->httpWlanInit()-->httpWlanBasicCfgRpmsInit()-->httpRpmConfigAdd()
函数获取 request_url 对应的函数指针,然后调用函数。
漏洞函数分析
好了,铺垫结束。现在分析本漏洞的主角stringModify()
单就本函数而言,Ghidra反编译的结果可读性明显高于IDA
1 | int stringModify(char *dest,int len,int src) |
通过分析这个函数,我们可以知道这个函数是用来转义/过滤一些特殊字符。问题出在,向dest缓冲区添加字符串<br>
,数据增加了4个字节,但index只增加了1个字节,所以会导致index小于实际长度,从而导致。 可能会导致缓冲区溢出。
然后我们查看函数被调用的地方,可见,我们只要合理构造参数a3,就可以让栈上的v8溢出。
然后查看交叉引用,找到可以控制参数a3的地方。这里找到的是sub_45FA94
,该函数在之前httpWlanBasicCfgRpmsInit()
中作为回调函数出现过。 该函数接收GET请求的参数,并调用漏洞函数。
这个wlanConfig
是我自己分析重建的结构体,结构如下
1 | 0x00 | | |
如果后面这些参数缺省的话就默认是0x00000001,如果小于某个值(比如对于Mode就是8)就会被设定为这个值。由于包含/x00,这两种情况都需要避免。
动态调试
确定偏移
为了方便查看在 0x0043BC24 和 0x0043BCA8 下断点,前者观察 ssid 传入值是否符合预期,后者观察 writePageParamSet 返回上层函数时的寄存器状态。
如果执行先前的POC,寄存器会是如下情况
于是我们可以得到寄存器的offset:填充 “/%0A”*0x55+’aa’ 之后,依次可以控制 s0-s02 、ra 寄存器的值。