当前位置:   article > 正文

路由器固件安全漏洞分析——开端入坑_固件漏洞

固件漏洞

前言

今日我们开一个新坑,——路由器固件的分析与漏洞挖掘。

尽管网上文章分析不少,但我还是感觉缺少点什么........虽然本人实力有限,比不上那些逆向大佬。我还是喜欢把自己的思路分享给大家。

固件的分析不同与常规的web网站。我们没有这款固件开发的原始的.c代码,只能利用工具提取固件的文件系统,使用逆向软件分析固件的可执行程序。如ida pro 在逆向界面中我们只能看到的是一条条指令操作着寄存器,栈空间地址。使用软件的反汇编功能F5查看程序的伪代码,这种代码在功能上与源码无差,但实际上代码阅读性上可谓是差了大节。

二进制安全底层的知识,我从来不觉的有很复杂。只是现在的书籍资料经常把一些知识讲的非常晦涩且庞大。这点尤其是在计算机底层原理这块,满篇大论让人云里雾里.....,而且它们总是在说是什么,没有从初设计者的想法出发思考为什么要这么做,做的过程中遇到了什么问题,是如何解决的.最终才形成这样的一个庞大的系统.....

在开始本章前我希望您具备或者说你有这样的理念

1.什么是固件?可以用来干什么?开发的大致流程?
2.指令是什么?指令的分类 ? 为什么这样分类?-----引出架构
3.程序执行内存是怎么分布的?或者说可以怎么分布?
4.栈的原理及调用(很重要)函数调用栈的变化!
5.socket编程c语言版,如何使用c开发自己的web服务器?

固件仿真解决方案

推荐一个项目---一键模拟仿真固件

GitHub - liyansong2018/firmware-analysis-plus: Simulate firmware with one click of firmadyne (使用 firmadyne 一键模拟固件)Simulate firmware with one click of firmadyne (使用 firmadyne 一键模拟固件) - GitHub - liyansong2018/firmware-analysis-plus: Simulate firmware with one click of firmadyne (使用 firmadyne 一键模拟固件)icon-default.png?t=N7T8https://github.com/liyansong2018/firmware-analysis-plus

项目的安装,看项目介绍,有很多坑要安装很多的依赖包。本人也是纯小白,待熟练后考虑出一期专门的踩坑教程

必使用功——binwalk 这个工具在上面的项目依赖中已经有了。如果要单独安装ubuntu官方源apt get就可以直接装。

本次测试的固件下载地址

D-Link Technical Support

我们下载固件版本B03

 binwalk -Me xxxxx.bin 可提取固件的文件系统

在提取的过程中我们可以从固件中得到一些信息,压缩信息 地址信息 文件系统 大小端 等

在提取后的squashfs-root文件夹中,我们会得到一个liunx的系统文件目录,也侧面说说明最初的开发就是在这样的系统上运行的

固件仿真,在firmware-analysis-plus中执行命令

./fap.py -q /qemu-builds/2.5.0/ DIR823GA1_FW102B03.bin

访问192.168.0.1,仿真模拟成功。

固件分析解决方案

IDA pro 网上搜索下载

binwalk -Me xxxxx.bin 可提取固件的文件系统

本次漏洞分析前置知识

SOAPAction

SOAPAction

SOAPAction 是一个 HTTP 头部(Header),用于指定在 SOAP(Simple Object Access Protocol)请求中要调用的 Web 服务操作。SOAP 是一种基于 XML 的协议,它允许网络上的计算机通过 HTTP 通信并交换结构化信息。尽管 SOAP 可以使用不同的传输协议,但最常见的是通过 HTTP 或 HTTPS 进行通信。

SOAPAction 的作用

当客户端向服务器发送一个 SOAP 请求时,SOAPAction 头部指明了要执行的特定操作。这有助于 Web 服务框架理解请求的目的,并将请求路由到正确的服务方法或操作处理程序。

在某些情况下,SOAPAction 头部也可以用来实现一定级别的网络安全策略,例如,通过检查 SOAPAction 来限制对敏感操作的访问。

示例

假设你有一个 Web 服务,它提供了一个名为 GetUserInfo 的操作,客户端在发送请求时,HTTP 头部可能包括类似以下内容的 SOAPAction

SOAPAction: "http://example.com/webservices/GetUserInfo"

这告诉服务器,该请求意图调用 GetUserInfo 操作。

在 HTTP 请求中的位置

SOAPAction 头部直接包含在 HTTP 请求中,紧跟在其他标准 HTTP 头部之后,例如 Content-Type。一个典型的 SOAP 请求可能看起来像这样:

POST /service.svc HTTP/1.1
Host: example.com
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://example.com/webservices/GetUserInfo"
​
<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body>
        <GetUserInfo xmlns="http://example.com/webservices">
            <!-- 请求数据 -->
        </GetUserInfo>
    </soap:Body>
</soap:Envelope>

注意事项

  • 在 SOAP 1.1 中,SOAPAction 头部是必需的,但在 SOAP 1.2 规范中,它被定义为可选,并且其用途和行为有所不同。在 SOAP 1.2 中,操作信息通常通过其他机制,如 WS-Addressing 标准中的 Action 头部来指定。

  • 虽然 SOAPAction 头部可以增强 Web 服务的自描述性,但它也可能暴露服务的内部结构,因此在设计 Web 服务时应考虑到安全性问题。

  • 确保客户端和服务器对 SOAPAction 头部的使用达成一致,特别是在使用第三方服务时,需要注意遵循服务提供者的指导和规范。

goahead

GoAhead 是一款轻量级、高性能、可嵌入的 Web 服务器,它被设计用于小型到中型的设备和应用,例如家庭网关、路由器、打印机、家庭自动化设备和其他嵌入式设备。GoAhead 被广泛用于工业和消费级产品中,因为它非常适合资源受限的环境。

主要特点

  1. 轻量级:GoAhead 设计紧凑,内存占用小,适合嵌入式系统。

  2. 跨平台:支持多种操作系统,包括 Windows、Linux、macOS 以及各种嵌入式操作系统。

  3. 易于扩展:提供了简单的 API,使得开发者可以容易地添加自定义的动态内容处理器。

  4. 安全:支持基本的安全特性,如 SSL/TLS 加密、基本认证和摘要认证等。

  5. 支持标准:支持 HTTP/1.1、CGI/1.1、WebSocket 等网络通信标准。

使用场景

GoAhead 常用于那些需要内置 Web 服务器功能的设备或应用中,例如:

  • 嵌入式设备的配置界面

  • 控制面板和监控系统

  • 小型 Web 应用

  • IoT 设备和网关

官方手册

Quick Start

在 GoAhead Web 服务器中,您可以使用 websUrlHandlerDefine 函数来自定义路由。以下是一个示例

  1. #include <stdio.h>
  2. #include "goahead.h"
  3. // 自定义路由处理函数
  4. static bool myCustomHandler(Webs *wp)
  5. {
  6. // 处理请求逻辑
  7. printf("Received request for path: %s\n", wp->path);
  8. // 发送响应
  9. websHeader(wp);
  10. websWrite(wp, "Hello, World!");
  11. websFooter(wp);
  12. return true;
  13. }
  14. int main(int argc, char **argv)
  15. {
  16. // 初始化 GoAhead Web 服务器
  17. if (websOpen(argc, argv) < 0) {
  18. fprintf(stderr, "Failed to initialize GoAhead Web Server\n");
  19. return -1;
  20. }
  21. // 定义自定义路由
  22. websUrlHandlerDefine("/myroute", NULL, WEBS_DEFAULT, myCustomHandler, 0);
  23. // 启动 Web 服务器
  24. websListen(NULL);
  25. // 清理资源
  26. websClose();
  27. return 0;
  28. }

分析固件启动的服务

位于liunx目录etc/init.d下为启动脚本,每次系统开始会执行(这也说明路由器的设置出厂模式 其实就是重启了设备而已)

本次固件分析的启动脚本如下

  1. #!/bin/sh
  2. ifconfig lo 127.0.0.1
  3. CINIT=1
  4. hostname rlx-linux
  5. mount -t proc proc /proc
  6. mount -t ramfs ramfs /var
  7. if [ -d "/hw_setting" ];then
  8. mount -t yaffs2 -o tags-ecc-off -o inband-tags /dev/mtdblock1 /hw_setting
  9. fi
  10. mkdir /var/tmp
  11. mkdir /var/web
  12. mkdir /var/log
  13. mkdir /var/run
  14. mkdir /var/lock
  15. mkdir /var/system
  16. mkdir /var/dnrd
  17. mkdir /var/avahi
  18. mkdir /var/dbus-1
  19. mkdir /var/run/dbus
  20. mkdir /var/lib
  21. mkdir /var/lib/misc
  22. mkdir /var/home
  23. mkdir /var/root
  24. mkdir /var/tmp/net
  25. ###for tr069
  26. mkdir /var/cwmp_default
  27. mkdir /var/cwmp_config
  28. if [ ! -f /var/cwmp_default/DefaultCwmpNotify.txt ]; then
  29. cp -p /etc/DefaultCwmpNotify.txt /var/cwmp_default/DefaultCwmpNotify.txt 2>/dev/null
  30. fi
  31. ##For miniigd
  32. mkdir /var/linuxigd
  33. cp /etc/tmp/pics* /var/linuxigd 2>/dev/null
  34. ##For pptp
  35. mkdir /var/ppp
  36. mkdir /var/ppp/peers
  37. #smbd
  38. mkdir /var/config
  39. mkdir /var/private
  40. mkdir /var/tmp/usb
  41. #snmpd
  42. mkdir /var/net-snmp
  43. cp /bin/pppoe.sh /var/ppp/true
  44. echo "#!/bin/sh" > /var/ppp/true
  45. #echo "PASS" >> /var/ppp/true
  46. #for console login
  47. cp /etc/shadow.sample /var/shadow
  48. #for weave
  49. cp /etc/avahi-daemon.conf /var/avahi
  50. #extact web pages
  51. cd /web
  52. #flash extr /web
  53. cd /
  54. mkdir -p /var/udhcpc
  55. mkdir -p /var/udhcpd
  56. cp /bin/init.sh /var/udhcpc/eth0.deconfig
  57. echo " " > /var/udhcpc/eth0.deconfig
  58. cp /bin/init.sh /var/udhcpc/eth1.deconfig
  59. echo " " > /var/udhcpc/eth1.deconfig
  60. cp /bin/init.sh /var/udhcpc/br0.deconfig
  61. echo " " > /var/udhcpc/br0.deconfig
  62. cp /bin/init.sh /var/udhcpc/wlan0.deconfig
  63. echo " " > /var/udhcpc/wlan0.deconfig
  64. if [ "$CINIT" = 1 ]; then
  65. startup.sh
  66. fi
  67. # for wapi certs related
  68. mkdir /var/myca
  69. # wapi cert(must done before init.sh)
  70. cp -rf /usr/local/ssl/* /var/myca/ 2>/dev/null
  71. # loadWapiFiles >/dev/null 2>&1
  72. # for wireless client mode 802.1x
  73. mkdir /var/1x
  74. cp -rf /usr/1x/* /var/1x/ 2>/dev/null
  75. mkdir /var/openvpn
  76. cp -rf /usr/share/openvpn/* /var/openvpn 2>/dev/null
  77. # Start system script
  78. init.sh gw all
  79. # modify dst-cache setting
  80. echo "24576" > /proc/sys/net/ipv4/route/max_size
  81. echo "180" > /proc/sys/net/ipv4/route/gc_thresh
  82. echo 20 > /proc/sys/net/ipv4/route/gc_elasticity
  83. # echo 35 > /proc/sys/net/ipv4/route/gc_interval
  84. # echo 60 > /proc/sys/net/ipv4/route/secret_interval
  85. # echo 10 > /proc/sys/net/ipv4/route/gc_timeout
  86. # echo "4096" > /proc/sys/net/nf_conntrack_max
  87. echo "12288" > /proc/sys/net/netfilter/nf_conntrack_max
  88. echo "600" > /proc/sys/net/ipv4/netfilter/ip_conntrack_tcp_timeout_established
  89. echo "20" > /proc/sys/net/ipv4/netfilter/ip_conntrack_tcp_timeout_time_wait
  90. echo "20" > /proc/sys/net/ipv4/netfilter/ip_conntrack_tcp_timeout_close
  91. echo "90" > /proc/sys/net/ipv4/netfilter/ip_conntrack_udp_timeout
  92. echo "120" > /proc/sys/net/ipv4/netfilter/ip_conntrack_udp_timeout_stream
  93. echo "90" > /proc/sys/net/ipv4/netfilter/ip_conntrack_generic_timeout
  94. # echo "1048576" > /proc/sys/net/ipv4/rt_cache_rebuild_count
  95. echo "32" > /proc/sys/net/netfilter/nf_conntrack_expect_max
  96. # modify IRQ Affinity setting
  97. echo "3" > /proc/irq/33/smp_affinity
  98. #echo 1 > /proc/sys/net/ipv4/ip_forward #don't enable ip_forward before set MASQUERADE
  99. #echo 2048 > /proc/sys/net/core/hot_list_length
  100. # start web server
  101. ls /bin/watchdog > /dev/null && watchdog 1000&
  102. #boa
  103. goahead &
  104. #Turn off the power led of orange
  105. echo "29" > /sys/class/gpio/export
  106. echo "out" > /sys/class/gpio/gpio29/direction
  107. echo "1" > /sys/class/gpio/gpio29/value
  108. #Turn on the power led of green
  109. echo "30" > /sys/class/gpio/export
  110. echo "out" > /sys/class/gpio/gpio30/direction
  111. echo "0" > /sys/class/gpio/gpio30/value
  112. cp /etc/passwd_orig /var/passwd
  113. cp /etc/group_orig /var/group
  114. MODE=`flash get HW_FACTORY_MODE`
  115. if [ "$MODE" = "HW_FACTORY_MODE=1" ];then
  116. telnetd&
  117. fi
  118. speedcheck&

除了一些基本的操作,如创建一些文件夹,写入一些配置项,配置下看门狗

还有重要的是服务器起了goahead服务

固件服务逆向分析

用IDA pro打开goahead服务。

目的—— 信息搜集 收集当前服务的有关接口,查看存在的接口的执行逻辑,是否可利用的参数可利用的方法调用、除此之外搜集接口信息还可以分析前端发出的包。

CTRL + E 选择主函数main进入, F5进入伪代码

if条件调用了很多函数,猜想这些函数是什么...... 。那一定有绑定服务的函数,建立socket客户端的函数,线程函数......如果这些代码执行错误那这个服务一定不可执行。之后while循环,这一定是阻塞等待客户端的连接,去处理用户的请求。

厂商既然用了goahead这个项目,就大概率配置了自己的接口,我们可以在while循环前,寻找相关信息

进入sub_423F90函数

 注意下面类似路径接口的函数

和示例中的 定义自定义路由多像啊! websUrlHandlerDefine("/myroute", NULL, WEBS_DEFAULT, myCustomHandler, 0);

根据原理第四个参数就是接口的处理函数,我们追进去sub_42383c

一眼望去 有一个很危险的行为 echo '%s' > 之后执行了system,首先这条语句在liunx一定是可以命令注入的,那么后面就是看参数a7是否可控了!

因为是伪代码,对比正向代码示例

// 自定义路由处理函数 static bool myCustomHandler(Webs *wp) {

a1 到 a7 一定是结构体webs的成员,那么a7就大概率是我们可控的参数。

不过执行system前,我们得先进入if条件语句中,判断for 与 if 的逻辑

循环遍历dword_58E084空间,每次循环将地址空间+8个字节,所指向的字符串与a1+1316的空间的字符串做对比,有则进入if执行代码

先看看dword_58E084空间有什么,+8就是一个字符串,+4就是一个函数(后面执行的函数也可判断出)(猜想 这函数一定是对应字符串的函数 的确是)  

那么a1+1316指向的空间是什么 ?

有些漏洞的发现无需逆向,凭经验与模糊测试就可以挖掘成功。

就像本次的a1+1316的空间 我们无需纠结那么多的细节,我们可以确定的是在路由器登录的时候一定执行了login方法, 那么a1+1316这个空间就一定符合程序预期的。我们前端抓包一探究竟。

登录页面

我们请求的url是POST /HNAP1 但最终处理的不一定不是HNAP1。header请求头中有SOAPAction 这个字段,网上收集资料学习下这种技术,最终明白了它强请求数据为什么是xml这种,为什么请求/HNAP 后端却是调用login函数。那么,a1+1316就大概率是SOAPAction 这个值了。  

a7也被传输了相关方法如login,我们就可以大胆的猜测 这个a7就是xml数据 是我们可控的。

此外我们还可以执行命令查看/var/hnaplog 到底被写入了什么作为日志信息,是请求的url还是请求的数据 是请求端的ip 还是请求的ugent

cat /var/hnaplog 将这条命令 在仿真的界面尝试执行(会有很多日志信息输出 手速快点 目前我没有找到一个干净的shell方法 如果有望告知)

 en.....的确是请求的post数据。

接下来我们就可以进行rce执行了 ,(实际测试本次固件无法发起连接请求,所以用写入文件的方法验证此漏洞)

抓包 输入我们的payload (web_mtn目录是web的根目录 在提取文件系统时可以大致判断出来)

`echo 123test > /web_mtn/1.txt` 

路由器固件RCE执行

  1. POST /HNAP1/ HTTP/1.1
  2. Host: 192.168.0.1
  3. Content-Length: 29
  4. Accept: */*
  5. X-Requested-With: XMLHttpRequest
  6. SOAPAction: "http://purenetworks.com/HNAP1/Login"
  7. User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36
  8. Content-Type: text/xml; charset=UTF-8
  9. Origin: http://192.168.0.1
  10. Referer: http://192.168.0.1/Login.html
  11. Accept-Encoding: gzip, deflate
  12. Accept-Language: en-US,en;q=0.9
  13. Connection: close
  14. '`echo 123 > /web_mtn/1.txt`'

之后访问路径 /1.txt 漏洞复现成功

总结

除此之外本次固件还有一系列的接口未授权,前端登录等同于虚设。除此之外貌似还有一些缓冲区溢出。 可以说是后端写的时非常随意了各种函数滥用,不考虑认证等问题。

其他说明 :本人纯小白,如有分析不对的地方或者有更好的分析方法 望大佬指出。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/507125
推荐阅读
相关标签
  

闽ICP备14008679号