Nmap for pentesting: port scanning commands step by step
How to scan a box with nmap like in a pentest: sweep all 65535 ports, versions and NSE scripts, UDP and how to read the output, with Hack The Box examples.
Every box starts the same way: a port scan. Miss a port and you miss the way in. This guide is the workflow almost every Hack The Box writeup uses (and the one you want for the OSCP): two TCP passes and one UDP pass, always saving the output, with the exact commands and what you should see at each step.
Tip
Practise each step against an easy retired box, for example Nibbles (Linux) or Blue (Windows). Retired machines are legal to attack because they live in the Hack The Box lab, which you reach over VPN. Do not scan anything you do not own or have written permission to test.
Requirements
- Kali, Parrot or any Linux with
nmap(sudo apt install nmap). Usesudo: as root, nmap runs a SYN scan (-sS), which is faster and more reliable than a full connect scan. - A connection to the HTB VPN (
sudo openvpn lab_user.ovpn) and the box IP, which here is10.10.10.75. - One folder per box to keep the output:
mkdir -p nibbles/nmap && cd nibbles.
Step 0: is it up? Linux or Windows?
ping -c 1 10.10.10.75
64 bytes from 10.10.10.75: icmp_seq=1 ttl=63 time=38.2 ms
The TTL hints at the operating system: Linux starts at 64 and Windows at 128, and the HTB VPN takes one hop off. 63 is almost certainly Linux; 127, Windows. If ping gets no answer, that is fine: many Windows boxes block ICMP, which is why the next commands use -Pn.
Step 1: every TCP port, fast
By default nmap only checks the 1000 most common ports. On HTB the way in is often on a high port (an 8808, a 50051...), so the first scan covers all 65535:
sudo nmap -p- --min-rate 5000 -n -Pn -oA nmap/all 10.10.10.75
| Option | What it does |
|---|---|
-p- |
Every port, 1 to 65535 |
--min-rate 5000 |
At least 5000 packets per second: under a minute instead of 15 |
-n |
No DNS resolution (faster) |
-Pn |
Skip the host discovery check: scan anyway |
-oA nmap/all |
Save the output in all three formats (.nmap, .gnmap, .xml) |
Expected output on Nibbles:
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
Warning
A high --min-rate on a slow network can drop ports. If something looks missing (a website that does not show up, a domain without Kerberos on 88), repeat with --min-rate 1000 or without that option.
Step 2: versions and scripts on the open ports only
Now the slow, detailed scan, but only against the ports you found. Pull the list out of the .gnmap file instead of copying it by hand:
ports=$(grep -oP '\d+(?=/open)' nmap/all.gnmap | paste -sd,)
echo $ports # 22,80
sudo nmap -p$ports -sCV -oA nmap/services 10.10.10.75
-sV detects the service and its exact version, and -sC runs the default NSE scripts (page titles, HTTP methods, SMB null sessions, certificates...). Output (trimmed):
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.18 ((Ubuntu))
|_http-title: Site doesn't have a title (text/html).
|_http-server-header: Apache/2.4.18 (Ubuntu)
Step 3: read the output like a pentester
A scan is not a list of ports: it is a list of questions. What you should take from the output above:
- The exact OS release. The package
OpenSSH 7.2p2 Ubuntu 4ubuntu2.2only ships with Ubuntu 16.04: look it up on Google or Launchpad. Now you know whether a kernel exploit is plausible. - Every version goes into searchsploit.
searchsploit apache 2.4.18andsearchsploit openssh 7.2. The guide on how to exploit a public CVE covers it. - Domain names. If a script shows
Did not follow redirect to http://something.htb/, add it to/etc/hostsand look for subdomains (directory and vhost fuzzing). - The port combination. 53 + 88 + 389 + 445 is a domain controller (start with Active Directory enumeration); 139 + 445 without 88 is a plain Windows or Samba host (SMB and NFS enumeration).
A quick cheat sheet of what to do with each port:
| Port | Service | First thing to try |
|---|---|---|
| 21 | FTP | ftp 10.10.10.75 as anonymous with no password |
| 22 | SSH | Only with credentials or a key: keep it for later |
| 80, 443, 8080 | HTTP | Open it in the browser, read the source and start fuzzing |
| 139, 445 | SMB | nxc smb IP -u '' -p '' --shares |
| 161/udp | SNMP | snmpwalk -v2c -c public IP (SNMP enumeration) |
| 1433 | MSSQL | Default credentials and MSSQL attacks |
| 3306 | MySQL | Only with credentials, except very old versions |
| 5985 | WinRM | evil-winrm as soon as you have a user |
Step 4: UDP, the one everybody skips
UDP scanning is slow (there is no handshake and nmap has to wait for nothing to arrive), so limit the ports:
sudo nmap -sU --top-ports 20 -n -Pn -oA nmap/udp 10.10.10.75
You will see lots of open|filtered: that means "I don't know". The ones that matter show as open. The classic HTB case is 161/udp (SNMP), which can hand you processes with passwords in their arguments, as on Pandora. To confirm a specific port add -sV: sudo nmap -sU -sV -p161 10.10.10.75.
Step 5: specific NSE scripts
Beyond the -sC ones, nmap ships with more than 600 scripts in /usr/share/nmap/scripts. To find the ones for a service and see what one does:
ls /usr/share/nmap/scripts | grep smb
nmap --script-help smb-vuln-ms17-010
The classic example is Blue, a Windows 7 box vulnerable to EternalBlue:
sudo nmap -p445 --script smb-vuln-ms17-010 10.10.10.40
| smb-vuln-ms17-010:
| VULNERABLE:
| Remote Code Execution vulnerability in Microsoft SMBv1 servers (ms17-010)
| State: VULNERABLE
Other useful ones: --script vuln (every vulnerability check, noisy), http-enum (well-known paths on a website) and ssl-cert (domain names in the certificate on a 443).
All together in a script
To run the same workflow on every box without thinking, save this as scan.sh:
#!/bin/bash
# Usage: ./scan.sh 10.10.10.75
ip=$1; mkdir -p nmap
sudo nmap -p- --min-rate 5000 -n -Pn -oA nmap/all "$ip"
ports=$(grep -oP '\d+(?=/open)' nmap/all.gnmap | paste -sd,)
sudo nmap -p"$ports" -sCV -oA nmap/services "$ip"
sudo nmap -sU --top-ports 20 -n -Pn -oA nmap/udp "$ip"
While the UDP scan runs, you can already look at the website.
Common errors
Note: Host seems down: the host does not answer ping. Add-Pn.- Every port
filtered: the VPN dropped or the box has not finished booting. Ping it and scan again after a minute. tcpwrapped: the port accepts the connection and closes it straight away. Usually a service that only talks to certain IPs or needs something specific; try connecting withnc -nv IP port.- Ports another writeup sees are missing: almost always a
--min-ratethat is too high or a box that rebooted. Repeat step 1 more slowly. -sCtakes forever: you are running it against all 65535 ports. Only run it on the list from step 2.
What next
Tick each step in the recon checklist, keep the nmap cheat sheet at hand and see the Nmap tool page for more options. If you are just starting, the Zero to OSCP path takes you from this first scan to your first domain, and the list of HTB machines to prepare for the OSCP tells you where to start.