Misunderstanding nmap -sn : It’s not a ping scan!
So it turns out I’ve misunderstood the behaviour of my most commonly used nmap option this entire time!
I was under the impression that -sn “ping scan” did a simple ICMP sweep of the provided hosts/subnets, avoiding any port scanning. Great for finding free IPs on your network…
…or so I thought, until today, when I realised the -sn scan wasn’t finding all devices on my home network, even though they responded to direct pings.
Reading the nmap reference guide, I can see why I made this assumption:
-sn
(No port scan)This option tells Nmap not to do a port scan after host discovery, and only print out the available hosts that responded to the host discovery probes. This is often known as a “ping scan”, but you can also request that traceroute and NSE host scripts be run.
So in my defence, the above is a little misleading, as a “port scan” does occur (of sorts, on TCP 80 and 443, as we’ll see below), and a “ping” scan certainly implies ICMP pings to me.
If we read on however, we see that -sn works differently depending on the privilege level of the user running nmap, and whether or not the target is on the same subnet as the scanner:
The default host discovery done with
-sn
consists of an ICMP echo request, TCP SYN to port 443, TCP ACK to port 80, and an ICMP timestamp request by default. When executed by an unprivileged user, only SYN packets are sent (using aconnect
call) to ports 80 and 443 on the target. When a privileged user tries to scan targets on a local ethernet network, ARP requests are used unless--send-ip
was specified.
You really do have to read that carefully to understand exactly what -sn is doing, and there is a subtle difference between a port scan and a TCP discovery probe. So let’s see it in action to explain why the -sn option wasn’t picking up a device on my home network.
The machine performing the scan is a Linux box on 192.168.0.14. Here are the results of the basic -sn scan:
user01@laptop1:~$ nmap 192.168.0.0/24 -sn
Starting Nmap 7.91 ( https://nmap.org ) at 2020-10-26 08:05 GMT
Nmap scan report for 192.168.0.1
Host is up (0.0078s latency).
Nmap scan report for 192.168.0.5
Host is up (0.00020s latency).
Nmap scan report for 192.168.0.11
Host is up (0.0018s latency).
Nmap scan report for 192.168.0.14
Host is up (0.00018s latency).
Nmap scan report for 192.168.0.223
Host is up (0.00057s latency).
Nmap scan report for 192.168.0.251
Host is up (0.0013s latency).
Nmap done: 256 IP addresses (6 hosts up) scanned in 2.38 seconds
All seems fine, except while experimenting with the below command for TCP host discovery, I found a device the -sn scan missed:
user01@laptop1:~$ nmap -PS21-25,80,110,443,3306,3389,8000,8080,445,139 192.168.0.0/24
Starting Nmap 7.91 ( https://nmap.org ) at 2020-10-26 08:03 GMT
...
Nmap scan report for 192.168.0.14
Host is up (0.00011s latency).
All 1000 scanned ports on 192.168.0.14 are closed
Nmap scan report for 192.168.0.222
Host is up (0.00055s latency).
Not shown: 996 filtered ports
PORT STATE SERVICE
135/tcp open msrpc
139/tcp open netbios-ssn
445/tcp open microsoft-ds
3306/tcp open mysql
Nmap scan report for 192.168.0.223
Host is up (0.00028s latency).
Not shown: 986 closed ports
...
Nmap done: 256 IP addresses (7 hosts up) scanned in 76.34 seconds
So lets look at a packet capture of the first command, against the device on 192.168.0.222 that we now know exists:
nmap 192.168.0.222 -sn
Only TCP 80 and 443 requests are present, which this device does not have open. The manual states, “When executed by an unprivileged user, only SYN packets are sent (using a connect
call) to ports 80 and 443 on the target.”
So let’s elevate the command, sudo nmap 192.168.0.222 -sn. Now we get a response from the host:
user1@laptop1:~$ sudo nmap 192.168.0.222 -sn
Starting Nmap 7.91 ( https://nmap.org ) at 2020-10-26 08:55 GMT
Nmap scan report for 192.168.0.222
Host is up (0.00038s latency).
MAC Address: 54:04:A6:4B:A3:28 (Asustek Computer)
Nmap done: 1 IP address (1 host up) scanned in 0.15 seconds
I still didn’t see the expected ICMP traffic when capturing this command in Wireshark. Again, the manual has the answer (who would have thought it!); “on a local ethernet network, ARP requests are used unless --send-ip
was specified”. Indeed, the scanner and target are on the same subnet, so ARP requests are used, not ICMP and/or TCP. Once we specify –send-ip, we see the full scan, as we would if the target was on a different subnet:
sudo nmap 192.168.0.222 --send-ip
In practice, I would always have used this command targeting a different subnet, so it was generating the desired ICMP sweep anyway. In theory though, I didn’t understand what this command was doing, so I was coming to potentially false conclusions.
And as a final thought; what is a good nmap command to find free IPs anyway? Even though I wanted an ICMP sweep using -sn, I was still aware that a host firewall could potentially be blocking ICMP traffic. Cross referenced with an IPAM, the combination is reliable enough, but still not ideal. From a single network scan, how can we pick up the hosts not responding to pings? A combined ARP/ICMP (-sn) and TCP scans on common open LAN management ports (-PS), ensuring that nmap is run under privileged mode, is probably the way I’ll do it going forward. Let me know if there’s a better way!
sudo nmap -PS22,23,80,443,3389 x.x.x.x/x -sn