Build Log: I pointed ReconLite at my own portfolio and it found something
Tags: Build Log Projects: ReconLite, farvees.xyz Read time: ~[X] min
The setup
Once ReconLite could actually run a full scan end to end, the obvious first target was my own portfolio site, farvees.xyz. Not a test domain, not Juice Shop, the real thing that's actually live and that I point recruiters at. If a tool I built to find misconfigurations couldn't find anything on the one site I control completely, that would say more about the tool than about the site.
It found something.
What the scan found
Technology fingerprint (51 ms)
[LOW ] nginx 1.18.0 (Server header)
Exact version disclosed in a response header; it tells anyone
which known bugs to look for.
fix: Suppress version banners (nginx: server_tokens off; ...)
CVE match (NVD) (51 ms)
[HIGH] nginx 1.18.0: 6 CVE(s) matched, highest CVSS 7.7
Top: CVE-2021-23017 (CVSS 7.7), CVE-2023-44487 (CVSS 7.5),
CVE-2021-3618 (CVSS 7.4), CVE-2022-41742 (CVSS 7.1),
CVE-2022-41741 (CVSS 7.0). Source: Server header.
fix: Verify the real patch level (distro packages often
backport fixes without changing the version string), then
upgrade to a supported release.
Two separate things happening here, worth untangling:
- The server was telling anyone who asked exactly which nginx
version it was running, via the plain
Server: nginx/1.18.0response header. No request needed beyond a normal page load. - That version string matched six known CVEs in NVD, one with a CVSS score of 7.7, high severity. Whether every one of those actually applies to my setup is a separate question, see the caveat below, but the version banner is what made the question askable from the outside in the first place.
Why the version banner matters even before patching anything
It's tempting to read [LOW] on the version-disclosure finding and
move on, the CVE match is the scarier-looking [HIGH]. But the two
findings are connected: the CVE match only exists because the version
was disclosed. Hiding the banner doesn't patch anything, nginx is
still whatever version it is underneath, but it removes the free,
zero-effort reconnaissance step that an automated scanner (including
mine) relies on. A real attacker running the same kind of scan against
a banner-less server has to work harder, probing rather than reading.
This is also exactly the caveat ReconLite prints with every CVE match: version-based matching can be wrong in both directions, a backported distro fix can make an "old" version string actually safe, and a hidden banner doesn't mean the underlying software is current either. The scan result is a lead, not a verdict, in either direction.
The fix
Two changes to the nginx config on farvees.xyz.
1. Suppress the version banner, added to both server blocks:
server_tokens off;
This alone addresses the [LOW] finding directly, the Server header
now just says nginx with no version number, so a scan like
ReconLite's has nothing to match against NVD anymore.
2. Cleaned up the port 80 handling. The existing config, generated
by Certbot, redirected to HTTPS conditionally per hostname and fell
back to return 404 for anything else:
# before (Certbot-generated)
if ($host = farvees.xyz) {
return 301 https://$host$request_uri;
}
return 404;
Replaced with an unconditional redirect:
listen 80;
return 301 https://$host$request_uri;
This wasn't something the scan flagged directly, but it came up while I
was in the config for the server_tokens change. Certbot's
conditional-per-host pattern is fragile: it only redirects the
hostnames it knew about at the time it generated the block, and
silently 404s anything else on port 80 instead of redirecting it. A
catch-all redirect is simpler and doesn't need to be regenerated every
time a new hostname or subdomain is added.
What I learned
- Running your own tool against your own production infrastructure finds real things, not just hypothetical ones. It's easy to build a scanner, test it against Juice Shop, and call it done. Pointing it at something I actually operate turned up a real, fixable misconfiguration I hadn't noticed.
- A
[LOW]finding can be the cause of a[HIGH]one. The CVE match looked like the more serious issue, but the version-disclosure finding underneath it is what made the CVE match possible in the first place. Fixing the root cause (the banner) is more durable than just planning to upgrade nginx eventually. - Suppressing a version banner is not the same as patching. I'm treating this as step one, reduce easy reconnaissance now, and separately verify the real patch level of the nginx install before deciding whether an upgrade is actually needed, exactly the caveat the tool itself prints.
- Infrastructure config accumulates auto-generated cruft. The Certbot conditional redirect wasn't wrong, exactly, but it wasn't something I'd have written by hand either, and it was more fragile than it needed to be. Worth occasionally reading config files that were generated rather than written.
Next
[Optional: note whether you've since verified the actual patched state of nginx on the server, e.g. checked the distro package changelog rather than relying on the version string either way, and whether you've re-run the scan post-fix to confirm the banner is gone.]
