2.3 Service Enumeration & Operating System Detection
Key Takeaways
Service version detection (
-sV) queries open ports with probe strings fromnmap-service-probesand matches responses against compiled regular expressions to determine software names and version numbers.Operating system fingerprinting (
-O) analyzes TCP/IP stack implementation nuances, including initial Time-to-Live (TTL) values (Linux ~64, Windows ~128, Cisco ~255), TCP window sizes, and flag responses.Manual banner grabbing with
nc -nvortelnetprovides rapid, direct verification of service software headers without relying on automated probing.The Nmap Scripting Engine (NSE) automates deep service enumeration, authentication auditing, and vulnerability discovery using specialized Lua scripts organized into categories like
default(-sC),vuln, andsafe.A standard penetration testing initial scan combines flags (
nmap -sC -sV -p- -T4 -oA target_scan <target>) to maximize discovery while preserving structured artifacts.
Service Version Detection Mechanics (-sV)
Discovering that a TCP or UDP port is open provides only the initial step of vulnerability analysis. In enterprise networks and penetration testing environments, network services frequently run on non-standard ports (such as SSH running on port 2222 or HTTP running on port 8080). Conversely, standard ports may host custom or outdated daemons. To locate exploitable vulnerabilities and CVEs, a penetration tester must determine the exact service daemon and software version operating on each open port.
How Nmap Performs Service Detection (-sV)
When invoked with the -sV flag, Nmap executes a multi-step probing sequence:
- Initial Connection (NULL Probe): Nmap establishes a TCP connection to the open port and listens silently for a specified timeout period. Many common daemons (including SSH, FTP, SMTP, and Telnet) automatically transmit an initial greeting banner upon connection establishment without waiting for client input.
- Probe Progression via
nmap-service-probes: If the service does not emit a greeting banner, Nmap consults its service probe database (/usr/share/nmap/nmap-service-probes). It transmits a sequence of standardized protocol challenge strings (such as HTTPGETrequests, SSL/TLS Client Hellos, SMB negotiation requests, and RPC probes). - Signature Pattern Matching: When the service returns data, Nmap evaluates the response against a vast library of compiled regular expressions. These expressions extract:
- Product Name (e.g.,
Apache httpd,OpenSSH,vsftpd) - Version Number (e.g.,
2.4.41,8.2p1,2.3.4) - Operating System Platform (e.g.,
Ubuntu Linux,Windows) - Hostname and Device Type (e.g.,
printer,embedded router)
- Product Name (e.g.,
Controlling Probe Intensity (--version-intensity)
Nmap categorizes each probe in nmap-service-probes with a rarity intensity rating ranging from 0 (very common) to 9 (rare). By default, Nmap operates at intensity level 7:
--version-intensity <0-9>: Sets the probe depth. Higher values test more probes but increase scan duration.--version-light: Shortcut for intensity level2. Fast scan that tests only high-probability probes.--version-all: Shortcut for intensity level9. Tests every single probe against every open port, essential when identifying obscure services bound to non-standard high ports.
# Scan designated ports with comprehensive version detection
nmap -sV --version-all -p 80,443,8080,8443 target_ip
Manual Banner Grabbing Techniques
While automated version detection is powerful, manual banner grabbing remains an essential skill for junior penetration testers. Automated tools can produce inaccurate deductions or trigger defenses, whereas manual socket interaction provides raw, ground-truth verification of service responses.
Banner Grabbing with Netcat (nc)
Netcat (nc) is the premier utility for reading and writing raw data across TCP and UDP network connections:
# Banner grab FTP (TCP 21)
nc -nv 10.10.10.20 21
# Expected Output: 220 (vsFTPd 3.0.3)
# Banner grab SSH (TCP 22)
nc -nv 10.10.10.20 22
# Expected Output: SSH-2.0-OpenSSH_7.9p1 Debian-10+deb10u2
# Banner grab SMTP (TCP 25)
nc -nv 10.10.10.20 25
# Expected Output: 220 mail.inlanefreight.local ESMTP Postfix (Ubuntu)
Banner Grabbing Web Services with curl
For HTTP and HTTPS web servers, raw socket probes can be tedious due to HTTP request formatting requirements. The curl command retrieves HTTP response headers cleanly:
# Fetch only HTTP headers using curl
curl -I http://10.10.10.20
# Inspect response headers on secure web endpoints
curl -k -I https://10.10.10.20
The returned Server: header (e.g., Server: Apache/2.4.29 (Ubuntu)) and X-Powered-By: header (e.g., X-Powered-By: PHP/7.2.24) provide direct insight into the server stack.
Warning
Service banners can be forged or intentionally sanitized by security-conscious system administrators (e.g., setting ServerTokens Prod in Apache or using banner-masking modules). Always correlate banner data with underlying OS stack behavior and secondary enumeration artifacts.
Operating System Fingerprinting Mechanics (-O)
Determining the remote host's operating system is crucial for selecting compatible exploit payloads (such as differentiating between Windows x64 and Linux x86_64 architecture). Nmap implements active TCP/IP stack fingerprinting (-O), which evaluates how a target's networking stack handles subtle protocol edge cases.
TCP/IP Stack Fingerprinting Principles
While RFC standards govern TCP/IP networking, operating system vendors implement these standards with subtle internal variances. Nmap transmits a sequence of up to 16 distinct probe packets (including TCP SYN packets to open ports with varied TCP options, TCP packets with invalid flag combinations like SYN+FIN, TCP packets to closed ports, and ICMP Echo requests).
Nmap inspects the returned responses against its nmap-os-db signature database, analyzing key parameters:
- Time-to-Live (TTL): The initial TTL header value set by the sender operating system before packet transmission.
- TCP Window Size: The initial receive window buffer negotiated during the handshake.
- Don't Fragment (DF) Bit: Whether the operating system enforces IP path MTU discovery.
- TCP Options Ordering: The precise sequence and formatting of TCP options (such as MSS, Window Scale, SACK Permitted, and Timestamps).
- Response to Invalid Flags: How the stack responds to non-standard flag permutations (e.g., Linux returns RST/ACK to a SYN+FIN probe, while older Windows stacks ignore it or behave differently).
Analyzing Default TTL Values
Penetration testers can quickly infer a target operating system family simply by observing the TTL (Time-to-Live) value in received packets (via ping or tcpdump):
| Operating System Family | Initial Default TTL | Observed TTL (Local Subnet) | Observed TTL (2 Hops Away) |
|---|---|---|---|
| Linux / Unix / Android / macOS | 64 | 64 | 62 (64 - 2) |
| Microsoft Windows | 128 | 128 | 126 (128 - 2) |
| Cisco IOS / Network Appliances | 255 | 255 | 253 (255 - 2) |
| Solaris / AIX | 255 | 255 | 253 (255 - 2) |
Because routers decrement the IP TTL header by 1 at each hop, a tester observing an inbound ICMP Echo Reply with ttl=63 can immediately deduce that the host is a Linux/Unix system operating one routing hop away (64 - 1 = 63).
The Nmap Scripting Engine (NSE)
The Nmap Scripting Engine (NSE) is an extensible subsystem powered by an embedded Lua interpreter. Located on Linux systems in /usr/share/nmap/scripts/, NSE enables penetration testers to automate advanced service discovery, vulnerability detection, and credential auditing.
NSE Script Categories
Every NSE script belongs to one or more predefined categories:
default: Thoroughly tested, fast, reliable, and safe scripts executed automatically when the-sCflag is invoked.vuln: Checks target services for specific known vulnerabilities, misconfigurations, and CVEs (e.g., checking for EternalBlue MS17-010 or Shellshock).safe: Scripts that are non-intrusive and highly unlikely to crash target services, exhaust memory, or consume excessive bandwidth.discovery: Queries public directories, SNMP trees, SMB shares, and DNS services to extract rich environmental metadata.auth: Tests authentication credentials, audits default administrative passwords, and detects anonymous login access.exploit: Actively attempts to deliver a functional exploit payload against the target service (use with extreme caution).intrusive: Scripts that carry a significant risk of crashing target services or generating high network noise that triggers IDS alerts.
Executing NSE Scripts
# Run default scripts against open ports (equivalent to --script=default)
nmap -sC target_ip
# Run all scripts within the 'safe' and 'discovery' categories
nmap --script "safe and discovery" target_ip
# Target specific services with dedicated scripts
nmap --script smb-os-discovery,smb-enum-shares -p 445 target_ip
nmap --script ftp-anon,ftp-syst -p 21 target_ip
nmap --script http-enum,http-title -p 80,443 target_ip
# Execute a script with custom arguments using --script-args
nmap --script smb-enum-shares --script-args smbuser=guest,smbpass="" -p 445 target_ip
# Display documentation and arguments for a specific script
nmap --script-help smb-os-discovery
Assembling Effective Scan Strategies
In hands-on penetration testing examinations such as the eJPT, running an overly aggressive or unoptimized scan can exhaust lab bandwidth, cause target services to hang, or waste valuable examination time. Professional penetration testers utilize a disciplined, two-stage scanning methodology:
Stage 1: Rapid Full-Port Discovery
Quickly sweep all 65,535 TCP ports at an elevated rate to discover every active listening port without the overhead of service versioning or script execution:
nmap -p- --min-rate 1000 -T4 -Pn -oN ports_quick.nmap target_ip
Stage 2: Deep Targeted Enumeration
Extract the discovered open ports and target only those active ports with service version detection (-sV), operating system fingerprinting (-O), default NSE scripts (-sC), and full output logging (-oA):
# Example targeting discovered ports 21, 22, 80, and 445
nmap -sC -sV -O -p 21,22,80,445 -T4 -oA target_deep_scan target_ip
For smaller standalone lab hosts where time permits, combining flags into a single comprehensive command provides complete initial intelligence:
nmap -sC -sV -p- -T4 -Pn -oA target_comprehensive target_ip
Common Network Services & Enumeration Cheat Sheet
| Service Daemon | Default Ports | Transport | Typical Service Banner | Primary Manual Enumeration | Primary Nmap NSE Script |
|---|---|---|---|---|---|
| FTP | 21 | TCP | 220 (vsFTPd 3.0.3) | nc -nv <ip> 21 | --script ftp-anon,ftp-syst |
| SSH | 22 | TCP | SSH-2.0-OpenSSH_8.2p1 | nc -nv <ip> 22 | --script ssh2-enum-algos |
| Telnet | 23 | TCP | Welcome to Linux | telnet <ip> 23 | --script telnet-encryption |
| SMTP | 25, 587 | TCP | 220 mail.domain.com ESMTP | nc -nv <ip> 25 | --script smtp-commands,smtp-enum-users |
| DNS | 53 | UDP / TCP | BIND version string | dig @<ip> version.bind txt chaos | --script dns-zone-transfer,dns-recursion |
| HTTP / HTTPS | 80, 443 | TCP | Server: Apache/2.4.41 | curl -I http://<ip> | --script http-enum,http-title |
| SMB / NetBIOS | 139, 445 | TCP | Windows / Samba version | enum4linux -a <ip> | --script smb-os-discovery,smb-enum-shares |
| SNMP | 161 | UDP | MIB sysDescr string | snmpwalk -v2c -c public <ip> | --script snmp-info,snmp-sysdescr |
| MySQL | 3306 | TCP | 5.7.33-0ubuntu0.18.04.1 | nc -nv <ip> 3306 | --script mysql-info,mysql-enum |
| RDP | 3389 | TCP | CredSSP / TLS Cert | rdesktop <ip> | --script rdp-enum-encryption |
An analyst intercepts an unsolicited ICMP Echo Reply or TCP SYN/ACK packet from a target host on the same local subnet with a Time-to-Live (TTL) header value of 64. What operating system family is the host most likely running?
Linux or Unix-like operating system
Microsoft Windows Server
Cisco IOS Enterprise Router
Solaris SPARC mainframe
Which Nmap Scripting Engine (NSE) flag executes all scripts categorized under the default collection without running intrusive or potentially crash-inducing exploit scripts?
-O --fuzzy
-sC
--script=exploit
--version-all
How does Nmap's service version detection (-sV) determine the software version running on an open TCP port when the daemon does not transmit an initial greeting banner?
It resets the host's operating system stack by transmitting an invalid TCP FIN packet
It brute-forces administrative credentials using the Lua embedded script engine
It references the local /etc/services port translation file to assume standard protocol versions
It sequentially transmits probe strings from nmap-service-probes and matches replies against regular expressions
Sections you finish are checked off in the contents.