1、概述
最近关注了Cisco的一个命令注入漏洞CVE-2021-1414,命令注入之后可导致远程代码执行:
漏洞存在于固件版本低于V1.0.03.21的RV340系列路由器中,当前最新版本V1.0.03.21已修复了此漏洞。RV340系列路由器可为小型企业提供防火墙和高速上网服务。刚好手头有一个RV340路由器,固件版本为V1.0.03.18,为存在漏洞版本,故实地分析测试了一下。
2、漏洞分析
从官网分别下载了V1.0.03.18固件:https://software.cisco.com/download/home/286287791/type/282465789/release/1.0.03.18
固件为.img格式,与常见的.bin文件貌似有一些些区别?直接使用7z一路解压,当得到fw.gz时继续解压,最终结果如下:
可得到一个较大的openwrt-comcerto2000-hgw-rootfs-ubi_nand.img文件,由此可知此型号的路由器固件是基于openwrt开发而来?OpenWRT是一个高度模块化、高度自动化的嵌入式Linux系统,拥有强大的网络组件和扩展性,多被用于工控设备、电话、小型机器人、智能家居、路由器以及VOIP设备中。文件系统为ubi,与常见bin格式的Squashfs文件系统相比,Squashfs有更好的压缩性。
使用binwalk对文件openwrt-comcerto2000-hgw-rootfs-ubi_nand.img文件进行分析,最终可得到文件系统中的全部内容:
可知目标平台为:ARM 32位小端。
搜索更多关于CVE-2021-1414信息,发现ZDI对漏洞给出了更多信息:
根据漏洞描述可知:由于JSON-RPC处理set_snmp请求中的USMUserPrivKey字段时存在命令注入,于是在解压的固件文件中寻找与RPC处理相关的文件,定位到rootfs/www/cgi-bin/jsonrpc.cgi文件,使用IDA打开jsonrpc.cgi,定位到处理RPC请求的函数:sub_149FC,函数sub_149FC根据不同的RPC指令进入对应的分支流程:
关键点位于else if ( !strncmp(method, “set_”, 4u),这里刚好与set_snmp指令的前4个字节匹配:
该分支首先调用sub_12DB4校验请求中的“sessionid”是否合法,如果合法则进入sub_13E2C函数,继续跟进这个函数:
可知此处调用了导出函数jsonrpc_set_config处理set_snmp请求,于是在rootfs根目录使用grep -r “jsonrpc_set_config” ./ 来定位导出此函数的so文件:
与jsonrpc.cgi依赖的库文件比较确定 jsonrpc_set_config函数是由libjsess.so文件导出的:
使用IDA打开libjsess.so定位到导出函数jsonrpc_set_config,发现函数被动态调用,而我们又无法动态调试此文件,因此无法获取到函数的真实地址。
由于已知问题出在 “USMUserPrivKey”字段,通过搜索字符串最终定位到漏洞函数 setpre_snmp,函数定义与上图中的动态声明相符,同时与漏洞描述的set_snmp也相符。
分析显示:程序最终会调用popen执行被sprintf格式化后的v60字符串,v60的最后一段子字符串来自变量v19,v19来自v44,v44来自json_object_get_string中的参数v52,v52正是usmUserPrivKey字段中的值。此函数在调用popen执行命令前未对usmUserPrivKey中的值进行过滤导致了命令注入。
3、漏洞复现
Web登录路由器,进入到SNMP设置界面,并全过程Burp抓包:
开启nc监听:
Brup重放上一步中抓取到的数据包,在usmUserPrivKey字段注入待执行的命令:
执行后,nc成功反弹shell:
4、补丁对比
下载修复漏洞之后的固件版本,将存在漏洞的文件和修复漏洞的文件进行对比分析,结果如下:
补丁之前的代码,未校验参数,直接调用popen执行命令:
补丁后的代码,调用popen前使用match_regex正则表达式过滤特殊字符,命令注入漏洞被修复:
参考资料:
[1] https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-sb-rv34x-rce-8bfG2h6b
[2] https://www.zerodayinitiative.com/advisories/ZDI-21-559/
发表评论
您还未登录,请先登录。
登录