Host Discovery with Nmap
I'd originally planned to start my Nmap adventure a bit further in, but realized partway through post #1 that it should actually be post #2. I failed to appreciate the importance of the discovery phase.
Phases of an Nmap Scan
Before we get into the good stuff, let's take a moment to get to know the phases of an Nmap scan.
- Script pre-scanning: Only applies when
--scriptis used and a script needs it.
- Target enumeration: Targets are resolved to an IPv4 or IPv6 address.
-sL -nwill cause this to just print the list of targets.
- Host discovery (ping!): Uses various techniques to discover hosts. Using
-sn -nwill cause the scan to terminate after this phase.
-Pnwill skip this phase.
- Reverse-DNS resolution: Reverse DNS lookups for all alive hosts. Can be skipped with
-nor done for all hosts, even down ones, using
- Port scanning: Probes sent to ports. Ports are assigned open, open|filtered, closed, or filtered status. Skipped with
- Version detection: If
-sVwas specified, Nmap will attempt to fingerprint the service.
- OS detection: If
-Owas specified, Nmap will attempt to identify the target's operating system.
- Traceroute: If
--traceroutewas specified, Nmap will traceroute the target and perform reverse DNS lookups on each hop.
- Script scanning: If
--scriptwas specified, Nmap will perform its scripty magic.
- Output: Display output to screen, or write to file (
The most important thing to understand here is that if a host is not identified in the discovery phase (step 3), no further actions will be performed on it. Seems obvious when you write it out, but underscores the important of getting the discovery phase right. Which is what we're now going to discuss.
Default Host Discovery Settings
A basic Nmap ping scan looks like this:
nmap -sn <targets>. Expanded, this is actually
nmap -PE -PP -PR -PS443 -PA80.
What does this do, exactly?
-PE- ICMP echo request
-PP- ICMP timestamp request
-PR- ARP ping (if target is on the same subnet)
-PS443TCP SYN ping to port 443
-PA80TCP ACK ping to port 80
Nmap Internet Host Discovery
Nmap's options here are pretty solid; I think they were designed with external scans in mind. The
-PS scans each check open TCP ports, but depending on firewall configuration one may work better than the other. You may want to double up on these (
Nmap Internal Host Discovery
Using Nmap's default discovery settings, if the remote host has ICMP enabled (
-PE, -PP), is on the local subnet (
-PR), or is listening on ports 80 or 443 (
-PS, -PA), we'll get a response. ICMP is disabled by default on many host-based firewalls/IPS but we've got a few other options to compensate for that.
Let's see what ports domain-joined Windows 10 system is listening to by default:
So in its default state, Nmap would totally miss this host unless it was on the same subnet where the ARP ping would pick it up. It would miss pretty much every other Windows host in their default state as well.
That is less than ideal.
Assuming we're scanning hosts beyond the local subnet, what we really want in our discovery phase is a good guess at the kind of ports we're going to find in the environment.
Here's a good start:
|Target Type||TCP Ports|
|Windows||80, 135, 443, 445, 3389, 5985|
|Linux & Network Devices||21, 22, 23, 80, 443|
The above list is based mostly on personal experience doing port scans and should detect most hosts. If you're scanning a remote network and can't afford to miss a few hosts, read on.
The Nuclear Option(s)
If you cannot miss a host and are willing to wait, you've got two options:
-Pn- Skip discovery phase and assume all hosts in the target range are up.
-PS1-65535- Perform a SYN ping on all ports to all hosts in the target range.
I got tired of waiting for these two to complete in my lab against a /24. I suspect the first option will be faster since the second effectively opens a connection on all 65535 ports on every host in the scope, while the second will only scan the ports you tell it to using
A Less Direct Approach
Depending on the information available to you, a less direct approach may be possible. If you've got access to a DNS server that will have PTR records for your targets, you can just query that directly for records without touching your target.
This sort of scan is also helpful if you're trying to validate your scope and/or if you're just lazy and want to turn a subnet into a list of IPs.
--dns-server parameter is optional; if your host OS is already configured to use a DNS server with the appropriate records, you can just leave that part off.