Effective Network Scanning with Nmap: A Practical Workflow

Radar scanning iconography of various connected laptops, servers, and routers.

There’s a ton of content about the network mapping tool, nmap, and rightfully so. It’s a powerful tool in the hands of a capable user.

But most of the tutorials out there are just regurgitations of the man page or docs in various forms. Many only cover basic usage of the tool that can be learned by typing nmap -h.

So, in this post, I’m going to take a more practical approach by showing you how to efficiently scan a network from the host discovery phase to in-depth enumeration.

Host discovery

Before we start scanning ports, we need to know what hosts are available to scan.

We can do that by telling nmap to omit the port scan and just do host discovery with -sn:

$ sudo nmap -sn 192.168.1.0/24 -oA host_discovery

Starting Nmap 7.95 ( https://nmap.org ) at [timestamp]
Nmap scan report for 192.168.1.1
Host is up (0.0042s latency).
MAC Address: DC:62:79:**:**:** (Unknown)
Nmap scan report for 192.168.1.2
Host is up (0.087s latency).
MAC Address: 16:1A:32:**:**:** (Unknown)
Nmap scan report for 192.168.1.90
Host is up (0.11s latency).
MAC Address: B8:A1:75:**:**:** (Roku)
Nmap scan report for [hostname redacted] (192.168.1.171)
Host is up (0.18s latency).
MAC Address: C0:35:32:**:**:** (Liteon Technology)
Nmap scan report for 192.168.1.231
Host is up (0.098s latency).
MAC Address: C2:3D:99:**:**:** (Unknown)
Nmap scan report for 192.168.1.58
Host is up.
Nmap done: 256 IP addresses (6 hosts up) scanned in 3.33 seconds

Now, we have a list of live hosts available for scanning.

You may have noticed that I used -oA to save the output to all nmap supported output types: normal, greppable, and XML. I’d rather save the output into extra formats I may not use instead of missing a format and having to rescan.

As a pentester, time is more valuable than disk space.

Scanning

Now that we know what hosts are available on the network, we can begin scanning for open ports.

To make this easy, I put the IPs of the live hosts in a file by parsing the greppable output from earlier:

$ grep 'Host:' host_discovery.gnmap | cut -d ' ' -f 2 | tee live_hosts.txt

192.168.1.1
192.168.1.2
192.168.1.90
192.168.1.171
192.168.1.231
192.168.1.58

This way, I can pass nmap the file instead of typing out each host. You can see how tedious this would be if I were scanning a much larger network with hundreds of hosts.

Initial port scan

Now that we have some live targets, it’s time to start scanning.

Using the -iL option, I can directly pass the list of live hosts to nmap:

$ sudo nmap -iL live_hosts.txt -sT -F -Pn -oA fast_scan_all_hosts
Starting Nmap 7.95 ( https://nmap.org ) at [timestamp]

Nmap scan report for 192.168.1.1
Host is up (0.034s latency).
Not shown: 96 closed tcp ports (conn-refused)
PORT     STATE SERVICE
53/tcp   open  domain
80/tcp   open  http
443/tcp  open  https
1900/tcp open  upnp
...

Nmap scan report for 192.168.1.231
Host is up (0.020s latency).
Not shown: 99 closed tcp ports (conn-refused)
PORT      STATE SERVICE
49152/tcp open  unknown

...

For brevity, I only included the hosts that returned open ports.

You may have noticed that I used the -F option in this scan. This makes nmap only scan the top 100 most common (according to statistical data) ports. Otherwise, nmap would scan for the top 1000 ports.

I limit the scan significantly for speed because I plan on using this information to prioritize targets for more in-depth analysis.

Just a few open ports can reveal a lot about a host’s role within a network. In this example, it is clear that the 192.168.1.1 system is a router. It has web ports 80 and 443 open, which is likely an admin interface. 1900 is also Universal Plug N Play, a protocol commonly used by residential routers to easily connect devices.

On an enterprise network, this similar train of thought could help you identify web servers, workstations, databases, file servers, and domain controllers that may be more critical targets to attack than, for example, mail servers and printers.

It’s also worth noting that you can adjust the depth of this initial scan depending on how many hosts you’re scanning at once. If you have hundreds of hosts to scan, you may want to use --top-ports to scan fewer hosts:

sudo nmap -Pn -iL live_hosts.txt -sT --top-ports 50 -oA fast_scan_all_hosts

Or, if you’re seeking specific targets, like web servers for example, you can supply ports with -p:

sudo nmap -iL live_hosts.txt -sT -p 53,80,443,3006,8080 -Pn -oA fast_scan_all_hosts

You have control depending on the context of the network you are scanning. That is the beauty of using nmap modularly in this way!

Those of you with keen eyes may have also noticed that I used -sT to use a full TCP connect scan instead of the default -sS (SYN) scan. I chose this because flooding a network with SYN packets can trigger alerts. I picked this tip up from Tim Medin’s Sec560 course on SANS.

Full port scan

Now that we’ve picked out targets to scan, it’s time to discover more ports.

Specifically, I want to scan all of the ports on each of my selected targets. Or, at least more than my initial scan, depending on the context (remember, you have the power)!

For the sake of this example, I’ll just scan the router:

$ sudo nmap -Pn -sT -p- --open 192.168.1.1 -oA all_ports_1
    
Starting Nmap 7.95 ( https://nmap.org ) at [timestamp]
Nmap scan report for 192.168.1.1
Host is up (1.1s latency).
Not shown: 56546 closed tcp ports (conn-refused), 8985 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT      STATE SERVICE
53/tcp    open  domain
80/tcp    open  http
443/tcp   open  https
20001/tcp open  microsan

Nmap done: 1 IP address (1 host up) scanned in 35.12 seconds

I used -p- as a shortcut for all 65,535 ports. And it paid off because I discovered a new port to probe!

This is why it’s important to consider all ports. Although it may take some extra time, you may find uncommon (and potentially less secure) open ports.

Now it’s time to go even deeper and enumerate the ports.

Deep scan

nmap has some amazing enumeration capabilities. We’ll save more advanced scanning for a later post, since there is a lot to cover there.

For now, a version+script scan with -sVC will suffice:

$ sudo nmap -Pn -sVC -p 53,80,443,20001 192.168.1.1 -oA version_script_1

Starting Nmap 7.95 ( https://nmap.org ) at [timestamp]
Nmap scan report for 192.168.1.1
Host is up (0.0061s latency).

PORT      STATE SERVICE    VERSION
53/tcp    open  tcpwrapped
| dns-nsid: 
|   NSID: rochnyei-dns-cac-308 (726f63686e7965692d646e732d6361632d333038)
|   id.server: rochnyei-dns-cac-308
|_  bind.version: Akamai Vantio CacheServe 7.7.3.0.d
80/tcp    open  http       BusyBox http 1.19.4
|_http-title: Site doesn't have a title (text/html).
443/tcp   open  ssl/http   BusyBox http 1.19.4
| ssl-cert: Subject: commonName=tplinkwifi.net/countryName=CN
| Subject Alternative Name: DNS:tplinkwifi.net, IP Address:192.168.1.1
| Not valid before: 2010-01-01T00:00:00
|_Not valid after:  2030-12-31T00:00:00
|_http-title: Site doesn't have a title (text/html).
20001/tcp open  ssh        Dropbear sshd 2019.78 (protocol 2.0)
MAC Address: DC:62:79:DB:24:C8 (Unknown)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 44.24 seconds
                                                              

I supplied only the open ports detected earlier during the full scan with -p.

-sVC is a short hand for:

  • -sV: Version scan. nmap probes the port to get the service version.
  • -sC: Script scan. Uses a set of scripts part of the Nmap Script Engine to enumerate ports.

As you can see, this gave us tons of juicy info! Let’s go over what we learned about this device:

  • This is a TP-Link router based on the SSL certificate’s common name
  • The mystery port (20001) is running ssh
  • It’s running some form of Linux

We could probe further and look up versions for more information or potential known vulnerabilities. But this is an excellent start!

Where to go from here…

As you can see, nmap is a very powerful scanning tool when used effectively. We were able to find a lot of information from just a few scans.

But this is just the beginning! You’ll want to repeat the process with more hosts. And the beauty of this modular system is that you can adjust each step to suit your needs.

After scanning more hosts, you’ll have a pretty good idea of which hosts you want to dig into and eventually exploit. Luckily, nmap has some incredible enumeration and scripting capabilities that can make it a great tool for the job. I promise I’ll do an nmap scripting deep dive later.

If you’re saving every scan in multiple formats (as you should), things can get messy fast. Fortunately, tools like Metasploit can import nmap XML output to help manage and analyze your findings. I’ll cover that soon.

Hope you enjoyed this, and stay tuned for more related content!