l1ackers
Not marked. Sign in and it follows you. Next: 060: nuclei, templates as opinion

~/tutorials/059-whatweb-and-the-version-game.md

059: whatweb, and the version game

Lesson 054 introduced whatweb as a testimony collector. Lesson 056 proved the testimony can lie. This lesson plays the full game: three servers, three banner postures, honest, silent, and lying, and the instrument that beats posture more often than any scanner admits, the behavior fingerprint. The version game is not about reading banners. It is about reading servers, and banners are only one of the things a server says.

What this lesson is for

The follow-on question every tester eventually asks: if banners lie, what is fingerprinting even worth. The answer is a method, not a verdict: banners are the cheap first read, behavior is the confirmation, and the two together beat either alone. This lesson receipts all three postures side by side, on the web lab page's wire, so the differences are seen rather than believed.

What the reader meets

Three servers, built from one dozen-line shape, differing only in what they say about themselves. The plain server is an honest default, Python's stock web server, announcing itself. The quiet server sends an empty banner, suppression, the hardening advice from 056 taken literally. The liar sends Apache/2.2.15 (Unix), the same lie as 056's server, on the same engine. Same machine, same hour, three postures, and whatweb reads all three at aggression level 3:

http://172.31.19.2:5003/ [200 OK] Country[RESERVED][ZZ],
  HTTPServer[BaseHTTP/0.6 Python/3.12.14], IP[172.31.19.2], Python[3.12.14]

http://172.31.19.3:5004/ [200 OK] Country[RESERVED][ZZ],
  HTTPServer, IP[172.31.19.3]

http://172.31.19.4:5005/ [200 OK] Apache[2.2.15],
  Country[RESERVED][ZZ], HTTPServer[Unix][Apache/2.2.15 (Unix)], IP[172.31.19.4]

Three answers, one instrument, and read together they are the game's whole board. The plain server is fully named, version and all, because it volunteers everything. The quiet server gets a single word, HTTPServer with no value, the fingerprinter shrugging: it knows there is a server, it knows nothing else from the banner, and the honest thing is to say so rather than guess. The liar is confidently, completely wrong, an Apache where a Python is, and whatweb's faithful reporting of the lie is 056's receipt all over again.

The middle row is the interesting one, and it is this lesson's center. Suppression worked. The banner channel is empty, and the banner reader got nothing. Now the question that defines the version game: is the quiet server actually anonymous, or did the suppression only close one of several mouths. Send one deliberately unsupported request, BREW, the teapot protocol, to the quiet server, and read its error page:

<title>Error response</title>
<h1>Error response</h1>
<p>Error code: 501</p>
<p>Message: Unsupported method ('BREW').</p>

That page is Python's stock error page, byte for byte, the same page the plain server sends, and the receipt that closes the case is a diff: the plain server's BREW response and the quiet server's BREW response are identical. The banner was silenced. The behavior was not. The server that refused to name itself answers an odd question in its native accent, and the accent names it, because error pages, header order, cookie shapes, and a dozen other behaviors are generated by the engine, not configured by the operator, and suppressing all of them is a project nobody finishes.

The instrument

The version game, played properly, is three channels read in order of cost.

The banner channel, one request, free. whatweb's default. Honest on most of the internet, because most operators never touch it, wrong on the hardened and deceptive remainder, and you cannot tell from the banner alone which world you are in. That is its entire weakness, and 056's trust card is the response.

The behavior channel, a handful of crafted requests, nearly free. Error pages are the classic confession, and one unsupported method draws one out of almost any server. Header order is another tell, servers emit headers in the order their code builds them, and Apache, nginx, and Python each have characteristic orders. Cookie shapes, redirect styles, supported methods from an OPTIONS probe, the 404 page's exact bytes: every one is engine-generated, every one survives banner surgery, and whatweb's higher aggression levels fold several of these into the same one-line answer you already read. The receipt above is the manual version, one BREW and a diff, and it cost two requests.

The capability channel, real probes, not free. When the version claim matters, and 056's card says verify what carries severity, the strongest confirmation is behavioral: does the server actually exhibit a trait the claimed version has, a known response to a known request, a known default route. This is the reproduce-the-behavior standard from 056, and it lives at the top of the cost ladder because each probe is bespoke to the claim being tested. Most fingerprinting stops before this channel. Severity calls should not.

The strategy falls out of the costs. Always read the banner, it is free. Always spend the two-request behavior check on anything whose version will matter, it is nearly free. Escalate to capability probes only for findings that will drive action in a report, because there the cost is real and so is the value. And treat the three postures as a triage signal rather than a frustration: an honest banner usually means an honest operation, a suppressed banner means someone thought about hardening, which usually means the rest of the stack was thought about too, and a lying banner means someone made a choice, and choices are worth a closer look at everything. The posture is itself intelligence, which is the game's quietest lesson.

Try it

  1. Build all three servers from the web lab page, run whatweb against each, and read the three rows until the differences are obvious on sight. Then BREW at all three and diff the error pages against each other. The liar will confess too, its error page is the same Python page wearing an Apache costume, and you will have fingerprinted through a lie with two requests.
  2. Take the quiet posture to a real target you are authorized to test, if you have one. Read the banner, get nothing, then draw the error page with one unsupported method. Most real servers will name themselves in their error page or their header order, and the moment a suppression falls to a BREW is the moment this lesson's method becomes yours.
  3. The match game. Fingerprint three different applications on your own machine, a static server, a framework dev server, anything, using behavior only, no banners, and write down your three answers. Then check the banners. Your behavior-only answers being right is the receipt that the second channel is real, and you collected it yourself.
Reveal the answer

The version game card, the whole method on one page, with this lesson's three postures as the worked column:

CHANNEL 1: BANNER        cost: one request
  read it: whatweb TARGET
  posture seen -> meaning:
    full version    honest default, most of the internet
    empty/suppress  hardened on purpose, expect hardening elsewhere
    wrong on purpose a choice was made, look closer at everything

CHANNEL 2: BEHAVIOR      cost: two requests
  curl -X BREW TARGET | diff - plain-error-page
  header order, cookie shapes, 404 bytes, OPTIONS list
  beats: suppression (receipt: quiet's banner empty, BREW page identical
  to plain's) and most lies (the liar confesses the same way)

CHANNEL 3: CAPABILITY    cost: bespoke per claim
  probe a trait the CLAIMED version must have
  use when: the finding will carry severity in a report
  056's law: reproduce the claimed behavior, not the claimed string

THE ORDER: always 1. usually 2. only when it matters, 3.

The card's quiet advantage, worth naming because no scanner menu names it: the three postures are not just obstacles, they are information. A tester who logs posture as a finding-adjacent fact, this target suppresses banners, this one lies about its server, is collecting intelligence about the operation's security maturity that no version string ever carried. The plainest sites often have the least-touched stacks, in both good and bad senses, and the quietest ones have had hands on them. The version game's deepest play is realizing the game board itself, banner, behavior, capability, posture, is a map of how much care the other side has spent, and care is the thing you were hired to measure.

What this lesson does not claim

Fingerprinting is probabilistic, and the receipts here are clean because the lab was built to be. Real servers run proxies that rewrite error pages, frameworks that catch odd methods before the engine sees them, and configurations that change every tell this lesson used, and a well-defended target can defeat all three channels, at which point the honest answer is unknown, which is itself a finding about the target's care. What the method claims is narrower: banners are cheap, behavior is nearly free, capability probes settle what matters, and reading all three in cost order beats trusting any one, every time, on every target, including the ones that beat you. The game never ends in a final answer. It ends in a calibrated confidence, written down, with the receipts that earned it.

Not marked. Sign in and it follows you. Next: 060: nuclei, templates as opinion
l1ackers · shell this is a way in, not a requirement
$