@ryanc@infosec.exchangeCoworker: ...and the IP address are compared with a string match.
Me: grinning manically
Coworker: Why are you looking at me like that?
Me: Open up a terminal and type ping 4.2.514 and hit enter.
Coworker: ...what's the fourth number?
Me: grin widens Just hit enter.
Coworker: WTF!?
@ryanc Well, that's something I didn't expect.
I mean... 2056 is 8*256 + 8, the maths makes sense, but WTFFFFFF?
@uastronomer @ryanc yeah, it's completely cursed
`ping 134744072`
```
>>> (8 * pow(256, 3)) + (8 * pow(256, 2)) + (8 * pow(256, 1)) + (8 * pow(256, 0))
134744072
```
or
```
sum(8 * pow(256, n) for n in range(4))
```
OK stepping away from the Python console now
@pikesley@mastodon.me.uk @uastronomer @ryanc huh, that's not too different from a phone number
@pikesley @uastronomer @ryanc Way back in the 90s I made someone angry with me when I gave the URL for a web site as http://[long number here]/whatever.html. Those were fun times.
@Austin_Dern @pikesley @uastronomer @ryanc
01189998819991197253.com/help.html
@ryanc@leitzke @Austin_Dern @pikesley @uastronomer the guy who made the it crowd is a monster
@pikesley @uastronomer @ryanc It’s actually really great, because it’s incredibly painful to do math with dotted decimal strings, especially when the netmasks don’t line up to a byte boundary. It’s much, much easier to convert them to a number and do math on the number.
For example, you can convert an interface’s IP number to an integer, convert its mask to an integer, and do a bitwise AND to get the lowest address. You can then bitwise NOT the mask integer and do a bitwise OR with the lowest address to get the highest address. And you can feed integers to seq or a for loop or whatever.
@ryanc@infosec.exchange I should start using 127.1 or even 2130706433 and see how much stuff gets very confused
@ryanc@yossi@techhub.social @dakkar technically, . is a valid hostname
@notsoloud @ryanc @_yossi_ @dakkar only a few years ago an island nation was serving on their top-level, can't immediately remember who
@zbrown @notsoloud @ryanc @_yossi_ @dakkar
I remember that at least one ccTLD used to have an MX record at the top level, to allow for vanity email addresses of the form 'user@zz'.
@ryanc WTF? (I only vaguely remember this)
@voltagex @ryanc An IPv4 address is a 32 bit number.
The representation of an address as four 8 bit numbers separated by dots is a convenience for the sake of UIs, it isn’t how any of the network stack treats addresses. They’re just 32 bit numbers.
4.2.514 is
00000100 . 00000010 . 0000001000000010
which is the same as
00000100 . 00000010 . 00000010 . 00000010
which is the same as
4.2.2.2
So when you ping 4.2.514 you get responses from 4.2.2.2.
@NewtonMark @voltagex @ryanc the WTF is not that it's a 32-bit value, but that the parsing code for text input supports this wild range of formats, because the canonical form wasn't settled at the time the original parser was written, so every possible representation was supported, and that support was never removed.
@NewtonMark @raven667 @voltagex @ryanc and never forget that 192.168.010.001 !== 192.168.10.1 (thanks octal representation)
@SeismoAllegra @NewtonMark @raven667 @voltagex @ryanc but at least IPv4-mapped IPv6 only allows either decimal (::ffff:127.0.0.1) or IPv6-style hexadecimal (::ffff:7f00:1)
@ryanc@autinerd @SeismoAllegra @NewtonMark @raven667 @voltagex you can write an ipv6 address with the last 32 bytes as dotted quad
@ryanc @SeismoAllegra @NewtonMark @raven667 @voltagex yeah, these are IPv4-mapped IPv6 addresses (the range ::ffff:0:0/96), these are for example used in Node.js (but also .NET and others support these), the big advantage is that you can deal completely with IPv6 addresses in your application (for example in a database) and the underlying layer takes care of the differences between IPv4 and IPv6.
@autinerd @SeismoAllegra @NewtonMark @raven667 @voltagex @ryanc Well.
`ping 0:00:000:0000::ffff:7f00:01`
@autinerd @NewtonMark @raven667 @voltagex @ryanc Despite most versions of Windows having a ridiculous UI in control panel that zero pads the decimal quad fields. Probably lots of routers, printers, etc. too.
@autinerd
If zero-padding to three digits forces octal parsing, then how can you force to treat e.g. 100.100.100.100 as octal? @NewtonMark @raven667 @voltagex @ryanc
@ryanc@martinrust @autinerd @NewtonMark @raven667 @voltagex
add a leading zero
@ryanc @martinrust @NewtonMark @raven667 @voltagex yep, 0100.0100.0100.0100, but this is more visible than 192.168.010.001, which can be very tricky
@autinerd
Understood. But if you want to try to go stealth, it's pointless to replace 1 by 001, because that makes no difference and it's very noticeable, right?
@ryanc @NewtonMark @raven667 @voltagex
@martinrust @ryanc @NewtonMark @raven667 @voltagex but it can fool someone unaware of the octal representation who thinks it's just padded zeroes so it looks nice with each segment being 3 digits, not aware that 192.168.010.001 == 192.168.8.1
@raven667 @NewtonMark @voltagex @ryanc There is still no standard text form for IPv4 addresses (unlike IPv6). x.y.z.t is just a common habit.
@raven667 @NewtonMark @voltagex @ryanc Yep, the IP address parsing is a minefield. Tons of different formats (octal, hexadecimal, IPv4-mapped IPv6 only to name a few), all supported. So many security issues due to this…
That's another of those I just lean on some library code to sort out...
@WPalant @raven667 @NewtonMark @voltagex @ryanc
@JessTheUnstill Definitely a good choice. Especially compared to everyone who decided “oh, an IP address is just a few dot-separated numbers, let’s throw in a regex” (have been guilty of that myself in some distant past).
@WPalant @JessTheUnstill @NewtonMark @voltagex @ryanc I mean, I usually don't intentionally support all the weird possibilities, I usually use a simple regex to untaint (perl) the common dotted quad or /([0-9a-f:]+)/then canonicalize with Net::Netmask or NetAddr::IP, or use the more complex regex from Regex::IPv4 / IPv6 if I'm feeling special. I think in most cases it's not a real problem because the user can enter whatever they want, any sanity checks happen after canonicalization so what weird format they use to enter the IP doesn't really matter.
@ryanc@JessTheUnstill @WPalant @raven667 @NewtonMark @voltagex I trust myself more than I trust IP parsing libraries.
@ryanc I trust it that you personally considered everything with your own IP parsing library but really: this is bad general advise. The trouble starts when your library processes that “cursed inet_aton nonsense” and passes it on to something that actually uses inet_aton or similar logic. And then your security checks are no longer valid because what you considered a DNS-resolvable host name is treated as an IP address further along the line, or what you considered decimal numbers is treated as octal. I’ve seen vulnerabilities due to such parser mismatches and avoiding them is very tricky.
@NewtonMark @voltagex @ryanc
I just pinged 8.8.2056
Thanks for the thought provoking and making me think today.
@NewtonMark @voltagex @ryanc @ljrk Depending on which library was used for a program, if you include a leading zero, the computer may parse something as an octal number so 010.010.010.010 would be parsed as 8.8.8.8.
@NewtonMark @voltagex @ryanc Just tried `ping 67240450` and it works too! o_O
@gumnos @voltagex @ryanc The relevant code is inet_aton(), which takes an ASCII string as input and deposits its protocol-specific bit field equivalent in the supplied struct inet_addr buffer.
(and its friend inet_ntoa() which takes a struct inet_addr and returns an ASCII string)
These are OS-wide functions provided by libc, and will be used by virtually all network applications on a given system.
(“Virtually” all because this is userland, there’s no reason why an application developer can’t replace them with something else if they wish … but why would they when they get these for free?)
Can you treat the bits as a single precision floating point number? Is this the equivalent of pinging 1.5282349e-36?