Browser Arcana: IP Literals in URLs

While virtually all web traffic flows over connections based on the Internet Protocol, most of the time your browser first uses DNS to look up the target hostname’s IP address. However, sometimes URLs directly specify an IP address, skipping DNS altogether. When an IP appears directly within such an URL, it is said to have an IP-Literal Hostname. In general, using IP-Literal hostnames is a bad idea (as they don’t support DNS Failover and other useful features) but in rare cases their use may be reasonable-- e.g. when communicating directly with network devices like switches and routers.

The most common IP-Literal URLs use the dotted-quad notation for an IP v4 address; for instance, https://127.0.0.1/mypage. The introduction of IPv6 complicated matters a bit, since IPv6 literals must be placed within square-brackets in the URL, like so: https://[::1]/mypage. Many users are surprised, however, to learn that IPv4 literals can be expressed using other notations.

For instance, any internal “0“ components of a dotted quad may be omitted, and thus https://127.0.1 and https://127.1 are both equivalent to https://127.0.0.1.

The more interesting of the notations are the raw integer forms—remember, an IPv4 address is simply a 32bit integer. As such, you can represent 127.0.0.1 in its decimal form as https://2130706433/ or even in octal form as https://017700000001/. The reason that these variants are interesting is that they don’t contain any dots, and various software components may treat hostnames without dots as special1. In 2001, for instance, incorrect mapping of all dotless hostnames to the (privileged) Intranet security zone resulted in a serious security vulnerability which was patched by introducing special detection for IP address literals.

In Internet Explorer 7, the CURI object was introduced to standardize handling of URLs throughout the browser and OS; one of the first steps that class undertakes when constructing a URL object from a string is to convert any IP literal hostname into its canonical dotted-quad form. Chrome and Opera appear to match Internet Explorer’s behavior here, while Firefox 27 leaves the undotted decimal in the address bar and in the request sent to the network2:

IE, Chrome, Opera

GET / HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 6.3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.45 Safari/537.36

Firefox

GET / HTTP/1.1
Host: 2130706433
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0

If your code makes any sort of security decision based on the absence of dots within a hostname, be sure that you aren’t fooled by undotted IP literals!

-Eric

1 For instance, the isPlainHostName function in PAC scripts, or the network.automatic-ntlm-auth.allow-non-fqdn preference in Firefox.

2 Mozilla has an issue filed to remove support for undotted IP literals entirely, and while it’s tagged as “New,” it is today just over 13 years old.