TL;DR: Kein schwacher Cipher, kein abgelaufenes Zertifikat — und die Transportschicht fiel trotzdem durch. Ich habe die Protokollerzwingung pro Hostnamen geprüft, den Archiv-Host mit älterer Aushandlung gefunden und eine estate-weite Basislinie gesetzt.
Ausgangslage
Ich habe das Ziel als Black-Box geprüft: keine Zugangsdaten, nur die öffentlich sichtbare Fläche. Das ist, was ich sah, bevor ich etwas angefasst habe.
Eine Universitäts--Content-Plattform auf einem Enterprise-Content-System mit campusweitem Servicekatalog, verteilt über mehrere Hosts einschliesslich eines Archivs. Geprüft wurden die TLS-Konfiguration jedes Hosts, E-Mail-Authentifizierung, Header-Policy und interne Host-Freigabe.
Ich habe alle identifizierenden Informationen entfernt. Das Ziel wird ausschließlich nach Branche und Technologieklasse beschrieben, damit das Muster übertragbar bleibt.
Das Muster
Das Muster, das ich erkannt habe — und das ich in ähnlichen Landschaften immer wieder finde:
Transportsicherheit ist die einzige Schicht, in der ein Downgrade im Screenshot unsichtbar bleibt. Eine Protokoll-Aushandlung, die auf eine ältere Version zurückfällt, gelingt, das Schlösschen erscheint, das Zertifikat ist gültig, die Seite lädt. Der Nutzer hat kein Signal.
Die Ursache ist fast immer der Konfigurationsbereich. Ein Administrator sichert den Haupthost, prüft ihn und hört auf. Archiv-Hosts, Vorschaumgebungen und Service-Subdomains erben die Plattformvorgaben, und die sind permissiv.
Befundrelevant wird das in Kombination mit allem anderen. Eine Seite, die auf zwei Hosts erzwingt und auf drei nicht, hat eine inkonsistente Perimeter, und eine inkonsistente Perimeter ist dort, wo ein Angreifer sich stellt.
Befunde
| Schweregrad | Befund | Nachweis |
|---|---|---|
| MITTEL | Ältere Transportversionen auf Archiv-Hosts akzeptiert | Downgrade auf Hosts möglich, den der Haupthost nicht erlaubt |
| MITTEL | E-Mail-Authentifizisierung für die Absenderdomain nicht erzwungen | Universitäts--Mail fälschbar |
| MITTEL | Interne Hostnamen in Response-Headern exponiert | Servicebenennung im Internet sichtbar |
| NIEDRIG | Protokollerzwingung zwischen Hosts inkonsistent | Keine estate-weite Basislinie |
| NIEDRIG | Strict Transport Security ohne Preload | Policy vorhanden, aber nicht zur Preload eingereicht |
| INFO | Zertifikate gültig und Schlüsselgrößen angemessen | Kein Befund auf Zertifikatsebene |
Der Angriffspfad
Reproduktion im Labor
Jeder Befehl unten zielt auf einen Lab-Container, den ich selbst kontrolliere. Nichts davon ist auf ein laufendes System gerichtet.
Protokollerzwingung pro Host in der eigenen Landschaft prüfen
# jeden Host prüfen, nicht nur den Haupthost
$ 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
# und was der strengste Host tatsächlich ausgehandelt hat
$ curl -sv https://example.org/ 2>&1 | grep -iE 'SSL connection using|TLSv1'
Erkennung in eigener Infrastruktur
Jeden Hostnamen aufzählen, der Inhalte ausliefert
$ 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
Behebung
Eine Transport-Baseline für die gesamte Landschaft setzen
# estate-weite Basislinie: nur moderne Versionen, nur Forward Secrecy
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;
# überall anwenden, auch auf Archiv- und Vorschaum-Hosts
include /etc/nginx/tls-baseline.conf;
Sobald ein Angreifer Zugriff hat, kann er folgende Aktionen durchführen:
Fazit — was ich daraus mitnehme
- Prüfen Sie die Transportkonfiguration pro Hostnamen; ein Screenshot beweist nichts über die Aushandlung.
- Archiv- und Vorschaum-Hosts sind diejenigen, die die Basislinie verfehlen.
- Eine inkonsistente Perimeter ist dort, wo ein Angreifer sich stellt.
- Preload erfordert eine ausdrückliche Einreichung; der Header allein bewirkt nichts zusätzlich.