D-Link router's ping function

D-Link routers have a basic ping function built in to them. Unlike their ASUS counterparts, which have ping, netstat, traceroute and nslookup builtin, D-Link routers have much more basic functionality. The ping function only displays success or failure and not the entire raw output of the command. Hence, on first look, it appears to be more secure.

The first step involves downloading the router firmware from D-Link's website and using binwalk to unpack the firmware. binwalk detected a squashfs file system, which is what we are looking for. sqaushfs is a read only file system, perfect for embedded devices since we do not store files on routers. After searching through the filesystem, I found the page responsible for the ping function located at /www/tools_vct.asp. The pertinent code in the file is as follows.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
function check_ip(){
if (get_by_id("ping_ipaddr").value == ""){
alert(tsc_pingt_msg2);
return false;
}else{
return true;

}
...
<form id="form5" name="form5" method="post" action="ping_response.cgi">
<input type="hidden" id="html_response_page" name="html_response_page" value="tools_vct.asp">
<input type="hidden" id="html_response_return_page" name="html_response_return_page" value="tools_vct.asp">
<tr>
<td>
<div align="right"><strong>
<script>show_words(tsc_pingt_h)</script>
 : </strong></div></td>
<td height="20" valign="top"> 
<input type="text" id="ping_ipaddr" name="ping_ipaddr" size=30 maxlength=63 value="<% CmoGetStatus("ping_ipaddr"); %>" >
<script>document.write('<input name="ping" id="ping" type="submit" value="'+_ping+'" onClick="return check_ip()">')</script></td>
</tr> </form>

Despite what the code suggests, I could not find ping_response.cgi. In fact, there were no CGI files found on anywhere on the file system. I began to suspect that D-Link designed their router firmware in a similar way as ASUS. A quick strings of the /sbin/httpd binary confirmed my suspicions, as a number of cgi filnames were found in the binary. The other function of interest is CmoGetStatus("ping_ipaddr"). I managed to find the corresponding function of the same name in the binary, it called the get_ping_app_stat function which performed the actual pinging.

image

This time, the actual command used is "ping -c 1 \"%s\" > /var/misc/ping_app.txt". It seems remarkably similar in design to the ASUS router. Both used system commands and piped the output to a file. For D-Link's case, since the output is not displayed, the best we can achieve is blind command execution. Unfortunately, the router does not support telnet/ssh and there was no wget/curl/nc binary present. Hence, one possible way I could think of to verify success of command execution is to issue the reboot command. I tried the following without any success.

  • 192.168.1.1#;/sbin/reboot
  • 192.168.1.1#";/sbin/reboot"
  • 192.168.1.1#\";/sbin/reboot\"