Correctly Validating IP Addresses: Why encoding matters for input validation.
Recently, a number of libraries suffered from a very similar security flaw: IP addresses expressed in octal were not correctly interpreted. The result was that an attacker was able to bypass input validation rules that restricted IP addresses to specific subnets.
The vulnerability was documented in (this list is unlikely to be complete):
- Node.js netmask package [1]
- Perl (various packages) [2]
- Python stdlib ipaddress module [3]
All of these vulnerabilities were caused by a similar problem: These libraries attempted to parse IP addresses as a string. Later, standard-based "socket" libraries were used to establish the actual connection. The socket libraries have their own "inet_aton" function to convert an IP address string to a long unsigned integer.
It isn't an accident that security researchers started to look at these libraries right now. More and more of our applications have surrendered data to cloud services and implement APIs to access the data. Server-Side Request Forgery (SSRF) is becoming more of an issue as a result. And to restrict which IP address a particular application may connect to, we often use the libraries above.
As a simple test string, use "010.010.010.010". The leading "0" indicates that the address is octal. In "dotted decimal," the address translates to Google's name server 8.8.8.8.
So if you have to validate an IP address: How to do it? First of all: Try to stick to one of the (hopefully now fixed) standard libraries. But in general, it can be helpful to stick to the same library for input validation and to establish the connection. This way, the IP address is not interpreted differently. There is also an argument to be made to just not allow octal. I leave that decision up to you. Standards do allow that notation.
For example, most languages under the hood rely on the C "Sockets" library to establish connections [4]. This library also includes functions to convert IP addresses expressed as a string into an unsigned 32-bit integer (inet_aton) and back (inet_ntoa) [5]. Take a look if your language is implementing these functions. Part of the problem of the node.js vulnerability was that node.js implemented its own "ip2long" function.
So how do you verify if an IP address is inside a subnet? Well, there is a reason netmasks are called netmasks: They are bitmasks. Bitmasking is a very efficient and simple way to verify IP addresses.
First of all: Is this IP address a valid IPv4 address?
My favorite "trick" is to convert the address to an integer with inet_aton. Next, convert it back to a string with inet_ntoa. If the string didn't change: You got a valid address. This will work nicely if you only allow dotted decimal notation. If not: just convert the string with inet_aton and keep it an integer. Not all languages may use the Sockets library for "inet_aton." Some may use their own (buggy?) implementation. So best to check quickly:
010.010.010.010 = 8.8.8.8 = 134744072 .
If you get 168430090, then you got it wrong (that would be 10.10.10.10). MySQL/MariaDB, for example, will get you the wrong answer:
MariaDB [(none)]> select inet_aton('10.10.10.10')-inet_aton('010.010.010.010'); +-------------------------------------------------------+ | inet_aton('10.10.10.10')-inet_aton('010.010.010.010') | +-------------------------------------------------------+ | 0 | +-------------------------------------------------------+
Output encoding matters for proper input validation!
So now, how do we verify if IP address "A" is in subnet B/Z ?
"z" is the number of bits that need to be the same. So let's create a mask:
mask = 2^32-2^(32-Z)
next, let's do a bitwise "AND" before comparing the result:
If ( A & mask == B & mask ) { IP Address A is in B/Z }
So in short:
- Try to use the same library to validate the IP address and to establish connections. That is probably the easiest way to avoid issues. Sadly, modern languages add additional layers, and it isn't always clear what happens in the background.
- Test! inet_aton('010.010.010.010') != inet_aton('10.10.10.10').
- IPs are long integers, not strings.
So why do I sometimes see IP addresses like "010.123.123.123" on isc.sans.edu?
Remember, we started collecting data 20 years ago. I have learned since :) But some of my early sins still haunt me. Over the last few years, we moved to store the IP addresses as 32-bit unsigned integers, but "back in the day," we used 15 digit strings and zero-padded them for easy sorting... sorry. should be mostly gone by now and if you find a case where this is still happening, let me know.
What about IPv6?
That will be a different diary :)
What about hex notation?
There are a number of additional formats that can be used for IP addresses. For a complete collection of different representations of IP addresses [6]. Test them. Let me know what you find :) .
[1] https://nvd.nist.gov/vuln/detail/CVE-2021-29418
[2] https://blog.urth.org/2021/03/29/security-issues-in-perl-ip-address-distros/
[3] https://nvd.nist.gov/vuln/detail/CVE-2021-29921
[4] https://www.gnu.org/software/libc/manual/html_node/Sockets.html
[5] https://www.gnu.org/software/libc/manual/html_node/Host-Address-Functions.html
[6] https://www.hacksparrow.com/networking/many-faces-of-ip-address.html
---
Johannes B. Ullrich, Ph.D. , Dean of Research, SANS.edu
Twitter|
Comments
www
Nov 17th 2022
6 months ago
EEW
Nov 17th 2022
6 months ago
qwq
Nov 17th 2022
6 months ago
mashood
Nov 17th 2022
6 months ago
isc.sans.edu
Nov 23rd 2022
6 months ago
isc.sans.edu
Nov 23rd 2022
6 months ago
isc.sans.edu
Dec 3rd 2022
6 months ago
isc.sans.edu
Dec 3rd 2022
6 months ago
<a hreaf="https://technolytical.com/">the social network</a> is described as follows because they respect your privacy and keep your data secure. The social networks are not interested in collecting data about you. They don't care about what you're doing, or what you like. They don't want to know who you talk to, or where you go.
<a hreaf="https://technolytical.com/">the social network</a> is not interested in collecting data about you. They don't care about what you're doing, or what you like. They don't want to know who you talk to, or where you go. The social networks only collect the minimum amount of information required for the service that they provide. Your personal information is kept private, and is never shared with other companies without your permission
isc.sans.edu
Dec 26th 2022
5 months ago
isc.sans.edu
Dec 26th 2022
5 months ago