Python-Package zur unabhängigen Überwachung statischer Websites gegen SEO-Spam und unbefugte Manipulationen. Läuft außerhalb des Hosters. Kernfunktionen: - Reiner Python-Crawler (bs4+lxml), kein wget - Baseline-Management mit manuellem Freigabe-Workflow (niemals automatisch) - Text-/Link-/Meta-Diff mit Risiko-Scoring (grün/gelb/rot) - Hidden-Content-Erkennung (CSS inline, noscript, Kommentar-Links) - Whitelist für externe Domains und interne Pfade - E-Mail + Webhook Alarmierung - CLI: init, crawl, check, scan, approve, report, status - 79 Unit-Tests (pytest), alle grün Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
203 lines
4.7 KiB
Markdown
203 lines
4.7 KiB
Markdown
# Website Integrity Scanner
|
|
|
|
Unabhängiges Überwachungswerkzeug für statische Websites gegen SEO-Spam
|
|
und unbefugte Manipulationen. Läuft im Verantwortungsbereich des Betreibers,
|
|
nicht beim Webhoster.
|
|
|
|
## Schnellstart
|
|
|
|
```bash
|
|
cd integrity_scanner_fuer_statische_Webseiten
|
|
python -m venv venv
|
|
source venv/bin/activate
|
|
pip install -r requirements.txt
|
|
|
|
# 1. Erste Baseline anlegen
|
|
python -m scanner init
|
|
|
|
# 2. Ergebnis prüfen, dann freigeben
|
|
python -m scanner approve --all --note "Initiale Baseline nach Sichtprüfung"
|
|
|
|
# 3. Täglicher Betrieb (oder per Cron)
|
|
python -m scanner scan
|
|
```
|
|
|
|
---
|
|
|
|
## Subcommands
|
|
|
|
| Befehl | Funktion |
|
|
|---|---|
|
|
| `init` | Erstcrawl + Vorschau, kein Baseline-Update |
|
|
| `crawl` | Crawlt die Website, speichert Snapshot |
|
|
| `check` | Vergleicht letzten Snapshot mit Baseline |
|
|
| `scan` | `crawl` + `check` in einem (für Cron) |
|
|
| `approve --all` | Alle Snapshot-URLs als neue Baseline freigeben |
|
|
| `approve --url URL` | Einzelne URL freigeben |
|
|
| `approve --rebuild` | Gesamte Baseline ersetzen (nach großer Änderung) |
|
|
| `report` | Letzten Report anzeigen |
|
|
| `status` | Baseline-Datum, letzter Scan, Risiko-Level |
|
|
|
|
Alle Befehle akzeptieren `--config path/to/config.yaml` und `--verbose`.
|
|
|
|
---
|
|
|
|
## Workflow: Erstinitialisierung
|
|
|
|
```
|
|
python -m scanner init
|
|
```
|
|
|
|
Ausgabe zeigt:
|
|
- alle gefundenen internen URLs
|
|
- alle externen Links (mit Whitelist-Status)
|
|
- potenzielle Auffälligkeiten (Hidden Content, Meta-Refresh, ...)
|
|
|
|
**Wichtig**: Die Ausgabe manuell prüfen, bevor die Baseline gesetzt wird.
|
|
Insbesondere externe Links in `config/allowed_external.yaml` eintragen.
|
|
|
|
```
|
|
python -m scanner approve --all --note "Initiale Baseline, geprüft am $(date)"
|
|
```
|
|
|
|
---
|
|
|
|
## Workflow: Täglicher Betrieb (Cron)
|
|
|
|
```
|
|
python -m scanner scan
|
|
```
|
|
|
|
Exit-Codes:
|
|
- `0` = Grün (keine Auffälligkeiten)
|
|
- `1` = Gelb (Warnung, manuelle Prüfung empfohlen)
|
|
- `2` = Rot (Alarm, sofortige Prüfung notwendig)
|
|
|
|
---
|
|
|
|
## Workflow: Legitime Änderung freigeben
|
|
|
|
```bash
|
|
# 1. Scan durchgeführt, Warnung auf /impressum/
|
|
python -m scanner report # Report ansehen
|
|
python -m scanner approve --url https://bredelar.info/impressum/ --note "Impressum aktualisiert"
|
|
|
|
# 2. Oder alle Änderungen auf einmal (wenn alles geprüft)
|
|
python -m scanner approve --all --note "Redesign vom 2026-06-12 freigegeben"
|
|
|
|
# 3. Nach großem Redesign: komplette neue Baseline
|
|
python -m scanner approve --rebuild --note "Komplettes Redesign, alle Seiten neu"
|
|
```
|
|
|
|
---
|
|
|
|
## Workflow: Incident (Alarm)
|
|
|
|
1. Report lesen: `python -m scanner report`
|
|
2. Verdächtige URLs manuell im Browser prüfen
|
|
3. Quelltext der betroffenen Seiten ansehen (insb. `display:none`-Bereiche)
|
|
4. Dienstleister kontaktieren, Zugriff auf Hosting prüfen
|
|
5. Nach Bereinigung: `python -m scanner scan` — muss grün sein
|
|
6. Dann: `python -m scanner approve --rebuild --note "Nach Incident bereinigt"`
|
|
|
|
**Wichtig**: Niemals `approve` auf eine kompromittierte Seite anwenden.
|
|
|
|
---
|
|
|
|
## Cron-Setup
|
|
|
|
```cron
|
|
# Täglich 03:00 Uhr
|
|
0 3 * * * cd /opt/scanner && /opt/scanner/venv/bin/python -m scanner scan >> /opt/scanner/logs/cron.log 2>&1
|
|
```
|
|
|
|
Log-Rotation (`/etc/logrotate.d/scanner`):
|
|
```
|
|
/opt/scanner/logs/*.log {
|
|
daily
|
|
rotate 30
|
|
compress
|
|
missingok
|
|
notifempty
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Konfiguration
|
|
|
|
### E-Mail aktivieren
|
|
|
|
In `config.yaml`:
|
|
```yaml
|
|
alerting:
|
|
email:
|
|
enabled: true
|
|
smtp_host: mail.example.com
|
|
smtp_port: 587
|
|
smtp_user: scanner@example.com
|
|
smtp_password_env: SCANNER_SMTP_PASSWORD
|
|
from: scanner@bredelar.info
|
|
to:
|
|
- admin@bredelar.info
|
|
```
|
|
|
|
Passwort als Umgebungsvariable setzen (nicht in config.yaml):
|
|
```bash
|
|
export SCANNER_SMTP_PASSWORD="geheimesPasswort"
|
|
```
|
|
|
|
### Webhook aktivieren
|
|
|
|
```yaml
|
|
alerting:
|
|
webhook:
|
|
enabled: true
|
|
url: "https://hooks.slack.com/services/..."
|
|
```
|
|
|
|
### Externe Domains whitelisten
|
|
|
|
Nach dem ersten `init` alle legitimen externen Domains in
|
|
`config/allowed_external.yaml` eintragen:
|
|
|
|
```yaml
|
|
- fonts.googleapis.com
|
|
- maps.googleapis.com
|
|
```
|
|
|
|
---
|
|
|
|
## Verzeichnisstruktur
|
|
|
|
```
|
|
data/
|
|
baseline/ Aktuell freigegebene Referenz (NIEMALS automatisch aktualisiert)
|
|
manifest.json Wer/was/wann freigegeben hat
|
|
pages/ Pro URL eine JSON-Datei
|
|
snapshots/ Zeitgestempelte Crawl-Ergebnisse
|
|
YYYYMMDD_HHMMSS/
|
|
reports/ Generierte Reports (JSON + Markdown)
|
|
logs/ scanner.log
|
|
config/
|
|
allowed_external.yaml
|
|
allowed_paths.yaml
|
|
ignore_rules.yaml
|
|
```
|
|
|
|
---
|
|
|
|
## Tests
|
|
|
|
```bash
|
|
pytest tests/ -v
|
|
```
|
|
|
|
---
|
|
|
|
## Erweiterungen (optional, nicht implementiert)
|
|
|
|
- Ollama-Integration: Neue Textblöcke semantisch auf Spam-Kategorien prüfen
|
|
- Telegram-Bot: direkter Alert-Kanal
|
|
- Diff-Anzeige im Terminal: `python -m scanner report --diff-only`
|
|
- Automatische Archivierung alter Snapshots nach N Tagen
|