From The Hacker News
Surprised this isn’t a better known / prevented vector. I remember experimenting with variant IPs like this in IE6 over 20 years ago.
Checking now with Firefox and it auto-translates on the line below as I type one in. (Tried both 0x7f000001 and 2130706433 because they’re both variants of 127.0.0.1, and if there’s something bad running on that address you have other problems.)
Irrelevant nerd fact: 2130706433 is a prime number.
So is 127
Interesting, I didn’t know IPv4 addresses converted to hex could be used for anything.
It’s all 1s and 0s at the end of the day
Dotted Decimal is just a human convention. IPs are just 32 bit numbers meaning binary digit, and octal, dotted decimal and Hex are all valid representations of that same number. Subnet masks work via binary math.
Almost every single thing you would use an IP address for, you can substitute dotted decimal for octal or hex representations.
You can use a decimal number as well. It’s rare to see that form of URL though.
We have PABXes that use VxWorks and it uses hex IPs to identify each ethernet port
Might be easier to use with lower-level stuff like pure C?
Nah, it’s easier in pretty much every language. It’s just a 32 bit number that can be compared with a standard “<=” or “=” comparison operator in pretty much every language out there and a single ASM instruction. Writing it as four smaller numbers joined with dots is just how it’s easy to display for humans.
Many make the mistake of thinking that IPv4 addressess are always encoded like that. The address “127.0.0.1” is just 2130706433 in decimal. Some tools even accept misformed addresses like “0.0.0.2130706433”. Security concerns come in to play when a program checks for local addresses by comparing the individual “127”, “0”, “0”, “1” parts (or eg. “192”, “168”, ““, ,””) and allow or deny access based on that for example. Another part of the software will likely just accept a misformed address and a malicious actor can circumvent the filtering from earlier.
Some tools even accept misformed addresses like “0.0.0.2130706433”
Is that because it’s just three octets of zero bits? What tools do this?
A naive implementation of a conversion from displayable IPv4 to 32bit integer IPv4 might look like this:
You have taken the four integer numbers of the IPv4 address from the text input, converted them to an integer and for simplicity sake we will say that they were put into variables a, b, c and d. It is common to just use ‘int’ for numbers and not choose something more fitting like ‘uint8’, so in our case the variables will look like this after assignment:
a: 0 b:0 c:0 d:2130706433
Now let’s declare a 32 bit variable R for our result and initialize it with 0 (or with d to skip a step, but optimization is not the point here).
Let’s work from left to right along the original representation. That means we’ll start with variable a. In an ideal case, only the rightmost 8 bits are set (0-255 decimal). Many will just make that (naive) assumption. We shift it to the left, so that the 8 bits that were previously on the very right are now in the leftmost 8 bit positions of variable a, like this: a<<24.
We are working with 32 bit integer variables and that means that in this first case, any bits beyond the intended 8 bits were “shifted out” to the left and are now gone. There is no problem here yet. We simply OR it to the result variable. The result R now contains the first 8 bits of the IPv4 address and they are correct.
Only when we want to do the same with variable b, c or d is when problems might appear. If we do the same as above with b, we now only need to shift to the second octet to the left: b<<16. If we simply put out shifted b into our result variable R by OR-ing it with the current result, we not only add 8 bits of information to our result, but possibly 16. In this case the input was 0, so nothing bad has happened yet.
We repeat the same for c by shifting it by only one octet: c<<8 and as c is also 0, nothing bad happens when we or it together with the previous result.
Now in the last step is where the (minimal) example from above gives us problems. In this case we do not need to shift at all (d<<0). Remember that our result R is still 0 at this point. If we now OR 0 and 2130706433 together, we just get 2130706433. This last step added 32 bits of information even though we only intended to add 8.
Our converted IPv4 address is valid and some might say we even did a correct conversion, but it is of course not the intuitive result we wanted.
As you can see, an attacker might choose b,c and d as they please to make the notation look irregular, but our conversion simply eats it up and spits out a valid address. That’s why it is important to always work with IP addresses as integer numbers in bit format. Convert first, then filter on that. You never know how somebody may have implemented the conversion and whether they reject odd choices like “0.0.0.2130706433”.
You could of course also prevent stuff like this by making the conversion smarter and have it reject a,b,c,d >256 or something similar, but then you are just putting bandaids on a simple problem with a simple solution. Our conversion had to work with 4 independent numbers in a loop. It’s best to only do that once and use 32 bit integers beyond that.
Does anyone know of a linux tool that can immediately ban an IP address if they try to log in to ssh with specific user names? I see a ton of attempts in my logs for names like fax, mysql, admin, and of course root. Fail2ban only works if the same IP makes repeated attempts but I’m betting if I could generate a list from these failed attempts it would probably correlate with standard blocklists of compromised hosts. For that matter, is there a way to use an RBL to limit addresses that ssh will even accept? Of course none of these attempts have a chance of logging in, but it would still be nice to further limit my exposure for any future attacks.
Sounds like a job for crowdsec. Basically fail2ban on steroids. They already have a ban scenario for attempts to exploit web application CVEs. While the default ssh scenario does not ban specific usernames, I’m pretty sure writing a custom one would be trivial (writing a custom parser+scenario for ghost cvs from no knowledge to fully deployed took me just one afternoon)
Another thing I like about crowdsec is the crowd sourced ban IPs. It’s super nice you can preemptively ban IPs that are port-scanning/probing other people’s servers.
It’s also MIT licensed and uses less ram than fail2ban.
Hmm I keep hearing about it but haven’t looked into it. One thing I have set up between my systems if they share the blocked IPs with each other so every server drops a blocked address at the same time… I assume crowdsec has something similar for local sharing so I don’t have to wait for a blocked IP to be sent to them, added to the database, and sent back to my local machines again?
One way to do this would be set up crowdsec bouncers on each server but only run a single instance of the crowdsec daemon. Send all logs to the daemon and let it communicate with all the bouncers.
Cool, thanks for the tip!
I use a ssh server on my notebook to sync files. is having public key authentification enough to mitigate this attack? are only ssh servers attacked which use password auth. ?