diff --git a/BEDIENUNGSANLEITUNG.md b/BEDIENUNGSANLEITUNG.md index 4a99f69..4d12a3d 100644 --- a/BEDIENUNGSANLEITUNG.md +++ b/BEDIENUNGSANLEITUNG.md @@ -23,6 +23,9 @@ unbefugte Manipulationen. Der Scanner läuft lokal im Verantwortungsbereich des 14. [Rausch-Unterdrückung konfigurieren](#14-rausch-unterdrückung-konfigurieren) 15. [Was der Scanner erkennt](#15-was-der-scanner-erkennt) 16. [Verzeichnisstruktur](#16-verzeichnisstruktur) +17. [Cloaking-Erkennung](#17-cloaking-erkennung) +18. [Externe Links auf Erreichbarkeit prüfen](#18-externe-links-auf-erreichbarkeit-prüfen) +19. [Binärdateien und Assets prüfen](#19-binärdateien-und-assets-prüfen) --- @@ -144,6 +147,10 @@ Globale Optionen: `--config path/to/config.yaml`, `--verbose` (`-v`). | `report` | Letzten Report im Terminal anzeigen | | `report --format json` | Letzten Report als JSON anzeigen | | `status` | Baseline-Datum, letzter Scan, aktueller Risk-Level | +| `cloak-check` | Doppel-Crawl: Browser-UA vs. Googlebot (Cloaking-Erkennung) | +| `check-ext-links` | Externe Links auf Erreichbarkeit prüfen (4xx/5xx) | +| `check-assets` | Binärdateien (JS/CSS/Bilder) auf Inhaltsänderung prüfen | +| `approve-assets` | Aktuelle Asset-Hashes als neue Baseline setzen | ### Beispiele @@ -384,17 +391,23 @@ Alle Einstellungen in `config.yaml`. Fehlende Werte werden aus den Defaults übe | Ereignis | Standard-Punkte | |---|---| | Verdächtiger Dateiname (Webshell) | 60 | +| Cloaking: Link nur im Bot-Crawl sichtbar | 60 | | Neue externe Domain | 50 | | Hidden Content (CSS-verstecktes Element mit Links/Text) | 40 | | Meta-Refresh | 40 | +| Cloaking: signifikant mehr Text im Bot-Crawl (>100 Zeichen) | 40 | +| Geänderte JavaScript-Datei (`check-assets`) | 40 | | Unerwartete Canonical-URL | 35 | | Unerwartetes JSON-LD `@type` | 35 | +| Geänderte CSS-Datei (`check-assets`) | 30 | | Neue interne URL | 30 | | Neues verdächtiges Inline-Script | 30 | | Link in HTML-Kommentar | 25 | +| Cloaking: `Vary: User-Agent` Header (ohne Inhaltsdiff) | 25 | | Großer Textblock (>200 Zeichen) | 20 | | Fehlende interne URL | 20 | | Neuer kaputte Link (4xx/5xx, nicht in Baseline) | 20 | +| Geänderte Bild-/Binärdatei (`check-assets`) | 20 | Alle Werte sind in `config.yaml` unter `scoring:` anpassbar. @@ -493,17 +506,19 @@ normalization: | Kaputte interne Links (neu) | Ja | 20 Punkte | | Kaputte interne Links (bekannt) | Ja, informativ | Kein Score | | Fehlende Security-Header | Ja, informativ | Kein Score | -| Kaputte **externe** Links | Nein | Nur ob Domain neu ist | -| Veränderungen in Bilddateien | Nein | Nur Dateiname/URL | +| Kaputte **externe** Links (4xx/5xx) | Ja, mit `check-ext-links` | Kein Score, nur Report | +| UA-basiertes Cloaking (Googlebot sieht anderen Inhalt) | Ja, mit `cloak-check` | Score 40–60 | +| Veränderungen in JS/CSS/Bildern (Inhalt) | Ja, mit `check-assets` | Score 20–40 | +| IP-basiertes Cloaking | Nein | Nur Google Search Console kann das erkennen | | Serverseitige Code-Änderungen | Nein | Nur sichtbare HTML-Ausgabe | ### Grenzen des Scanners -- Er prüft nur, was der Crawler als HTML-Seite sieht. Serverseitig eingeschleuster Code, - der nur unter bestimmten Bedingungen aktiv wird (z.B. nur für Suchmaschinen-Bots), - wird möglicherweise nicht erkannt. -- Bilder und andere Binärdateien werden nicht auf Inhalt geprüft. -- Externe Links werden nur auf Neuheit geprüft, nicht auf Erreichbarkeit. +- **IP-basiertes Cloaking** wird nicht erkannt: Wenn der Server je nach Herkunfts-IP + unterschiedliche Inhalte liefert (nur für echte Googlebot-IPs), sieht der Scanner immer + den normalen Inhalt. Ergänzung: Google Search Console → URL-Prüfung. +- Serverseitig injizierter Code, der nur unter bestimmten Bedingungen aktiv wird, ist + nur per `cloak-check` (UA-Variante) teilweise erkennbar. --- @@ -518,6 +533,7 @@ data/ baseline/ Freigegebene Referenz (NIEMALS automatisch geändert) manifest.json Wer/was/wann freigegeben hat pages/ Pro URL eine JSON-Datei (16-stelliger Hex-Name) + asset_hashes.json SHA-256-Hashes aller freigegebenen Assets (approve-assets) snapshots/ Ein Verzeichnis pro Crawl-Durchlauf YYYYMMDD_HHMMSS/ manifest.json Zeitstempel, Seitenzahl, Fehler @@ -526,9 +542,18 @@ logs/ scanner.log Detailliertes Laufzeit-Log cron.log Ausgabe der Cron-Ausführungen reports/ - YYYYMMDD_HHMMSS/ - report.md Menschenlesbarer Report - report.json Maschinenlesbarer Report (für spätere Auswertung) + YYYYMMDD_HHMMSS/ Normaler Scan-Report + report.md + report.json + YYYYMMDD_HHMMSS_cloak/ Cloaking-Check-Report + report.md + report.json + YYYYMMDD_HHMMSS_ext-links/ Externer-Links-Report + report.md + report.json + YYYYMMDD_HHMMSS_assets/ Asset-Check-Report + report.md + report.json scanner/ Python-Paket (Quellcode) tests/ Automatisierte Tests ``` @@ -540,3 +565,137 @@ pytest tests/ -v # alle Tests pytest tests/test_differ.py -v # einzelnes Testmodul pytest tests/test_differ.py::TestScoreDiff::test_green_for_no_changes -v # einzelner Test ``` + +--- + +## 17. Cloaking-Erkennung + +Cloaking bedeutet: der Server liefert Suchmaschinen-Bots absichtlich anderen Inhalt als +normalen Besuchern — ein klassisches Parasite-SEO-Angriffsmuster. + +### Befehl + +```bash +python -m scanner cloak-check +``` + +Der Scanner crawlt die Website zweimal nacheinander: einmal mit dem normalen Browser-User-Agent, +einmal als `Googlebot/2.1`. Unterschiede im Text, in den Links oder im `Vary`-Header werden +gemeldet. + +### Scoring + +| Fund | Punkte | +|---|---| +| Link nur im Bot-Crawl sichtbar | 60 (RED) | +| Bot sieht >100 Zeichen mehr Text | 40 | +| `Vary: User-Agent` Header ohne Inhaltsdiff | 25 | + +### Report + +Der Report liegt unter `reports/_cloak/report.md` und zeigt pro auffälliger Seite: +- ob `Vary: User-Agent` gesetzt ist +- welche Links nur der Bot sieht +- wie viele Zeichen mehr Text der Bot bekommt +- einen Text-Diff (bis zu 20 Zeilen) + +### Grenzen + +Erkennt nur **UA-basiertes** Cloaking. IP-basiertes Cloaking (Server prüft die +Herkunfts-IP des Crawlers) ist damit nicht erkennbar — dafür ist die Google Search Console +das richtige Werkzeug (URL-Prüfung → Live testen). + +### Wann ausführen? + +Nicht täglich — der Doppel-Crawl belastet den Server doppelt. Empfehlung: monatlich +oder bei konkretem Verdacht. + +--- + +## 18. Externe Links auf Erreichbarkeit prüfen + +Der tägliche `scan` erkennt *neue* externe Domains, prüft aber nicht ob bestehende externe +Links noch funktionieren. Dafür gibt es: + +```bash +python -m scanner check-ext-links +``` + +### Was geprüft wird + +Alle externen ``-Links aus dem letzten Snapshot werden per HEAD-Request abgefragt +(Fallback auf GET bei HTTP 405). Gemeldet werden: + +- **Kaputte Links** (HTTP 4xx/5xx) — mit Angabe, auf welchen Seiten sie verlinkt sind +- **Verbindungsfehler** (Timeout, DNS-Fehler) — ebenfalls mit Quelladressen + +### Scoring + +Kaputte externe Links werden **nicht bewertet** (kein Score-Einfluss). Das Ergebnis ist +rein informativ — externe Links brechen regelmäßig ohne Angriffsbezug. + +Exit-Code: `0` wenn alle Links erreichbar, `1` wenn mindestens ein kaputtes oder +fehlendes Link gefunden wurde. + +### Report + +Der Report liegt unter `reports/_ext-links/report.md`. + +### Wann ausführen? + +Wöchentlich oder monatlich reicht. Nicht im täglichen Cron — zu viele Requests an +externe Server. + +--- + +## 19. Binärdateien und Assets prüfen + +Der tägliche `scan` erkennt Änderungen im HTML-Text und an Link-URLs, aber nicht ob der +*Inhalt* einer Bilddatei oder eines JavaScript-Files ausgetauscht wurde. Dafür: + +### Ersteinrichtung (einmalig) + +```bash +python -m scanner crawl # aktuellen Snapshot anlegen (falls noch keiner vorhanden) +python -m scanner approve-assets # SHA-256-Hashes aller Assets als Baseline speichern +``` + +### Regelmäßige Prüfung + +```bash +python -m scanner check-assets +``` + +Alle verlinkten JS-, CSS- und Bilddateien aus dem letzten Snapshot werden heruntergeladen +und per SHA-256 gehasht. Abweichungen von der gespeicherten Baseline werden gemeldet. + +### Scoring + +| Dateityp | Punkte | +|---|---| +| JavaScript (`.js`) | 40 — YELLOW | +| CSS (`.css`, Stylesheets) | 30 — YELLOW | +| Bilder, PDFs, sonstige | 20 — YELLOW | +| 2× JS geändert | 80 — RED | + +### Änderungen freigeben + +Nach einem legitimen Update (neues CDN-Bundle, neues Logo): + +```bash +python -m scanner approve-assets --note "CDN-Update nach Redesign Juli 2026" +``` + +`approve-assets` fetcht alle Assets frisch und setzt die neuen Hashes als Baseline. + +### Report + +Der Report liegt unter `reports/_assets/report.md` und zeigt pro geänderter Datei: +- den Dateityp +- die ersten 16 Zeichen des alten und neuen SHA-256-Hash +- die Größenänderung in Bytes + +### Wann ausführen? + +Wöchentlich oder nach bekannten Website-Updates. Nicht täglich — lädt alle Assets herunter +und ist entsprechend langsam.