关于路由器的CGI漏洞分析及挖掘
本文主要记述了CGI的含义,以及常见网络设备中使用的CGI框架与流程,最后通过DLINK和Netgear两款路由器的CGI漏洞介绍当前常见的CGI漏洞挖掘和分析流程。
CGI是什么
到目前为止,实现动态Web页面有4种技术可供选择:CGI,ASP,PHP和JSP。本节记述关于路由器CGI相关知识。
早期的Web服务器,只能响应浏览器发来的HTTP静态资源的请求,并将存储在服务器中的静态资源返回给浏览器。随着Web技术的发展,逐渐出现了动态技术,但是Web服务器并不能够直接运行动态脚本,为了解决Web服务器与外部应用程序(CGI程序)之间数据互通,于是出现了CGI(Common Gateway Interface)通用网关接口。简单理解,可以认为CGI是Web服务器和运行其上的应用程序进行“交流”的一种约定。
CGI不是一门编程语言。它是网页的表单和你写的程序之间通信的一种协议。可以用任何语言写一个CGI脚本,这些语言只要能接收输入输出信息,读取环境变量。所以,几乎所有的编程语言都能写一个CGI脚本,例如:python ,C,甚至是shell脚本。
典型的CGI脚本做了如下的事情:
读取用户提交表单的信息
处理这些信息
输出,返回html响应
设备CGI分析
目前IOT设备主要有三个WebServer:httpd,thttpd和Boa。httpd是最简单的一个Web Server,它的功能最弱,不支持认证,不支持CGI。Thttpd和Boa都支持认证、CGI等,功能都比较全。
Boa
Boa 是一个单任务的http服务器,源代码开放、性能高。Boa 是一个单任务 HTTP 服务器。这意味着与传统的 Web 服务器不同,它不会为每个传入的连接 fork,也不会 fork自身的许多副本来处理多个连接。它在内部多路复用所有正在进行的 HTTP 连接,并且只为 CGI 程序(必须是单独的进程)、自动目录生成和自动文件压缩进行 fork。
源码分析
在Boa官网下载源码。
Boa首先会调用 process_option_Iine()将一些头部信息填写到request结构中完成这些环境变量的设置,随后 process_header_end()会对用户进行验证。如果验证通过则判断request结构中的is_cgi,非0则是CGI程序,调用 init_cgi()函数进行处理,为0则是静态页面,调用init_get()函数进行处理。
init_cgi
boa程序在解析请求头的收尾函数process_header_end中,translate_uri函数会解析请求的虚拟路径.
?*?Name:?init_cgi
?*
?*?Description:?Called?for?GET/POST?requests?that?refer?to?ScriptAlias
?*?directories?or?application/x-httpd-cgi?files.??Ties?stdout?to?socket,
?*?stdin?to?data?if?POST,?and?execs?CGI.
?*?stderr?remains?tied?to?our?log?file;?is?this?good?
?*
?*?Returns:
?*?0?-?error?or?NPH,?either?way?the?socket?is?closed
?*?1?-?success
init_cgi首先通过调用 create_common_env(),complete_env()完成对CGI环境变量的设置

translate_uri函数中的init_script_alias函数,负责解析ScriptAlias请求,设置请求cgi类型,查看文件是否存在以及具有相关权限。
然后CGI会execve执行相应的程序。
if?(req->cgi_type)?{
????????????char?*aargv[CGI_ARGC_MAX?+?1];
????????????create_argv(req,?aargv);
????????????execve(req->pathname,?aargv,?req->cgi_env);
????????}?else?{
????????????if?(req->pathname[strlen(req->pathname)?-?1]?==?'/')
????????????????execl(dirmaker,?dirmaker,?req->pathname,?req->request_uri,
??????????????????????(void?*)?NULL);
固件分析
这里分析vivetok摄像头固件,该摄像头的web是基于Boa进行二次开发的。
uhttpd
uHTTPd作为OpenWrt中默认的HTTP服务器,主要是用来配合LuCI Web接口方便OpenWrt设备的管理,luci就是一个网页界面,包含openwrt配置页面。以cgi的方式被web服务器调用并渲染页面,语言采用lua,支持CGI、Lua和UBUS完成对请求的处理。在IoT设备上使用OpenWrt比较常见的情况是,结合uhttpd使用LuCI框架编写lua处理脚本。
源码分析
下载?uhttpd源代码
首先在uh_handle_request中解析接收到的请求头
void?uh_handle_request(struct?client?*cl)
{
????struct?http_request?*req?=?&cl->request;
????struct?dispatch_handler?*d;
????char?*url?=?blobmsg_data(blob_data(cl->hdr.head));
????char?*error_handler,?*escaped_url;
????blob_buf_init(&cl->hdr_response,?0);
????url?=?uh_handle_alias(url);
????uh_handler_run(cl,?&url,?false);
????if?(!url)
????????return;
????req->redirect_status?=?200;
????d?=?dispatch_find(url,?NULL);
????if?(d)
????????return?uh_invoke_handler(cl,?d,?url,?NULL);
????if?(__handle_file_request(cl,?url))
????????return;
????if?(uh_handler_run(cl,?&url,?true))?{
????????if?(!url)
????????????return;
????????uh_handler_run(cl,?&url,?false);
????????if?(__handle_file_request(cl,?url))
????????????return;
????}
????req->redirect_status?=?404;
????if?(conf.error_handler)?{
????????error_handler?=?alloca(strlen(conf.error_handler)?+?1);
????????strcpy(error_handler,?conf.error_handler);
????????if?(__handle_file_request(cl,?error_handler))
????????????return;
????}
????escaped_url?=?uh_htmlescape(url);
????uh_client_error(cl,?404,?"Not?Found",?"The?requested?URL?%s?was?not?found?on?this?server.",
????????????????????escaped_url???escaped_url?:?"");
????if?(escaped_url)
????????free(escaped_url);
}
使用dispatch_find函数根据请求的url找到合适的dispatch_handler,cgi_prefix在/etc/config/uhttpd配置文件中的默认值为/cgi-bin,并且程序在main函数中默认添加了cgi_dispatch,当请求的url通过check_cgi_path函数校验,则会调用cgi_handle_request函数回调cgi_main函数execl执行对应的CGI程序
static?void?cgi_handle_request(struct?client?*cl,?char?*url,?struct?path_info?*pi)
{
????unsigned?int?mode?=?S_IFREG?|?S_IXOTH;
????char?*escaped_url;
????if?(!pi->ip?&&?!((pi->stat.st_mode?&?mode)?==?mode))?{
????????escaped_url?=?uh_htmlescape(url);
????????uh_client_error(cl,?403,?"Forbidden",
????????????????"You?don't?have?permission?to?access?%s?on?this?server.",
????????????????escaped_url???escaped_url?:?"the?url");
????????if?(escaped_url)
????????????free(escaped_url);
????????return;
????}
????if?(!uh_create_process(cl,?pi,?url,?cgi_main))?{
????????uh_client_error(cl,?500,?"Internal?Server?Error",
????????????????"Failed?to?create?CGI?process:?%s",?strerror(errno));
????????return;
????}
????return;
}
struct?dispatch_handler?cgi_dispatch?=?{
????.script?=?true,
????.check_path?=?check_cgi_path,
????.handle_request?=?cgi_handle_request,
};
执行CGI程序:
static?void?cgi_main(struct?client?*cl,?struct?path_info?*pi,?char?*url)
{
????const?struct?interpreter?*ip?=?pi->ip;
????struct?env_var?*var;
????clearenv();
????setenv("PATH",?conf.cgi_path,?1);
????for?(var?=?uh_get_process_vars(cl,?pi);?var->name;?var++)?{
????????if?(!var->value)
????????????continue;
????????setenv(var->name,?var->value,?1);
????}
????if?(!chdir(pi->root))?{
????????if?(ip)
????????????execl(ip->path,?ip->path,?pi->phys,?NULL);
????????else
????????????execl(pi->phys,?pi->phys,?NULL);
????}
????printf("Status:?500?Internal?Server?Error\r\n\r\n"
???????????"Unable?to?launch?the?requested?CGI?program:\n"
???????????"??%s:?%s\n",?ip???ip->path?:?pi->phys,?strerror(errno));
}
CGI漏洞
D-LINK SERVICE.CGI远程命令执行漏洞
2018年1月17日,CNVD公开了D-LinkDIR 615/645/815 service.cgi远程命令执行漏洞(CNVD-2018-01084)。
D-Link DIR 615/645/815路由器1.03及之前的固件版本存在远程命令执行漏洞。该漏洞是由于service.cgi中拼接了HTTP POST请求中的数据,造成后台命令拼接,导致可执行任意命令。
下载固件
先解压,再使用binwalk分析固件
$?unzip?DIR-645_FIRMWARE_1.03.ZIP??
Archive:??DIR-645_FIRMWARE_1.03.ZIP
??inflating:?dir645_FW_103.bin???????
$?binwalk?-Me?dir645_FW_103.bin?
Scan?Time:?????2021-08-12?23:03:41
MD5?Checksum:??12a10a6a2fe96e0b7a50c2babd714e3d
Signatures:????410
DECIMAL???????HEXADECIMAL?????DESCRIPTION
--------------------------------------------------------------------------------
0?????????????0x0?????????????DLOB?firmware?header,?boot?partition:?"dev=/dev/mtdblock/2"
112???????????0x70????????????LZMA?compressed?data,?properties:?0x5D,?dictionary?size:?33554432?bytes,?uncompressed?size:?4237576?bytes
1441904???????0x160070????????PackImg?section?delimiter?tag,?little?endian?size:?3169792?bytes;?big?endian?size:?6172672?bytes
1441936???????0x160090????????Squashfs?filesystem,?little?endian,?version?4.0,?compression:lzma,?size:?6170670?bytes,?2216?inodes,?blocksize:?262144?bytes,?created:?2012-10-09?10:24:09
Scan?Time:?????2021-08-12?23:03:43
MD5?Checksum:??0eab4114d12c97a4a1ff29d0d307d6da
Signatures:????410
DECIMAL???????HEXADECIMAL?????DESCRIPTION
--------------------------------------------------------------------------------
1571792???????0x17FBD0????????MySQL?ISAM?index?file?Version?8
1621686???????0x18BEB6????????PGP?RSA?encrypted?session?key?-?keyid:?801000?4C?RSA?Encrypt-Only?1024b
3149062???????0x300D06????????PGP?RSA?encrypted?session?key?-?keyid:?801000?3A?RSA?Encrypt-Only?1024b
3149250???????0x300DC2????????PGP?RSA?encrypted?session?key?-?keyid:?801000?3A?RSA?Encrypt-Only?1024b
3338272???????0x32F020????????Linux?kernel?version?2.6.33
3398624???????0x33DBE0????????CRC32?polynomial?table,?little?endian
3803284???????0x3A0894????????Neighborly?text,?"NeighborSolicitstunnel6?init():?can't?add?protocol"
3803304???????0x3A08A8????????Neighborly?text,?"NeighborAdvertisementst?add?protocol"
3808047???????0x3A1B2F????????Neighborly?text,?"neighbor?%.2x%.2x.%.2x:%.2x:%.2x:%.2x:%.2x:%.2x?lost?on?port?%d(%s)(%s)"
逆向cgibin
使用IDA逆向cgibin文件
$?file?cgibin???????????????????????????????
cgibin:?ELF?32-bit?LSB?executable,?MIPS,?MIPS32?version?1?(SYSV),?dynamically?linked,?interpreter?/lib/ld-uClibc.so.0,?stripped
查看servicecgi_main函数,我们可以看到servicecgi_main调用了lxmldbc_system函数,

此函数调用了system函数。

接下来该漏洞的成因。
在servicecgi_main中先判断请求的方法,只处理get和post

在servicecgi_main中可以处理EVENT,SERVICE,ACTION三个类型的form表单参数域。servicecgi_main会把这三个表单域参数存储在特定区域,然后进行event,service,action的处理。
在处理event请求时没有对EVENT值做必要的处理,然后进入loc_40D038模块,在模块中调用了lxmldbc_system函数,进而调用了system函数。

而lxmldbc_system会调用system执行command,而且是没有任何过滤的,那就存在命令注入的风险了。
Netgear CVE-2016-6277
NETGEAR R6250在1.0.4.6.Beta之前,R6400在1.0.1.18.Beta之前,R6700在1.0.1.14.Beta,R6900,R7000在1.0.7.6.Beta之前,R7100LG在1.0.0.28.Beta之前,R7300DST在1.0.0.46.Beta之前,1.0.1.8.Beta之前的R7900、1.0.3.26.Beta,D6220,D6400,D7000之前的R8000,以及可能的其他路由器,允许远程攻击者通过shell在 cgi-bin/ 的路径中执行任意命令。
下载Netgear R7000固件
使用binwalk解析固件,使用IDA分析httpd文件
通过漏洞提示信息在IDA中查找到对应字符串


查看v51的来源

可以看到v51是v19拷贝来的

接着溯源可以看到v19来自v12,v12来自v6,v6是一个URL,这也就和上文对应了起来

所以这里是一个因为对命令没有过滤的命令注入漏洞。
参考链接:
常见嵌入式Web服务器CGI处理功能简要分析:https://larry.ngrep.me/2020/02/03/iot-web-server-cgi-handler-analysis/
D-LINK SERVICE.CGI远程命令执行漏洞:
https://www.freebuf.com/articles/terminal/164680.html
end
招新小广告
ChaMd5?Venom?招收大佬入圈
新成立组IOT+工控+样本分析?长期招新
欢迎联系admin@chamd5.org

关注公众号:拾黑(shiheibook)了解更多
[广告]赞助链接:
四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/
关注网络尖刀微信公众号随时掌握互联网精彩
- 1 习近平将发表二〇二六年新年贺词 7904141
- 2 2026年国补政策来了 7808738
- 3 东部战区:开火!开火!全部命中! 7712893
- 4 2026年这些民生政策将惠及百姓 7616985
- 5 小学食堂米线过期2.5小时被罚5万 7519709
- 6 解放军喊话驱离台军 原声曝光 7428214
- 7 为博流量直播踩烈士陵墓?绝不姑息 7327605
- 8 每月最高800元!多地发放养老消费券 7238391
- 9 数字人民币升级 1月1日起将计付利息 7141831
- 10 2026年1月1日起 一批新规将施行 7040675








Chamd5安全团队
