If there’s one tool every penetration tester should know it’s nmap
. In this post, I’m going to teach you how to use it practically as one might use it in a real-world testing scenario.
Don’t let the title fool you. Although we’re going to cover the basics here, we’re going to take a deeper dive into how to use this tool effectively. So, I’ll assume you have at least a basic understanding of the Internet and the protocol stack.
Overview
nmap
is an open-source command line tool used to discover hosts connected to a network and expose what services might be listening on those hosts. It is extremely popular because it can map an entire network automatically, while also being flexible.
I’m going to expose you to the more technical features of the tool while teaching you the basics so that you can use it flexibly and confidently. So, let’s jump into it!
Host Discovery
The first step in testing a network is figuring out what hosts (computers connected to a network) are up and running. After all, computers need to be powered on and connected to the same network we’re on for us to be able to attack them. We also don’t want to blindly spray exploits to all addresses–that’s just noisy and a waste of time.
To get started with host discovery with nmap
it’s as simple as running it and giving it a range of ip’s (or a single hostname/ip):
$ nmap 192.168.186.0/24
Starting Nmap 7.93 ( https://nmap.org ) at 2023-03-17 13:51 PDT
Nmap scan report for 192.168.186.2
Host is up (0.00070s latency).
Not shown: 999 closed tcp ports (conn-refused)
PORT STATE SERVICE
53/tcp open domain
Nmap scan report for 192.168.186.71
Host is up (0.0021s latency).
Not shown: 997 closed tcp ports (conn-refused)
PORT STATE SERVICE
22/tcp open ssh
53/tcp open domain
389/tcp open ldap
Nmap scan report for 192.168.186.93
Host is up (0.0019s latency).
Not shown: 999 closed tcp ports (conn-refused)
PORT STATE SERVICE
22/tcp open ssh
Nmap scan report for ms2 (192.168.186.131)
Host is up (0.0023s latency).
Not shown: 977 closed tcp ports (conn-refused)
PORT STATE SERVICE
21/tcp open ftp
22/tcp open ssh
23/tcp open telnet
25/tcp open smtp
53/tcp open domain
80/tcp open http
111/tcp open rpcbind
139/tcp open netbios-ssn
445/tcp open microsoft-ds
512/tcp open exec
513/tcp open login
514/tcp open shell
1099/tcp open rmiregistry
1524/tcp open ingreslock
2049/tcp open nfs
2121/tcp open ccproxy-ftp
3306/tcp open mysql
5432/tcp open postgresql
5900/tcp open vnc
6000/tcp open X11
6667/tcp open irc
8009/tcp open ajp13
8180/tcp open unknown
Nmap done: 256 IP addresses (4 hosts up) scanned in 14.55 seconds
I used the range 192.168.186.0/24
which is the equivalent of 192.168.186.0-255
, or the subnet of my virtual network. As you can see, it produced quite a bit of output. I just wanted to see the hosts online and nmap
went ahead and did a TCP-connect port scan on the top 1000 common ports as well.
This is nice and all but it clutters up my terminal with more than I needed. We can use the -sn
option to tell nmap
not to do a port scan:
$ nmap -sn 192.168.186.0/24
Starting Nmap 7.93 ( https://nmap.org ) at 2023-03-17 13:57 PDT
Nmap scan report for 192.168.186.2
Host is up (0.0032s latency).
Nmap scan report for 192.168.186.71
Host is up (0.0019s latency).
Nmap scan report for 192.168.186.93
Host is up (0.0013s latency).
Nmap scan report for ms2 (192.168.186.131)
Host is up (0.0042s latency).
Nmap done: 256 IP addresses (4 hosts up) scanned in 2.32 seconds
Much better. If you notice at the bottom of the scan, this was performed much faster (2.32 seconds vs 14.55 seconds in the first scan). This might seem marginal at first but imagine scanning a much larger network (like a business network).
By default, nmap
uses a variety of methods to determine if a host is online. Let’s check this out by scanning a single host:
$ sudo nmap -sn -vv ms2
Starting Nmap 7.93 ( https://nmap.org ) at 2023-03-17 14:01 PDT
Initiating ARP Ping Scan at 14:01
Scanning ms2 (192.168.186.131) [1 port]
Completed ARP Ping Scan at 14:01, 0.04s elapsed (1 total hosts)
Nmap scan report for ms2 (192.168.186.131)
Host is up, received arp-response (0.0013s latency).
MAC Address: 00:0C:29:7B:A1:58 (VMware)
Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 0.17 seconds
Raw packets sent: 1 (28B) | Rcvd: 1 (28B)
I used the -vv
option to make nmap
spit out very verbose output so it can tell us what it’s doing step by step. ms2
is a hostname I configured my system to recognize as 192.168.186.131
(my metasploitable instance). As I mentioned earlier, you can supply nmap
with a human-readable hostname and it will automatically go out and resolve the IP address for you.
Reading the output, we can see that nmap
ran an ARP scan and started a port scan, but after the ARP scan finished, it deemed the host was up. This is because nmap
will use a variety of methods to scan a host, including:
- ARP scan (local network only)
- ICMP echo request
- sending a TCP SYN packet to port 443
- sending a TCP ACK packet to port 80
- sending an ICMP timestamp request
If these methods fail, the host is considered offline. Those of you with keen eyes will notice that I ran nmap
with sudo
. That’s because nmap
relies on packet crafting to do some of it’s scans, which requires root level privileges. Let’s see what happens when we run it without sudo
…
$ nmap -vv -sn ms2
Starting Nmap 7.93 ( https://nmap.org ) at 2023-03-17 14:00 PDT
Initiating Ping Scan at 14:00
Scanning ms2 (192.168.186.131) [2 ports]
Completed Ping Scan at 14:00, 0.00s elapsed (1 total hosts)
Nmap scan report for ms2 (192.168.186.131)
Host is up, received syn-ack (0.0020s latency).
Nmap done: 1 IP address (1 host up) scanned in 0.00 seconds
This time, nmap
performed a ping scan instead of an ARP scan and performed a TCP scan as well. The TCP scan received a SYN-ACK
which is how nmap
was able to tell the system was online. It’s important to take this information into account as it could lead to some false negatives while testing (what if the host blocked ICMP traffic and the ports scanned)?
So, I would encourage you to use sudo
to get the most out of nmap
. You’ll definitely need it when I talk about performing different types of host discovery in the next few sections.
ARP Scanning
The first method of host discovery I’m going to talk about is ARP scanning. ARP or Address Resolution Protocol resolves IP addresses into MAC addresses. This protocol sits low on the stack, which means it has a low overhead (less data per packet) giving two key advantages when using it for scanning:
- Faster
- Stealthier (may slip past firewalls/IDS’s)
The only caveat is that it only works on local networks (can’t scan over the internet). So, know what context you’re scanning in!
We can perform an ARP scan with nmap
by telling it not to do ping scans with the -Pn
option:
$ sudo nmap -sn -PRn 192.168.186.0/24
Starting Nmap 7.93 ( https://nmap.org ) at 2023-03-17 14:59 PDT
Nmap scan report for 192.168.186.1
Host is up (0.0013s latency).
MAC Address: 00:50:56:C0:00:08 (VMware)
Nmap scan report for 192.168.186.2
Host is up (0.00045s latency).
MAC Address: 00:50:56:FC:7E:8B (VMware)
Nmap scan report for 192.168.186.71
Host is up (0.0047s latency).
MAC Address: 00:0C:29:91:6A:82 (VMware)
Nmap scan report for 192.168.186.73
Host is up (0.00098s latency).
MAC Address: 00:0C:29:39:19:E4 (VMware)
Nmap scan report for ms2 (192.168.186.131)
Host is up (0.0016s latency).
MAC Address: 00:0C:29:7B:A1:58 (VMware)
Nmap scan report for 192.168.186.254
Host is up (0.00078s latency).
MAC Address: 00:50:56:EA:7A:B5 (VMware)
Nmap scan report for 192.168.186.93
Host is up.
Nmap done: 256 IP addresses (7 hosts up) scanned in 2.02 seconds
You’ll notice that I also used the R
option with -P
. This is because I wanted to eliminate false positives by having nmap
perform Reverse DNS resolution on the hosts it finds, which it can only do with live hosts.
Doing it without, results in a mess:
$ sudo nmap -sn -Pn 192.168.186.80-85
Starting Nmap 7.93 ( https://nmap.org ) at 2023-03-17 15:03 PDT
Nmap scan report for 192.168.186.80
Host is up.
Nmap scan report for 192.168.186.81
Host is up.
Nmap scan report for 192.168.186.82
Host is up.
Nmap scan report for 192.168.186.83
Host is up.
Nmap scan report for 192.168.186.84
Host is up.
Nmap scan report for 192.168.186.85
Host is up.
Nmap done: 6 IP addresses (6 hosts up) scanned in 0.01 seconds
Here, I purposefully chose a range I knew didn’t have any connected hosts, yet nmap
still said they were up…
Using the R
option felt like a cheat, so you might be better of using a different tool like arp-scan
to do ARP scanning.
Ping Scanning
Higher up on the protocol stack is ping probing using the ICMP protocol. When most people think of pinging, they think of using the ping
command to send ICMP echo requests.
nmap
can use ICMP echo requests, as well as other methods of the protocol using the -P
switch:
-PE
: echo request-PP
: timestamp query-PM
: address map query
If a host replies, it’s online. I scanned my network using the --disable-arp-ping
flag to tell nmap
only to do ping scanning:
$ sudo nmap -sn -PE --disable-arp-ping 192.168.186.0/24
Starting Nmap 7.93 ( https://nmap.org ) at 2023-03-20 14:43 PDT
Nmap scan report for 192.168.186.2
Host is up (0.0023s latency).
MAC Address: 00:50:56:FC:7E:8B (VMware)
Nmap scan report for 192.168.186.71
Host is up (0.0011s latency).
MAC Address: 00:0C:29:91:6A:82 (VMware)
Nmap scan report for 192.168.186.72
Host is up (0.0031s latency).
MAC Address: 00:0C:29:19:6C:BF (VMware)
Nmap scan report for 192.168.186.73
Host is up (0.0012s latency).
MAC Address: 00:0C:29:39:19:E4 (VMware)
Nmap scan report for 192.168.186.74
Host is up (0.0019s latency).
MAC Address: 00:0C:29:01:40:16 (VMware)
Nmap scan report for 192.168.186.93
Host is up.
Nmap done: 256 IP addresses (6 hosts up) scanned in 4.86 seconds
In this example I chose to use ICMP Echo requests to scan the network. As expected, this scan took a little longer than the ARP scan we did in the last example. Remember to consider network contexts when performing scans. Since, I’m on a local network, it’s preferable to use an ARP scan to get results faster and more reliably.
That being said, it’s important to try different protocols as systems are configured to respond differently:
$ sudo nmap -sn -PP --disable-arp-ping 192.168.186.0/24
Starting Nmap 7.93 ( https://nmap.org ) at 2023-03-20 14:42 PDT
Nmap scan report for 192.168.186.71
Host is up (0.0038s latency).
MAC Address: 00:0C:29:91:6A:82 (VMware)
Nmap scan report for 192.168.186.72
Host is up (0.0015s latency).
MAC Address: 00:0C:29:19:6C:BF (VMware)
Nmap scan report for 192.168.186.73
Host is up (0.0012s latency).
MAC Address: 00:0C:29:39:19:E4 (VMware)
Nmap scan report for 192.168.186.74
Host is up (0.0016s latency).
MAC Address: 00:0C:29:01:40:16 (VMware)
Nmap scan report for 192.168.186.93
Host is up.
Nmap done: 256 IP addresses (5 hosts up) scanned in 9.63 seconds
In this example I told nmap
to do a timestamp query scan and it took considerably longer. My VMware gateway was also configured not to respond to timestamp queries, so it did not show up in the results.
Always mix and match protocol types. Some systems might be online but are configured not to respond to echo requests. So, you might find something that was missed in a previous scan by running nmap
with different options.
TCP/UDP/SCTP Scanning
We’re taking another step higher in the protocol stack using TCP/UDP/SCTP scanning. In this type of scan, we’re using these protocols to probe a single port. While this scan has the highest level of overhead (and will be slower) it an advantage of being able to scan a host over the internet.
As with the previous scans, we’re going to again use the -P
option:
-PY
: SCTP INIT-PS
: TCP SYN-PA
: TCP ACK-PU
: UDP
Let’s try a SYN ping scan:
$ sudo nmap -sn --disable-arp-ping -PS 192.168.186.0/24
Starting Nmap 7.93 ( https://nmap.org ) at 2023-03-20 15:04 PDT
Nmap scan report for 192.168.186.2
Host is up (0.0020s latency).
MAC Address: 00:50:56:FC:7E:8B (VMware)
Nmap scan report for 192.168.186.71
Host is up (0.0012s latency).
MAC Address: 00:0C:29:91:6A:82 (VMware)
Nmap scan report for 192.168.186.72
Host is up (0.0060s latency).
MAC Address: 00:0C:29:19:6C:BF (VMware)
Nmap scan report for 192.168.186.74
Host is up (0.0018s latency).
MAC Address: 00:0C:29:01:40:16 (VMware)
Nmap scan report for 192.168.186.93
Host is up.
Nmap done: 256 IP addresses (5 hosts up) scanned in 4.88 seconds
nmap
chooses ports to probe by default but you can specify them by putting a number or range next to the scan type:
$ sudo nmap -sn --disable-arp-ping -PU53 192.168.186.0/24
Starting Nmap 7.93 ( https://nmap.org ) at 2023-03-20 15:06 PDT
Nmap scan report for 192.168.186.72
Host is up (0.0018s latency).
MAC Address: 00:0C:29:19:6C:BF (VMware)
Nmap scan report for 192.168.186.74
Host is up (0.0017s latency).
MAC Address: 00:0C:29:01:40:16 (VMware)
Nmap scan report for 192.168.186.93
Host is up.
Nmap done: 256 IP addresses (3 hosts up) scanned in 9.61 seconds
I chose port 53 (DNS) to perform my UDP scan because it’s super common. As you can see, I got fewer results with this and it took a lot longer. Again, it’s important to try different ports and protocols with these scans. For example, if I knew an organization had websites up and running, I might try ports 80 and 443 to see what servers they have online. If I’m scanning a business network with a lot of users, they may be using AD to manage their systems, so I might try port 389 or 636 for LDAP.
Context matters!
Port Scanning
Now that we know what hosts are up and running, we can check what services are running on these hosts. Open ports present an opportunity for access, so it’s important to know what can be potentially accessed or exploited.
We saw that nmap
scans ports by default using full TCP connections, or just by using TCP SYN packets when running as root.
To specify a scan option, we can use the -
s argument with nine different options. We’ll only go over a few but I’ll list some common scans:
-sS
: SYN Scan (default)-sT
: TCP Scan-sU
: UDP Scan- –
sY
: SCTP Scan
This sort of syntax should be familiar to you as it is very similar to the various ping scan options with -P
. I used a SYN scan to scan my metasploitable machine:
$ sudo nmap -sS ms2
Starting Nmap 7.93 ( https://nmap.org ) at 2023-03-22 21:16 PDT
Nmap scan report for ms2 (192.168.186.131)
Host is up (0.0029s latency).
Not shown: 977 closed tcp ports (reset)
PORT STATE SERVICE
21/tcp open ftp
22/tcp open ssh
23/tcp open telnet
25/tcp open smtp
53/tcp open domain
80/tcp open http
111/tcp open rpcbind
139/tcp open netbios-ssn
445/tcp open microsoft-ds
512/tcp open exec
513/tcp open login
514/tcp open shell
1099/tcp open rmiregistry
1524/tcp open ingreslock
2049/tcp open nfs
2121/tcp open ccproxy-ftp
3306/tcp open mysql
5432/tcp open postgresql
5900/tcp open vnc
6000/tcp open X11
6667/tcp open irc
8009/tcp open ajp13
8180/tcp open unknown
MAC Address: 00:0C:29:7B:A1:58 (VMware)
Nmap done: 1 IP address (1 host up) scanned in 0.38 seconds
nmap
was able to find quite a bit of open ports. I like using the SYN scan because it combines the reliability of a TCP scan without being as slow (this scan only took 0.38 seconds) because it doesn’t establish a full connection.
That being said, it’s important to try other scan types:
$ sudo nmap -sU -p 53,1000-1010 ms2
Starting Nmap 7.93 ( https://nmap.org ) at 2023-03-22 21:20 PDT
Nmap scan report for ms2 (192.168.186.131)
Host is up (0.0018s latency).
PORT STATE SERVICE
53/udp open domain
1000/udp closed ock
1001/udp open|filtered unknown
1002/udp closed unknown
1003/udp closed unknown
1004/udp closed unknown
1005/udp open|filtered unknown
1006/udp closed unknown
1007/udp closed unknown
1008/udp open|filtered ufsd
1009/udp closed unknown
1010/udp closed surf
MAC Address: 00:0C:29:7B:A1:58 (VMware)
Nmap done: 1 IP address (1 host up) scanned in 4.87 seconds
This time, I told nmap
to do a UDP scan. You’ll also notice that I specified what ports to scan using the -p
option. You can tell nmap
to scan a range, comma-separated values, ports specified by name, or every port using -p-
.
Even though I scanned only 11 ports, it took a little longer than the SYN scan. Outside of finding ports that were open and closed, nmap
claimed some ports were open|filtered
. This just mean that nmap
couldn’t tell if the port was truly open, or is protected by some sort of firewall.
Like I said when doing host discovery, it’s important to experiment with different scan methods. There are more than just the few types I listed, so feel free to check those out at nmap.org.
Output
As a penetration tester, it’s important to keep track of your scan results. Not only for you to go back over (instead of repeating scans), but for reporting purposes as well.
nmap
makes this a snap with the -o
option. There are few options that go along with -o
:
-oN
: normal output-oX
: XML output-oG
: grepable output-oA
: output in all formats
I usually stick with outputting my scan results in every format because they’re all useful in their own ways. I like normal output for reading over myself. Grepable output is great because it puts each host on a single line which makes it easier to grep
by host (hence the name). Finally, XML output is extremely useful for web-based visualization tools or storing the results in a database. For example, I love feeding my XML scan results to metasploit
, which makes it really easy to organize and search through my results.
Conclusion
If you made it this far, you can now add an invaluable tool to your hacking arsenal. This was a lengthy post so give your self a huge pat on the back for reading it all. Your learning is not over yet, though. To really make this stick, download nmap
and play around on your own network. It’s fun and is a great way to make sure you retain what you learned. Otherwise (in my own experience) the knowledge won’t stick!