Nmap
nmap (nmap book, GitHub 8.7k ⭐) is the most popular tool to scan hosts and map a network. This includes
- 🔎 Detecting open ports (+may find the running protocol and version)
- 📻 Guessing the host operating system
- 💥 Exploiting vulnerabilities in some protocols
- ...
➡️ There is a graphical version called ZenMap.
According to nmap, a port can be
open
: can be reachedfiltered
: no response, usually meaning there is a firewallunfiltered
: nmap can't determine if the port is open, or filteredclosed
: cannot be reached
Once you found a port, refer to the protocols section to find more about each protocols and its vulnerabilities.
Pentesting Overview
The most common usage in CTF is to run an initial -sS
(faster) scan:
$ sudo nmap -sS IP # top TCP ports
$ sudo nmap -sU IP --top-ports=20 -vv # top UDP ports
Then, while working on the ports we found, we may run:
$ sudo nmap -sS IP -p- # all TCP ports
$ sudo nmap -sU IP -p- # all UDP ports (rare)
$ sudo nmap -sS -sU IP -p- # all ports (very rare)
$ sudo nmap -sSU IP -p- # same (very rare)
However, this doesn't often work. NMap uses an ICMP Scan to check if the host is up, which is blocked by multiple hosts such as Windows.
$ sudo nmap [...] -Pn # assume host is up, don't ping
On practice, during CTFs, we want to be fast, so we use these two:
$ sudo nmap -Pn -sU -p- --min-rate 10000 IP -v
$ sudo nmap -Pn -sT -p- -min-rate 5000 IP -v
A few common options:
-n
: we often don't need DNS resolution-p
: don't scan all ports twice, use-p
to specify which one you want nmap to further analyze-sV
: try to dig service names and versions-sC
: run default scripts to find some vulnerabilities-sCV -A
: mainly in CTFs for maximum information-oA
: store results
As the port may be protected by a firewall, we may add stealth options and use firewall detection or bypass techniques.
⚠️ NMap uses banner grabbing or signature-based matching to identify the running services. It also good to cross-check as nmap may not have presented to us all information returned by a service.
⚠️ It also worth noting that nmap uses a timeout, which may cause low latency ports to not be shown in scan results.
🔫 CTF notes, delayed banners may take 30 seconds before popping.
Basic usage 🚸
nmap is quite complex. First, provide some hosts. We can use scanme.nmap.org
for testing purposes.
$ nmap scanme.nmap.org
Scan type
nmap has many types of scans. Each type is a flag starting with s
such as -sT
or -sS
.
$ nmap -sT [...] # no root required for sT
$ sudo nmap -sS [...] # root required for sS
Verbosity
As scans are usually slow, we usually increase the verbosity to know what's happening. You can use -v
, -vv
, -d
, and -dd
.
$ nmap -vv [...]
📌 You can press Enter during a scan in progress to prompt the progression of the scan.
Host probing
⚠️ nmap will try to see if a host is up before scanning it. Many hosts, including Windows hosts, do not reply to ICMP requests, so the scan will fail. In such case, you should skip this check:
$ nmap -Pn [...]
➡️ An ARP request is used if the target in on the same network.
Store results
To avoid losing the result, especially as it takes time, and we may work a lot on it, you should store it.
$ nmap [...] > output_file_name # 🤔
$ nmap [...] -oA output_file_name # all formats
$ nmap [...] -oN output_file_name # .nmap
$ nmap [...] -oG output_file_name # grep-able
$ nmap [...] -oX output_file_name # xml
Port range
We often only limit the scan to some ports. By default, the top 1000 most common ports are randomly tested.
$ nmap [...] -F # Fast, only top 100
$ nmap [...] -p 22 # only port 22
$ nmap [...] -p 22,23 # both 22, and 23
$ nmap [...] -p 0-65535 # from x to y
$ nmap [...] -p- # same as 0-65535
$ nmap [...] -p22-25,80,443 # mix
$ nmap [...] -top-ports 20 # top 20
$ nmap [...] --top-ports=20 # top 20
$ nmap [...] -p T:21 # TCP port 21
$ nmap [...] -p U:53 # UDP port 53
➡️ Use -r
to sequentially test ports.
Scan types 🤯
There are many types of scans, and we will usually use the most appropriate given the target host network architecture (firewall...), and what action we want to perform (detect TCP ports...).
TCP scans
Used for ports using the TCP protocol.
-
TCP Scan |
-sT
. Default scan if not root. Usually blocked by firewalls. Send an SYN packet, and receive RST (closed), or SYN/ACK (open). If the latter, answer back with ACK (3-ways handshake). -
TCP Syn (Half-open/Stealth) Scan |
-sS
|Need root privileges
. Default scan as root. Same as a TCP scan, but close the connection with 'RST,ACK'. Sightly faster than-sT
.
TCP scans - firewall bypass
The 3 scans below are used to bypass (old/weak) firewalls. They check if a port is closed
, so we don't know if the port is open
. Most modern or Windows OS are answering closed
to any malformed packet.
-
TCP NULL scans |
-sN
|Need root privileges
. Send a malformed packet with no flags. If the port is closed, an RST packet is received. -
TCP FIN scans |
-sF
|Need root privileges
. Send a malformed packet with an invalid flag (FIN). If the port is closed, an RST packet is received. -
TCP Xmas scans |
-sX
|Need root privileges
. Send an unexpected packet with FIN+PSH+URG flags. If the port is closed, an RST packet is received. -
Maimon scan |
-sM
|Need root privileges
. Send an unexpected packet with FIN+ACK flags. If the port is closed, an RST packet is received. It's not quite used because it's often blocked.
UDP Scans
Used for ports using the UDP protocol.
- UDP Scan |
-sU
|Need root privileges
. The scan is slow as UDP ports may only respond if they are closed (with a PING/ICMP). We don't know if the port is actually open or filtered.
ICMP Scans
- Ping Scan |
-sn
. Do not scan ports. Check if a host is up and replying to pings. Uses ARP if run as root, and the target is on the same network.
Firewall Detection Scans
We may want to find if a port is protected by a firewall, by checking who answered. Note that it doesn't mean that the port is open.
-
ACK scan |
-sA
. Send a packet with ACK, any port will reply with RST. The response is analyzed to find who answered. -
Window scan |
-sW
. Same as ACK, but analyze the window field to identify who answered. On some systems, it may even help in determining if the port is open, or not.
Custom Scan
You can create custom scans with --scanflags
# RST SYN FIN enabled
$ sudo nmap [...] --scanflags RSTSYNFIN
Host specification 🎯
Nmap can scan one or more hosts
$ nmap 192.168.0.0
$ nmap 192.168.0.* # from 0 to 254
$ nmap 192.168.0.0-254 # same
$ nmap 192.168.0.0/24 # same
$ nmap scanme.nmap.org # a domain name
$ nmap -iL hosts.txt # file
$ nmap xxx yyy zzz # list
You can exclude a machine from a scan
$ nmap [...] --exclude x.x.x.x
If you don't want nmap
to fetch DNS records, use -n
. You can use -R
to force nmap
to query DNS servers.
$ nmap -n x.x.x.x [...]
# won't look for the domain associated with this IP
You can use -sL
to list every host that will be scanned.
$ nmap -sL -n 192.168.0/29 [...]
# Nmap scan report for 192.168.0.0
# [...]
# Nmap scan report for 192.168.0.7
# Nmap done: 8 IP addresses (0 hosts up)
👉 This may be useful to know how many hosts will be scanned.
Target host information 🎣
nmap can try to guess the protocols and service running on a port, along with its version. If a service has been secured, then it may not leak much information (i.g. the version may be hidden...).
- Service and versions: guess the service and version used by an open port (ex: 80 $\to$ Apache x.xx.xx).
$ nmap -sV [...]
👉 It may also include the hostname, the OS, and the CPE.
👉 You may set the intensity with --version-intensity level
(from 0 to 9). There are shortcuts --version-light
(2), and --version-all
(9).
- Operating system: try to guess the OS. Sometimes
-sV
or others may be more reliable.
$ nmap -O [...]
- Default scripts: run default scripts to find vulnerabilities, find the hostname/computer name and other information...
$ nmap -sC [...]
- All/Aggressive: operating system, script, services, and traceroute
$ nmap -A [...]
Stealth 🐈
nmap can send more or less stealthy by adding a timing between requests. It ranges from 0 to 5, while 0 means one request per 5 minutes (paranoid (0), sneaky (1), polite (2), normal (3), aggressive (4), and insane (5)). 3
is the default, 0
/1
are usually used for stealth, 4
is used in CTFs, and 5
can be inaccurate as many packets may be lost.
$ nmap [...] -T4
Fragmentation
You can fragment packets which may be used to bypass firewalls
$ nmap -f # create packets of 8 bytes or less
$ nmap -ff # create packets of 16 bytes or less
$ nmap --mtu xxx # maximum transfer unit (multiple of 8)
$ nmap --data-length length # split by length
IP spoofing
Spoof the requester IP. It's useless if you can't get the response.
$ nmap [...] -S IP -e tun0 # IP must be up
Explicit DNS
You can explicitly specify the DNS server, such as an internal DNS server of a company, using:
$ nmap [...] --dns-server ns
$ nmap [...] --dns-server ns1,ns2
Custom Source Port
We can use a custom source ports, which may bypass some misconfigured systems:
$ sudo nmap [...] -g 53
$ sudo nmap [...] --source-port 53
# use "nc --source-port 53 [...]"
MAC spoofing
Spoof the requester MAC. It's useless if you can't get the response. Also, it may be useless if you don't use a MAC address that is on the same network that the target.
$ nmap [...] --spoof-mac SPOOFED_MAC
Decoys
Simulate that multiple IP are making the request, to hide yours in the list of provided IPs.
$ nmap [...] -D XXX,YYY,YOUR_IP
$ nmap [...] -D RND:5 # random IPs, beware of SYN-flooding
# generated IPs must be up, your IP is randomly mixed in
️🧟️ Zombies/Idle host -sI
🧟
An idle host is not making any requests, such as a printer.
We can exploit them to perform requests for us. Every packet has an ID that is usually incrementing by one at every request. We will query the zombie once to know the starting number, spoof a request using the zombie IP, then query again the packet ID, and we will know if the target replied to them, or not according to the new value.
Other options 🥾
Select a network interface
$ nmap [...] -e NETWORK_INTERFACE
Ask for the reason
You can ask nmap to give the reason why a port is identified as "xxx". This will add a column "REASON" in the result, which is usually present by default (at least on Kali).
$ nmap [...] --reason
Traceroute
You can ask nmap to do a traceroute, much like with traceroute
.
$ nmap [...] --traceroute
$ nmap [...] --packet-trace # sort of log of every request
Performance
--min-RTT-timeout
,--initial-rtt-timeout
,--max-rtt-timeout
: timeout, can be shorter, but will impact results--max-retries
: can be reduced, but will impact results--min-rate
/--max-rate
: how many simultaneously packets--min-parallelism
/--max-parallelism
: frequency
Nmap Scripting Engine (NSE) 📌
When using flags such as -sV
or -sC
, you are actually using nmap scripts. They are categorized in 6 categories as follows:
safe
: won't harm the targetintrusive
: will harm the targetvuln
: scan for vulnerabilitiesexploit
: try to exploit a vulnerabilitybrute
: attempt to brute forcediscovery
: try to discover more about the network.
You can execute every script of a category
$ nmap [...] --script=vuln
$ nmap [...] --script vuln # same
🔥 I had to disable some functionalities of my antivirus, otherwise some/most NSE scripts would fail.
To find a script
- Use NSEDoc, for instance "smb" NSE scripts
- Or, use commands,
ls -l /usr/share/nmap/scripts/*smb*
- Note that there are also CVEs!
You can run a specific script that you selected
$ nmap [...] --script=lua_script
# run two scripts, set argument "key" of "s1" to "value"
$ nmap [...] --script=s1,s2 --script-args s1.key=value
You can also use patterns to select scripts, but you may inadvertently use scripts that you were not supposed to.
$ nmap [...] --script "ftp*"
Common scripts
Brute force scripts
Refer to nmap list of brute force scripts. nmap will do the cartesian product of the list of usernames by the list of passwords.
$ nmap IP -p 22 --script ssh-brute --script-args userdb=users.lst,passdb=pass.lst
$ nmap IP --script "*brute*" --script-args userdb=users.lst,passdb=pass.lst
Uncommon usages
Banner grabbing
See also: banner grabbing.
$ nmap [...] --script=banner
$ nmap [...] --script=http-server-header.nse
Forced browsing
$ nmap [...] --script=http-enum
👻 To-do 👻
Stuff that I found, but never read/used yet.
- nmapAutomator, nmap-vulners, zgrab2
nmap --log-errors
nmap --badsum
: if answer, should be from a firewall/IDS--script-trace
,--open
- map the company network
nmap range -sn
--stats-every=5s
instead of space- sacrifice one VPS to test the firewall limits. Each time you are caught, move to another VPS and be quieter.
$ sudo nmap --script-updatedb
Host probing
-PE
: ICMP echo requests (default if root)-PP
: ICMP timestamp requests-PM
: ICMP type 17/18 packets-PS
: TCP SYN packet to port 80-PA
: TCP ACK packet to port 80-PU
: UDP packet to a random port--disable-arp-ping
: disable ARP