By Steve Lord in Pentesting | February 23, 2016
Beyond the basics, there are various little things pentesters need know about when it comes to network mapping. It's quite surprising how many people get these things wrong, until you actually look at the RFCs behind them. The tricks I'm going to show you are actually based mostly on implementation gaps, and as such it's not surprising that people get them wrong (I know I sometimes do), but keep this post handy as a reference and you'll be able to learn from my mistakes.
ICMP Address mask messages
ICMP can be used to identify a given target host’s IP address mask (also called a subnet mask), which can be useful in distinguishing subnets within an IP address range. This is achieved by sending an ICMP address mask request to our target. Hosts that implement ICMP address mask responses may then respond with an ICMP address mask reply containing the host’s 32-bit subnet mask. Most hosts won’t respond to ICMP address mask messages, but it’s useful to know when they do as this often signifies an older TCP/IP stack in use and might indicate the presence of other vulnerabilities. We can use nmap to test for this, but to look at this in more detail we’ll use the excellent hping and Wireshark.
The switches used are fairly straightforward. The --icmp-addr
flag tells hping that we’re sending an ICMP address mask request, while -c 3
tells hping to send three packets before giving up. The final argument is the target IP address. As you can see there’s no response here. If you have a metasploitable 2 VM to hand, try it and you should get the same results.
Looking at the packet in wireshark above we can see that the request uses an ICMP type of 17 and a code of 0. There’s a checksum then two identifiers and sequence numbers. These are simply big and little-endian representations of the same data, which you can see starting at byte 0x0026 of the hex dump at the bottom. You’ll notice that the client sends an address mask as part of the protocol, in this case 0.0.0.0. This may be part of the reason that a response wasn’t received as the Address mask being sent shouldn’t be 0.0.0.0 in all cases, with the rules being a little confusing and spread across multiple RFCs (See page 11 of RFC 950, pages 46 and 46 of RFC 1122 and pages 61 and 62 of RFC 1812 for specific details). If you do see an ICMP address mask reply, the correct type and code are type 17 and code 0. The address mask will provide the remote system or network’s subnet mask depending on whether the target is an individual host or a gateway.
ICMP Timestamp requests
ICMP can also be used to obtain timestamps from remote systems. This is particularly useful when looking into time-based activity, such as nightly scheduled tasks. However, over the years many Operating Systems have implemented less accurate timestamps, making this rather a useless protocol. We can still use it as an alternative to ping when things are filtered and sometimes it will provide suitably accurate time.
An ICMP timestamp request is sent using an ICMP type 13 and code 0. As with the address mask request there’s an identifier and sequence number. We can also see an originate, receive and transmit timestamp. The originate timestamp is the number of seconds after midnight on the sender’s host. Wireshark has turned this timestamp into a human readable time for us in the screenshot above. In this example the time is off by around 4 hours.
In the screenshot above we see an ICMP timestamp reply message. The format is pretty much identical except for the message type of 14 and that the receive and transmit timestamps have been populated. The receive timestamp is the number of seconds since midnight on the target host at the point of receiving the request. The transmit timestamp is the number of seconds since midnight on the target host at the point of sending the reply. In all cases, timestamps are based on UTC time rather than the systems own timezone and in both the sender and the recipient’s case the actual time is off by around 4 hours.
We can send timestamp requests using nmap or hping. In this example I’ll use hping as it provides the actual timestamps in a readable format.
The command line used is the same as with the address mask request. The only difference is the use of --icmp-ts
to specify an ICMP timestamp request instead of --icmp-addr
for an ICMP address mask request.
While it might seem a little useless, one thing that I have found useful with timestamp requests is when you have a host that has multiple IP addresses and poor network time synchronisation. Such hosts tend to show up with a continuation of the same ICMP timestamp responses, while different hosts vary slightly. This then makes the host’s interfaces stand out across a network.
IP Record route option
For years I struggled with how this worked until one day while researching this book I found the answer in an obscure corner of W. Richard Stevens’ TCP/IP Illustrated volume 1. If you don’t own a copy you should definitely get one. This and volume two are the definitive books on TCP/IP theory and implementation. Because they were amongst the first books to describe TCP/IP in so much detail, they became a standard reference guide for people writing TCP/IP stacks.
The IP record route option is an IP option that allows up to 9 hops of a packet’s journey to be recorded and sent back to the sender. When the option is set (usually using ping, but other codes, messages and protocols may or may not work), every intermediary router that supports IP record route will add the IP address of it’s outgoing interface to a list in the IP options field. When the packet reaches it’s destination the list of IP addresses is copied into the outgoing ICMP echo-reply message. As the packet makes it’s way back to the originating sender, each router adds its outbound IP to the list again. When it reaches it’s final destination the ping command processes the recorded route and prints it out to the user.
There are several problems with this functionality. It was originally designed for the Internet’s predecessor, the Arpanet. As such, it only supports storing up to 9 IP addresses. Furthermore a lot of how the record route was implemented is optional at best. Despite this, it’s worth trying. If you have a Virtualbox-based lab, you may struggle with the sockets needed to implement record route, so like me you might find it won’t work from a Kali Linux VM. Instead, I’ll show you how it works from a physical OSX system using ping with the record route option -R to a Linux system behind a VPN.
In the screenshot above I’m pinging the host zardoz (10.69.0.5) from fluffykittens (192.168.1.23). If we work from the bottom of the list up you can see that fluffykittens passes through the local side of vpngw before reaching zardoz. The packet then heads back through the VPN side of vpngw before reaching fluffykittens. I like kittens.
IP ID and load balancers
You may have noticed that when we’ve used hping there’s an id value, normally 0. Historically the IP id increments by one for each IP datagram sent, then resets once it passes 65535. This used to be particularly useful for finding load balancers by looking at patterns in IP ID sequences. For example, lets imagine that bob has a server farm using IP load balancing.
When alice makes a request the load balancer forwards the connection on to server A. The next request is sent to server B, then the following one to C and the fourth back to A. This is called round robin load balancing. For each IP datagram that each server sends, they’ll increment their IP ID by 1 until it reaches 65535 at which point it will normally wrap around to 0.
Under this scenario, if Alice was to then send another 3 packets to Bob’s load balancer, then the results would traditionally look like this:
I say traditionally because there’s been some changes to common architecture patterns over the last decade, but from the network the results mostly look the same or similar. As you can see from the two pictures above it’s pretty easy to find out that there are 3 hosts behind Bob’s load balancer by monitoring IP IDs. You can also abuse this to work out how busy a system is by looking at the rate of IP ID increments. A busy site might see a large jump in IP IDs over a short period of time compared to a quiet one that might only go up by one with each probe, indicating no real activity.
Many Operating Systems now will provide an IP ID of 0 for SYN-based probes to open ports using tools like hping, but there are still applicable workarounds. For example, the IP ID is still tracked internally on the system even if it’s not exposed, so by establishing a connection the IP ID will appear on some Operating Systems. This slows us down but can still be automated.
Some Operating Systems will respond with the correct IP ID value if your SYN packet is sent to a closed port. Another trick is to simply use a different TCP flag that will always solicit a response, such as the ACK flag.
Because we’re working at the IP layer, our VirtualBox lab might rewrite some of the packet details including the IP ID. Lets take a look at some techniques that I used to perform IP ID analysis on the rawhex.com server.
In the example above I used hping to send 3 TCP SYN packets on port 80 to rawhex.com. You can see in the results that the IP ID is set to 0. When I send packets with only the TCP ACK flag set the IP ID appears and each packet increments by one. When using hping the -S and -A flags tell hping to send a TCP packet with the SYN or ACK flags set respectively. You can use this in combination to specify that both SYN and ACK flags should be set by using -SA for example.
What About ICMP Information Requests?
There are large differences between the formal specification for a set of standards and their implementation. The rules governing ICMP are specific enough to mandate particular responses under specific circumstances, but not specific enough to define the exact structure of those responses beyond messages and code types.
The impact of this is that by looking at different known ICMP implementations and their behaviours, we can then apply our knowledge of those behaviours to identify systems using known ICMP implementations. This is basically the core behind every form of service fingerprinting as well as OS fingerprinting: find stuff that matches what you know, and when enough samples are obtained to be confident in your assessment, you’re usually right. We’ll look at this in detail in a different blog post, but to answer the question about ICMP Information requests we need to look at how they’re applied in Operating System fingerprinting.
In his seminal paper, ICMP Usage in Scanning, Ofir Arkin summarises the standard responses to ICMP information, timestamp and address mask requests for various Operating Systems. As the paper was released in 2001 the information is substantially out of date, and you’re unlikely to come across systems running the software tested at the time. However, it’s worth bearing in mind across general Operating System families and may come in useful if you find Nmap saying one thing, but other tools saying the OS is something different.
If you’ve worked along with this blog post, trying out the commands I’ve tried, you should be able to look at your results for the timestamp and address mask requests and compare to the table in section 3.5 of Arkin’s paper. It’s unlikely your results will match, but it’s worth checking in this case. Now you may be thinking, “What about ICMP Information requests?” Well, there are two answers.
1. Information requests were obsolete when the paper was released, they're even more obsolete now.
2. We can already probe firewall filtering through the other requests, sending information requests across the Internet or a large network is unlikely to tell us anything new as the de facto standard for handling these requests appears to be not to respond even if it hits the host.
ICMP Information Requests and Replies are two messages (Type 15 and 16) that were used to help systems boot and obtain IP functioning addresses, before BOOTP and DHCP were popular. A system that responds to these messages is not only extremely old, it’s also supporting functionality to allow extremely old systems to boot off a network. The bottom line is that you shouldn’t really expect to see this in a real-world environment, but if you really want to send a request, you can do so via hping3 with the --icmptype 15
command line switch.
Conclusions
Tools like Nmap and Traceroute are great for helping to map out networks, but to be a successful pentester you need to understand the underlying protocols being used. In this blog post we looked at:
- ICMP Address Mask Messages
- ICMP Timestamp Requests
- The IP Record Route option
- IP Identifiers and load balancers
- ICMP Information requests (and why we don’t use them anymore)
Thankfully the underlying protocols used by these techniques are fairly straightforward and easy to understand and apply in a network mapping context. Being able to build a network diagram is an essential network infrastructure penetration testing skill. Hopefully this post has helped you further along the way.
Further Reading
If you’ve enjoyed this post, you might want to look at the unhealthy journey into the world of the traceroute post. I’m posting more technical material on networking and pentesting over the coming months. If you’d like to get a heads up of coming posts, subscribe to my mailing list below.