60 lines
1.9 KiB
Markdown
60 lines
1.9 KiB
Markdown
# Issue #42 – CSRF-Schutz für Kontaktformular
|
||
|
||
## Komplexität: S (Small)
|
||
- Token-Generierung, Hidden-Field, Validierung
|
||
- Geschätzter Aufwand: < 30 Min
|
||
|
||
## Analyse
|
||
Kontaktformular in HomeController. Session wird bereits gestartet. CSRF-Token muss vor Formular-Render generiert und bei POST validiert werden.
|
||
|
||
### Aktueller Formular-Flow
|
||
1. `session_start()` in HomeController::index()
|
||
2. POST-Verarbeitung mit Validierung
|
||
3. Redirect nach Verarbeitung (PRG-Pattern)
|
||
4. Session speichert Formular-Status
|
||
|
||
### Architektur-Entscheidung
|
||
CSRF-Token direkt in HomeController implementieren:
|
||
1. Token beim GET-Request generieren und in Session speichern
|
||
2. Token als Hidden-Field im Formular ausgeben
|
||
3. Bei POST: Token validieren bevor Verarbeitung
|
||
|
||
### Implementierung
|
||
```php
|
||
// GET: Token generieren
|
||
if (empty($_SESSION['csrf_token'])) {
|
||
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
|
||
}
|
||
|
||
// POST: Token validieren
|
||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||
$csrfToken = $_POST['csrf_token'] ?? '';
|
||
if (!hash_equals($_SESSION['csrf_token'] ?? '', $csrfToken)) {
|
||
// CSRF-Fehler
|
||
header('Location: /#form-result');
|
||
exit;
|
||
}
|
||
// ... bestehende Validierung
|
||
}
|
||
```
|
||
|
||
Im View: `<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token'] ?? '') ?>">`
|
||
|
||
### Akzeptanzkriterien
|
||
- [ ] CSRF-Token wird bei jedem GET generiert
|
||
- [ ] Token ist als Hidden-Field im Formular vorhanden
|
||
- [ ] POST ohne gueltiges Token wird abgelehnt
|
||
- [ ] Formular funktioniert weiterhin korrekt mit Token
|
||
|
||
### Abhängigkeiten
|
||
Keine. Unabhaengig von anderen Issues.
|
||
|
||
### Edge Cases
|
||
- Token muss nach erfolgreicher Validierung nicht regeneriert werden (kein Login-Kontext)
|
||
- Mehrere Tabs: Gleicher Token pro Session ist ok
|
||
- Honeypot-Feld: Muss vor CSRF-Check kommen (sonst CSRF-Fehler beim Bot-Trap)
|
||
|
||
### Sicherheitsrisiken
|
||
- `hash_equals()` statt `===` verwenden (timing-safe Vergleich)
|
||
- Token-Laenge: 64 Hex-Zeichen (32 Bytes) ausreichend
|