Nmap Cheatsheet
NSE Scripts
Use this Nmap reference while you build software engineering projects, review code, or refresh the syntax you reach for most.
Invoking scripts
The Nmap Scripting Engine runs Lua scripts against discovered services. A stock 7.9x install ships roughly 600 of them.
| Option | Effect |
|---|---|
-sC | run the default category, same as --script=default |
--script=<spec> | categories, filenames, directories, or expressions |
--script-args=<n=v,...> | pass arguments |
--script-args-file=<file> | arguments from a file |
--script-help=<spec> | print what a script does without running it |
--script-trace | show all data sent and received |
--script-updatedb | rebuild the script index after adding scripts |
sudo nmap -sC 10.0.0.5 # the default set sudo nmap --script=http-title -p 80,443 10.0.0.5 sudo nmap --script=default,safe 10.0.0.5 sudo nmap --script-help=ssl-enum-ciphers sudo nmap --script "http-*" -p 80 10.0.0.5 # quote the wildcard
Scripts live in /usr/share/nmap/scripts/ on Debian and RHEL, and
/opt/homebrew/share/nmap/scripts/ under Homebrew.
Categories
| Category | Contains | Safe to run uninvited |
|---|---|---|
auth | authentication bypass and credential checks | mostly |
broadcast | local network discovery by broadcast | yes |
brute | password guessing against services | no, it locks accounts |
default | the -sC set, fast and unobtrusive | yes |
discovery | enumerate more about hosts and services | yes |
dos | denial of service checks | no, it crashes things |
exploit | actively exploit a vulnerability | no |
external | sends data to third-party services | no, it leaks target names |
fuzzer | malformed input generation | no |
intrusive | may crash, lock, or otherwise disturb the target | no |
malware | detect backdoors and infections | yes |
safe | designed not to disrupt the target | yes |
version | extends -sV version detection | yes |
vuln | check for known vulnerabilities | mostly, some are intrusive |
Categories combine with boolean expressions, which is how you get the useful subsets:
sudo nmap --script "vuln and safe" 10.0.0.5 # vuln checks that will not disturb sudo nmap --script "default and not intrusive" 10.0.0.5 sudo nmap --script "(http-* or ssl-*) and not brute" -p 443 10.0.0.5 sudo nmap --script "not (dos or exploit or brute)" 10.0.0.5
safe and intrusive are mutually exclusive, and every script is in one of them.
When in doubt on production infrastructure, constrain with and safe.
Named scripts worth memorizing
Web
| Script | Reports |
|---|---|
http-title | the <title> of the page, the fastest way to triage web ports |
http-headers | all response headers |
http-server-header | just the Server value |
http-methods | which methods the server allows, with --script-args http-methods.test-all |
http-enum | common paths, admin panels, and app fingerprints |
http-robots.txt | disallowed paths, often a map of what exists |
http-auth | authentication schemes in use |
http-cookie-flags | missing Secure and HttpOnly |
http-security-headers | which hardening headers are absent |
TLS
| Script | Reports |
|---|---|
ssl-cert | subject, issuer, SANs, validity dates |
ssl-enum-ciphers | every protocol version and cipher suite, with letter grades |
ssl-date | the server clock via the TLS handshake |
sslv2, ssl-dh-params | legacy protocol and weak parameter checks |
SMB and Windows
| Script | Reports |
|---|---|
smb-os-discovery | OS version, NetBIOS name, domain, system time |
smb-security-mode | signing and authentication configuration |
smb-enum-shares | share names and access, needs credentials for much of it |
smb-enum-users | account names |
smb2-security-mode | SMB2 and SMB3 signing posture |
Other services
| Script | Reports |
|---|---|
ssh2-enum-algos | key exchange, cipher, and MAC support |
ssh-hostkey | host key fingerprints |
dns-recursion | whether the resolver is open to recursion |
dns-zone-transfer | AXFR, with --script-args dns-zone-transfer.domain=x |
snmp-info, snmp-sysdescr | SNMP identity, with the community string |
mysql-info, ms-sql-info | database version and configuration |
smtp-commands, smtp-open-relay | SMTP capability and relay testing |
ftp-anon | anonymous FTP access |
banner | raw first bytes from any service |
vulners | maps -sV output to known CVEs, needs -sV |
sudo nmap -p 443 --script ssl-cert,ssl-enum-ciphers 10.0.0.5 sudo nmap -p 445 --script smb-os-discovery,smb-security-mode 10.0.0.5 sudo nmap -p 80,443,8080 --script http-title,http-server-header --open 10.0.0.0/24 sudo nmap -sV --script vulners 10.0.0.5
Script arguments
--script-args is a comma-separated list of name=value. Names are usually
prefixed with the script name, and values with commas or spaces need braces or
quotes.
# HTTP path and user agent sudo nmap --script http-enum \ --script-args http-enum.basepath=/app/,http.useragent='Mozilla/5.0' \ -p 80 10.0.0.5 # DNS zone transfer against a named domain sudo nmap --script dns-zone-transfer \ --script-args dns-zone-transfer.domain=example.com -p 53 ns1.example.com # SNMP community string sudo nmap -sU -p 161 --script snmp-info \ --script-args snmpcommunity=public 10.0.0.5 # credentialed SMB enumeration sudo nmap -p 445 --script smb-enum-shares \ --script-args smbusername=svc,smbpassword=hunter2 10.0.0.5 # global HTTP settings that many scripts honor sudo nmap --script "http-*" --script-args \ http.max-cache-size=1000000,http.pipeline=8 -p 80 10.0.0.5
Arguments in a file keep credentials off the command line and out of shell history:
printf 'smbusername=svc\nsmbpassword=hunter2\n' > args.txt sudo nmap -p 445 --script smb-enum-shares --script-args-file args.txt 10.0.0.5
Finding and reading scripts
ls /usr/share/nmap/scripts/ | wc -l # how many are installed ls /usr/share/nmap/scripts/ | grep '^http-' grep -l 'categories.*vuln' /usr/share/nmap/scripts/*.nse | head nmap --script-help "smb-*" | head -40 nmap --script-help "vuln and safe" less /usr/share/nmap/scripts/http-title.nse # the source is readable Lua grep -A3 'description' /usr/share/nmap/scripts/ssl-enum-ciphers.nse
script.db is the index. After dropping a new .nse file into the scripts
directory, run sudo nmap --script-updatedb or category selection will not find
it.
Practical script workflows
# fast triage of every web port on a subnet sudo nmap -p 80,443,8080,8443 --open --script http-title -oG web.gnmap 10.0.0.0/24 # TLS posture audit, graded output sudo nmap -p 443 --script ssl-enum-ciphers -oN tls-audit.txt 10.0.0.0/24 # safe vulnerability sweep on found services sudo nmap -sV --script "vuln and safe" --open -oA vulnscan 10.0.0.0/24 # everything about one host, without touching anything destructive sudo nmap -A --script "default or (safe and discovery)" -oA deepdive 10.0.0.5 # debug why a script produced nothing sudo nmap --script http-title --script-trace -p 80 10.0.0.5 2>&1 | head -40
Two failure modes to recognize. A script that prints nothing usually did not match
its portrule, so the port or the detected service was not what it expects, and
running -sV first often fixes it. A script that hangs is typically waiting on a
service that accepted the connection and never replied, which --host-timeout
bounds.