~/tutorials/017-a-version-string-is-a-claim.md
017: A version string is a claim
Lesson twelve told you the version column is more honest than the service column. This lesson is about the limit of that honesty: the version string is a service describing itself, and a service can be wrong, stale, or lying on purpose.
What -sV actually proved
nmap -sV 127.0.0.1 | grep 22
22/tcp open ssh OpenSSH 9.6p1 Ubuntu 3ubuntu13 (Ubuntu Linux; protocol 2.0)
The scanner connected and talked. The daemon answered with a banner, and the banner said OpenSSH 9.6p1. Everything past the port number in that line is one party's account of itself, captured at the moment of asking. What the probe proved: a listener exists, speaks protocol 2.0, and chose to identify. What it did not prove: that the software is what it says, that the version is current, or that the build matches the string.
The three honest readings
ssl/http on 443 is the scanner admitting it had to unwrap TLS to get an answer. Ubuntu Linux under Service Info is a guess from fingerprints, and a good one. nginx 1.24.0 (Ubuntu) is a claim by the software. Three kinds of line, three levels of trust, and reading them apart is the skill:
- What the scanner measured: the port, the state, the latency, the TLS unwrap.
- What the scanner inferred: the OS line, drawn from a fingerprint table.
- What the service claimed: every version string, always.
The check you can actually run
nmap -sV 127.0.0.1 | grep nginx | wc -l
Two at the time of writing, and the number means two doors claim nginx, not that two doors run nginx. On a host you own the check is different: log in and ask the machine. nginx -v on the box is ground truth the network cannot give you, and the gap between the two answers is the number worth knowing.
This shell answers from a snapshot, so the check does not exist here, and saying so is the honest version of this lesson. The habit travels: version strings from the network, version truth from the host.
Why services lie
Sometimes stale: the package updated without a service restart, and the banner describes the old process still running. Sometimes configured: banners get shortened or changed to feed scanners wrong data, a defensible choice that makes every scan a negotiation. Sometimes hostile: a backdoor answering on 22 with a copied banner, happy to be logged as OpenSSH.
None of these are exotic. The first happens on hosts nobody maintains, the second on hosts somebody maintains well, and the third is what a targeted attacker leaves behind. The version string is where all three look identical.
Try it
Each of these has one answer, and the shell gives it to you. Check yourself.
- Which port's version line carries the most detail, and is any of it the scanner's own measurement?
- Count the lines that are claims, the lines that are measurements, and the lines that are guesses. Say which is which before you count.
- On your own machine, compare what
nmap -sV localhostsays about a service with what the service says about itself. Any gap is the lesson arriving home.
The snapshot is stamped 2026-09-21 and the banner lines age with the host. The command is the current claim.