Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Identify the server software, framework, and component versions a target is running from its HTTP response signatures — Server header, X-Powered-By, Via, X-AspNet-Version, X-Runtime, X-Drupal-Cache, X-Generator, Set-Cookie name patterns, error-page artwork, HTTP method behavior signatures. Use when: penetration test reconnaissance phase, post-deploy audit of fingerprintable exposure, or before reporting "no obvious version disclosure" to an auditor. Threshold: any version string in a response he
.claude/skills/jeremylongshore-fingerprinting-server-software/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-07 | ✗→✓ | ▲ Improved | 34% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 49% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 73% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 83% | 0% |
| case-12 | ✗→✓ | ▲ Improved | 23% | 0% |
Version disclosure is the cheapest recon an attacker buys. A single GET request returns the Server: header, the X-Powered-By: header, and any framework-default cookies. From those three signals the attacker derives: web server family + exact version, app-framework + version, language runtime + version. That maps directly to a CVE catalog query: every published CVE affecting any of those components, filtered to ones an unauthenticated attacker can trigger.
The fix is operationally trivial (one line in nginx, one line in Apache, one line in IIS) but the discipline isn't universal. This skill enumerates the signals + reports each disclosure with the severity matching how much it enables follow-on attack.
| Finding | Severity | Threshold | Affected control | |---|---|---|---| | Server header discloses version | MEDIUM | Server: nginx/1.18.0 or similar with explicit version | CWE-200 | | Server header discloses minor version | LOW | Server: nginx (no version) | CWE-200 | | X-Powered-By discloses framework version | MEDIUM | X-Powered-By: PHP/7.4.21, Express, ASP.NET | CWE-200 | | X-AspNet-Version present | HIGH | Specific dotnet runtime version | CWE-200 | | X-Runtime / X-Rails / X-Django headers present | LOW | Framework identification, no version | CWE-200 | | X-Generator: drupal/wordpress + version | MEDIUM | CMS family + version disclosure | CWE-200 | | Via header discloses proxy chain | LOW | Reveals upstream architecture (Varnish, Squid, CloudFront) | CWE-200 | | Framework-default Set-Cookie pattern | LOW | PHPSESSID, JSESSIONID, connect.sid, etc. | CWE-200 | | Error page reveals stack trace | HIGH | 5xx response body contains source file paths or framework banner | CWE-209 | | HTTP/2 server-push fingerprint | LOW | HTTP/2 :server pseudo-header with version | CWE-200 | | ETag format identifies cluster member | LOW | Apache-style hex ETags reveal node | CWE-200 |
requeststext"Do you have authorization to perform server-fingerprinting probes on this target? I need confirmation before proceeding."
bashpython3 ${CLAUDE_PLUGIN_ROOT}/skills/fingerprinting-server-software/scripts/fingerprint_server.py \ https://target.example.com \ --authorized
Options:
Usage: fingerprint_server.py URL [OPTIONS]
Options:
--authorized Attest authorization (required for non-local)
--output FILE Write findings to FILE
--format FMT json | jsonl | markdown (default: markdown)
--min-severity SEV (default: info)
--timeout SECS Per-probe timeout (default: 10)
--trigger-error Send a malformed request to surface error-page disclosure
(off by default — some WAFs block on this)The scanner sends a baseline GET + an OPTIONS + (optionally) a malformed request to surface error-page disclosure. For each response, it parses the standard fingerprinting headers and classifies each match against the threshold table above.
The vast majority of findings will be MEDIUM or LOW. CWE-200 is by itself rarely a critical vulnerability — it's a recon enabler.
The exception: error-page stack-trace disclosure (CWE-209) is HIGH because production error pages should never leak server-internal paths or framework banners. If the error page reveals /home/app/src/handlers/auth.py, the attacker now knows the source layout AND that the language is Python.
After this skill, suggest:
detecting-debug-endpoints (#7) — fingerprinted framework pointsto which debug endpoints to probe (e.g., Server: nginx → check /nginx_status; X-Powered-By: Spring → check /actuator/).
detecting-exposed-secrets-files (#6) — framework fingerprintinforms which CI / IDE / build-tool configs to probe for.
User: "Make sure we're not leaking nginx version on prod."
bashpython3 ${CLAUDE_PLUGIN_ROOT}/skills/fingerprinting-server-software/scripts/fingerprint_server.py \ https://app.example.com --authorized --min-severity medium
Expected on a properly-configured host: zero findings of medium+.
User: "Bug bounty submission. We don't know what stack this runs. What's the surface?"
bashpython3 ${CLAUDE_PLUGIN_ROOT}/skills/fingerprinting-server-software/scripts/fingerprint_server.py \ https://target.example.com --authorized --format markdown
Use the output to inform which subsequent skills to chain (debug- endpoint probe, secrets-file probe).
User: "Audit production error pages for stack-trace disclosure."
bashpython3 ${CLAUDE_PLUGIN_ROOT}/skills/fingerprinting-server-software/scripts/fingerprint_server.py \ https://app.example.com --authorized --trigger-error --min-severity high
The --trigger-error flag sends a malformed request to provoke a
the result comes back empty.
JSON / JSONL / Markdown. Exit codes: 0 clean, 1 high/critical, 2 error.
Cloudflare/Imperva targets. The CDN itself is what gets fingerprinted, not the origin.
references/THEORY.md — Per-header reasoning: what each disclosureenables, threat-modeling guidance, CVE-lookup workflow
references/PLAYBOOK.md — Per-server-type remediation snippets(nginx server_tokens, Apache ServerTokens, IIS removeHeader, Express helmet hidePoweredBy, framework-default cookie renaming)
../analyzing-tls-config/references/AUTHORIZATION.md — Active-scanauthorization pattern
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 9,402 | 39,808 | +323% | 1 | 1 | 0% | 1,656 | 3,472 | +110% | 0 | 0 | — |
case-02 | fail→fail | 8,853 | 5,795 | -35% | 1 | 1 | 0% | 1,461 | 1,904 | +30% | 0 | 0 | — |
case-03 | fail→fail | 10,143 | 15,827 | +56% | 1 | 1 | 0% | 776 | 3,194 | +312% | 0 | 0 | — |
case-04 | pass→pass | 7,492 | 5,153 | -31% | 1 | 1 | 0% | 1,351 | 2,498 | +85% | 0 | 0 | — |
case-05 | pass→pass | 13,775 | 18,262 | +33% | 1 | 1 | 0% | 2,474 | 4,973 | +101% | 0 | 0 | — |
case-06 | pass→pass | 12,939 | 15,578 | +20% | 1 | 1 | 0% | 2,216 | 4,588 | +107% | 0 | 0 | — |
case-07 | fail→pass | 12,755 | 6,134 | -52% | 1 | 1 | 0% | 1,821 | 2,443 | +34% | 0 | 0 | — |
case-08 | fail→pass | 14,624 | 9,008 | -38% | 1 | 1 | 0% | 1,987 | 2,957 | +49% | 0 | 0 | — |
case-09 | fail→pass | 9,209 | 14,376 | +56% | 1 | 1 | 0% | 1,325 | 2,290 | +73% | 0 | 0 | — |
case-10 | fail→pass | 8,949 | 6,979 | -22% | 1 | 1 | 0% | 1,479 | 2,713 | +83% | 0 | 0 | — |
case-11 | pass→pass | 11,996 | 6,467 | -46% | 1 | 1 | 0% | 1,876 | 2,734 | +46% | 0 | 0 | — |
case-12 | fail→pass | 10,001 | 3,570 | -64% | 1 | 1 | 0% | 1,746 | 2,144 | +23% | 0 | 0 | — |
case-13 | pass→pass | 16,948 | 2,461 | -85% | 1 | 1 | 0% | 1,710 | 1,978 | +16% | 0 | 0 | — |
case-14 | fail→pass | 8,961 | 2,102 | -77% | 1 | 1 | 0% | 1,403 | 1,914 | +36% | 0 | 0 | — |
case-15 | pass→pass | 8,139 | 14,615 | +80% | 1 | 1 | 0% | 1,308 | 2,460 | +88% | 0 | 0 | — |
case-16 | pass→pass | 8,776 | 2,313 | -74% | 1 | 1 | 0% | 1,558 | 1,969 | +26% | 0 | 0 | — |
case-17 | fail→pass | 12,117 | 12,021 | -1% | 1 | 1 | 0% | 1,865 | 2,604 | +40% | 0 | 0 | — |
case-18 | fail→pass | 9,692 | 3,004 | -69% | 1 | 1 | 0% | 1,459 | 2,014 | +38% | 0 | 0 | — |
case-19 | fail→pass | 8,011 | 11,619 | +45% | 1 | 1 | 0% | 1,284 | 2,103 | +64% | 0 | 0 | — |
case-20 | pass→pass | 9,859 | 3,603 | -63% | 1 | 1 | 0% | 1,596 | 2,173 | +36% | 0 | 0 | — |
case-21 | pass→pass | 12,829 | 6,744 | -47% | 1 | 1 | 0% | 2,051 | 2,646 | +29% | 0 | 0 | — |
case-22 | pass→pass | 11,143 | 8,290 | -26% | 1 | 1 | 0% | 1,797 | 2,769 | +54% | 0 | 0 | — |
case-23 | fail→pass | 11,615 | 6,044 | -48% | 1 | 1 | 0% | 1,614 | 2,445 | +51% | 0 | 0 | — |
case-24 | pass→pass | 13,029 | 4,916 | -62% | 1 | 1 | 0% | 2,102 | 2,362 | +12% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 24 cases were attempted, and 23 counted toward the lift figure. The other 1 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +42 percentage points is the difference between those two pass rates over the 23 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.