固件CGI分析手法(一)

安全入门
2022-08-05 19:04
70315

还是前两天买的那款TOTOLINK 720R,从官网上下到了固件,本篇文章将以这款路由器的固件为例,详细讲解如何一步步的分析cgi文件

首先下载固件:https://www.totolink.cn/data/upload/20210728/1a9db40978a2a86472b9e0bd7128da1d.zip

然后直接

binwalk -Me xxx.web

解出文件系统

接下来到web_cste目录下寻找主要的cgi程序

将其拖进IDA中逆向分析一下:

可以看到main函数长这样,首先看到的逻辑是通过getenv函数获取了一些环境变量的值,getenv函数我们无法在当前程序中找到具体实现,可以通过grep -r getenv,在固件中搜索一下在哪里出现过:

可以看到这个getenv应该是uclibc中实现的一个获取类似环境变量的东西的函数,而各类参数的含义这里给出一个CGI环境变量参数表

  • CGI环境变量列表
    SERVER-NAME:运行CGI序为机器名或IP地址。
    SEUVER-INTERFACE:WWW服务器的类型,如:CERN型或NCSA型。
    SERVER-PROTOCOL:通信协议,应当是HTTP/1.0。
    SERVER-PORT:TCP端口,一般说来web端口是80。
    HTTP-ACCEPT:HTTP定义的浏览器能够接受的数据类型。
    HTTP-REFERER: 发送表单的文件URL。(并非所有的浏览器都传送这一变量)
    HTTP-USER-AGENT:发送表单的浏览器的有关信息。
    GETWAY-INTERFACE:CGI程序的版本,在UNIX下为 CGI/1.1。
    PATH-TRANSLATED: PATH-INFO中包含的实际路径名。
    PATH-INFO:浏览器用GET方式发送数据时的附加路径。
    SCRIPT-NAME: CGI程序的路径名。
    QUERY-STRING:表单输入的数据,URL中间号后的内容。
    REMOTE-NOST:发送程序的主机名,不能确定该值。
    REMOTE-ADDR:发送程序的机器的IP地址。
    REMOTE-USBR:发送程序的人名。
    CONTENT-TYPE:POST发送,一般为applioation/xwww-form-urlencoded。
    CONTENT-LENGTH:POST方法输入的数据的字节数

对照上述列表即可大致理解getenv获取到的值都对应着什么含义,我们在分析的时候大部分时间还是把目光投向QUERY-STRING,因为大部分情况下是由这个参数来决定后续要执行什么函数,完成什么功能。

我们跟随QUERY_STRING继续分析

首先判断了QUERY_STRING是否为空,不为空则去判断是否存在action=login的字样,或者是否有atciton=upload的字样或者是否有exportOvpn的字样

如果三个都没有则goto label 47

如果有action=login或者有action=upload,则获取并设置一些参数,然后goto label 47

如果有action=exportOvpn字样,则会在执行一些命令之后直接给出返回包内容

所以可以看出来,对于大部分情况来说,label 47 是进一步处理分发函数的地方,我们继续跟进看看

分析到这里又要面临一个问题,cJSON_Parse和websGetVar又是干嘛的

我们随便找个功能,bp抓个包看看

可以看到,这里又一串明显是json格式的数据

我们可以大致做一个判断,路由器管理界面很多功能所发送的请求都是
POST /cgi-bin/cstecgi.cgi
那么如何分发不同按钮所需的不同功能函数呢,靠的就是后面这一串json格式的数据,其中起主要作用的是topicurl,这个key对应的value是所需功能函数的函数名,比如上图中的setSmartQosCfg,然后其他的参数则大部分是在这个分发到的功能函数中使用。

现在回过头来继续分析cJSON_Parse和websGetVar

当action=login或者upload的时候:

程序通过sprintf将一个json格式的数据填上一些指定的值然后放进v45,而后又放进v13中,当不满足两个action的时候:

是将v10给到v13,然后执行cJSON_Parse(v13)
向上跟踪v10:

发现v10其实就是读入的原始数据,即上面bp包里红框里的内容,所以无论怎么样,v13最后都会指向一个json格式的字符串,根据名字也能够大致猜测出来,cJSON_Parse其实就是将一个json格式的字符串解析成一个特殊的结构体,而websGetVar应该就是从这个结构体中取出指定key对应的value

如果读者感兴趣的话可以通过分析源码的方式验证一下我们的分析结果,通过命令

grep -r xxx

可以在文件系统中寻找指定函数出现的位置,一般在so文件中会有其具体实现

可以看到,cJSON_Parse函数应该就是在libcjson.so具体实现的,其他函数同理

今天这篇文章暂时就到这里,暂时打算第二篇文章进一步对cgi中出现的一些函数功能以及分发函数的原理进行分析,第三篇则结合我自己的一些漏洞挖掘经历来说说cgi中一些脆弱的地方,我们下期见~

分享到

参与评论

0 / 200

全部评论 3

zebra的头像
学习大佬思路
2023-03-19 12:14
Hacking_Hui的头像
学习了
2023-02-01 14:20
iotstudy的头像
内容棒棒的,期待三连。
2022-08-12 11:57
投稿
签到
联系我们
关于我们