Having fun with unusual IPv4 formats

Did you know that “2130706433” is a valid IPv4 address, and pinging it from major OSes will yield a positive result? Let’s look into how it works.

Before we go any further, let’s try actually pinging it from my Linux laptop.

$ ping 2130706433
PING 2130706433 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.024 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.039 ms

Woah, it actually works. But why?

Let’s look into the man page for “inet_aton”, the standard library responsible for parsing human readable representations of IP addresses into binary:

a.b.c.d

Each of the four numeric parts specifies a byte of the address; the bytes are assigned in left-to-right order to produce the binary address.

a.b.c

Parts a and b specify the first two bytes of the binary address. Part c is interpreted as a 16-bit value that defines the rightmost two bytes of the binary address. This notation is suitable for specifying (outmoded) Class B network addresses.

a.b

Part a specifies the first byte of the binary address. Part b is interpreted as a 24-bit value that defines the rightmost three bytes of the binary address. This notation is suitable for specifying (outmoded) Class C network addresses.

a

The value a is interpreted as a 32-bit value that is stored directly into the binary address without any byte rearrangement.

In all of the above forms, components of the dotted address can be specified in decimal, octal (with a leading 0), or hexadecimal, with a leading 0X). Addresses in any of these forms are collectively termed IPV4 numbers-and-dots notation. The form that uses exactly four decimal numbers is referred to as IPv4 dotted-decimal notation (or sometimes: IPv4 dotted-quad notation).

In other words, there are several ways to represent IPv4 addresses, including using them in the decimal, octal and hexadecimal bases. Now, how can we leverage that to have fun?

Turns out it’s pretty easy. Let’s start by converting https://1.0.0.1, which is CloudFlare’s public DNS service into these fancy formats (your browser will automatically convert these links into the quad-octet dotted decimal format).

  • https://1.1
    This one is pretty straightforward. Since the middle 2 octets are zeroes, we can just omit them.
  • https://0x1.0x1
    Same as the previous example, but the octets are converted to their hexadecimal forms.
  • https://01.0x1
    The bases can be combined across octets.
  • https://0x1000001
    The whole IP address can be represented as a single number, without the dotted separators.
  • https://0100000001
    Same as the previous example, only in the octal base.
  • https://16777217
    The previous example can be also represented in base 10.

Let’s do the same for a more complex address, like 192.168.0.1:

  • 192.168.1
  • 192.0xa80001
  • 192.11010049
  • 0300.11010049
  • 0300.0xa80001
  • 0xc0.11010049

Many other combinations can be created.

Why should I care?

You might ask, what’s the purpose of writing addresses like this? Well for starters, it is important to take these forms of addresses into account while designing secure (and security) systems.

Imagine if you have a spam filtering system which looks for IP addresses in emails. Generally, you would look for a pattern like [0-255].[0-255].[0-255].[0-255]. That sort of pattern would not match any of the aforementioned example combinations. Malicious actors would be easily able to circumvent this kind of filtering by using an address like “0300.0xa80001”.

Most importantly though, telling your networking minded friends that “IPv4+” is a real protocol and that it’s currently being deployed, while telling them to visit https://16777217 is a fun exercise.

Does this work on IPv6?

I was obviously curious if something like this is possible with IPv6 addresses as well.

Turns out that’s (un)fortunately not the case. The only sort of interesting addressing is possible using the IPv4-mapped IPv6 format:

$ ping 2001:4860:4860::0.0.136.136
PING 2001:4860:4860::0.0.136.136(2001:4860:4860::8888) 56 data bytes
64 bytes from 2001:4860:4860::8888: icmp_seq=1 ttl=57 time=8.44 ms

 

2 Comments

Add yours

  1. great article. I noticed the following typo in its current version:

    There is a link with text https://01.0×1 (notice the multiplication character); the multiplication character is incorrect. it should be https://01.0×1 (x-as-in-xavier character). This typo only exists in the link text; the actual href attribute is correct.

Leave a Reply...