TL;DR: No weak cipher, no expired certificate — and the transport layer still failed. I verified protocol enforcement per hostname, found the archive host negotiating older versions, and set one estate-wide baseline.
The scenario
I ran this as a black-box review: no credentials, only the publicly visible surface. Here is what I saw before I touched anything.
A university content platform on an enterprise content system with a campus-wide service catalogue, distributed across multiple hosts including an archive. Assessment covered transport security configuration across every host, mail authentication, header policy and internal host exposure.
I removed all identifying information. The target is described only by sector and technology class so the pattern can be reused.
The pattern
The pattern I recognised — and that I keep finding in similar estates:
Transport security is the one layer where a downgrade is invisible in a screenshot. A protocol negotiation that falls back to an older version succeeds, the padlock appears, the certificate validates, and the page loads normally. The user has no signal at all. This is why protocol enforcement has to be verified from the outside, per host, rather than assumed from the fact that one host is configured correctly.
The cause is almost always configuration scope. An administrator secures the primary host, verifies it, and stops. Archive hosts, preview environments and service subdomains inherit the platform defaults, and the defaults on a content system are frequently permissive because the vendor supports a wider range of deployments than any single site needs. Each of these is a separate hostname with a separate certificate and a separate configuration file, and nothing reminds anyone that they exist.
What makes it worth a finding rather than a note is the combination with everything else. A site that enforces protocol versions on two hosts and not on three has an inconsistent perimeter, and an inconsistent perimeter is where an attacker chooses where to stand. The archive host with the older protocol negotiation is the one that gets used, not because it is attractive but because it is where the negotiation is easiest.
Findings
| Severity | Finding | Evidence |
|---|---|---|
| MEDIUM | Older transport versions accepted on archive hosts | Downgrade available on hosts the primary does not allow |
| MEDIUM | Mail authentication not enforced for the sending domain | Spoofable university mail |
| MEDIUM | Internal host names exposed in response headers | Service naming visible to the internet |
| LOW | Protocol enforcement inconsistent between hosts | No estate-wide baseline |
| LOW | Strict transport security without preload | Policy present but not submitted for preload |
| INFO | Certificates valid and key sizes adequate | No certificate-level finding |
The attack path
Reproduction in my lab
Every command below targets a lab container I control. Nothing here is aimed at a live system.
Test protocol enforcement per host on your own estate
# do every hosts, not just the primary
$ for h in example.org www.example.org archive.example.org; do
printf '%-26s ' "$h"
curl -so /dev/null -w '%{http_version} %{ssl_verify_result}\n' --tlsv1.0 --tls-max 1.0 "https://$h/" 2>&1 | tail -1
done
# and what the strictest host actually negotiated
$ curl -sv https://example.org/ 2>&1 | grep -iE 'SSL connection using|TLSv1'
Detection in your own estate
Enumerate every hostname that serves content
$ for h in $(cat hosts.txt); do
printf '%s ' "$h"
openssl s_client -connect "$h:443" -servername "$h" </dev/null 2>/dev/null \
| openssl x509 -noout -subject -dates 2>/dev/null | tr '\n' ' '
echo
done
Remediation
Set one transport baseline for the whole estate
# estate-wide baseline: modern versions only, forward secrecy only
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
# apply it everywhere, including archive and preview hosts
include /etc/nginx/tls-baseline.conf;
Once an attacker gains access, they can perform the following actions:
Takeaways
- Verify transport configuration per hostname; a screenshot proves nothing about negotiation.
- Archive and preview hosts are the ones that miss the baseline.
- An inconsistent perimeter is where an attacker chooses where to stand.
- Preload requires explicit submission; the header alone does nothing extra.