mirror of
https://github.com/HolgerHatGarKeineNode/einundzwanzig-nostr.git
synced 2026-02-15 03:23:17 +00:00
## Security Audit: Session-Konfiguration härten
### Problem
Die aktuelle `.env.example` hat unsichere Session-Defaults:
```env
SESSION_ENCRYPT=false # Session-Daten unverschlüsselt in der DB
SESSION_SECURE_COOKIE= # Nicht gesetzt – Cookie wird auch über HTTP gesendet
SESSION_DOMAIN=null # Nicht eingeschränkt
```
Da die App eine Custom Nostr-basierte Auth verwendet (`app/Auth/NostrSessionGuard.php`) und der `pubkey` in der Session gespeichert wird, ist die Session ein attraktives Angriffsziel. Unverschlüsselte Sessions in der Datenbank bedeuten, dass ein DB-Leak sofort alle aktiven Sessions kompromittiert.
### Lösung
**1. `.env.example` aktualisieren:**
```env
SESSION_ENCRYPT=true
SESSION_SECURE_COOKIE=true
```
**2. Session-Config in `config/session.php` prüfen:**
Falls `config/session.php` nicht existiert (Laravel 12 Slim-Struktur), muss die Config ggf. mit `php artisan config:publish session` veröffentlicht werden. Prüfe ob die folgenden Werte korrekt gesetzt sind:
```php
'encrypt' => env('SESSION_ENCRYPT', true), // Default auf true ändern
'secure' => env('SESSION_SECURE_COOKIE', true), // Default auf true ändern
'http_only' => true, // Bereits Standard
'same_site' => 'lax', // Bereits Standard
```
**3. Cookie-Sicherheit:**
- `http_only` verhindert JavaScript-Zugriff auf Session-Cookies (Schutz gegen XSS-Cookie-Theft)
- `secure` erzwingt HTTPS-only Übertragung
- `same_site: lax` schützt gegen CSRF bei Top-Level-Navigation
### Betroffene Dateien
- `.env.example` – Default-Werte aktualisieren
- `config/session.php` – Falls vorhanden, Defaults härten. Falls nicht vorhanden, mit `php artisan config:publish session` erstellen und anpassen
### Vorgehen
1. Prüfe ob `config/session.php` existiert (bei Laravel 12 ist es möglicherweise nicht veröffentlicht)
2. Falls nicht vorhanden: `php artisan config:publish session --no-interaction`
3. Sichere Defaults setzen (encrypt=true, secure=true)
4. `.env.example` aktualisieren
5. Einen Pest-Test schreiben, der verifiziert dass Session-Cookies die korrekten Flags haben (secure, httpOnly, sameSite)
6. `vendor/bin/pint --dirty` und `php artisan test --compact`
### Hinweis
- In der lokalen Entwicklung (`APP_ENV=local`) kann `SESSION_SECURE_COOKIE=false` gesetzt werden, damit HTTP funktioniert
- Der Default in der Config sollte aber `true` sein, damit Produktion abgesichert ist
- Die `.env` Datei selbst wird NICHT bearbeitet (nur `.env.example`)
### Akzeptanzkriterien
- `SESSION_ENCRYPT=true` als Default in `.env.example`
- `SESSION_SECURE_COOKIE=true` als Default in `.env.example`
- Session-Config verwendet sichere Defaults
- Tests verifizieren Cookie-Sicherheitsflags
- Lokale Entwicklung bleibt funktional (über `.env` Override)
40 lines
1.5 KiB
PHP
40 lines
1.5 KiB
PHP
<?php
|
|
|
|
it('has secure defaults in session config file', function () {
|
|
$config = require base_path('config/session.php');
|
|
|
|
// When no env vars are set, these should default to secure values
|
|
expect($config['http_only'])->toBeTrue('http_only should default to true');
|
|
expect($config['same_site'])->toBe('lax', 'same_site should default to lax');
|
|
});
|
|
|
|
it('defaults session encryption to true in config', function () {
|
|
$configContent = file_get_contents(base_path('config/session.php'));
|
|
|
|
expect($configContent)->toContain("env('SESSION_ENCRYPT', true)");
|
|
});
|
|
|
|
it('defaults secure cookie to true in config', function () {
|
|
$configContent = file_get_contents(base_path('config/session.php'));
|
|
|
|
expect($configContent)->toContain("env('SESSION_SECURE_COOKIE', true)");
|
|
});
|
|
|
|
it('has secure session defaults in env example', function () {
|
|
$envExample = file_get_contents(base_path('.env.example'));
|
|
|
|
expect($envExample)->toContain('SESSION_ENCRYPT=true');
|
|
expect($envExample)->toContain('SESSION_SECURE_COOKIE=true');
|
|
});
|
|
|
|
it('sets httponly and samesite flags on session cookie', function () {
|
|
$response = $this->get('/');
|
|
|
|
$sessionCookie = collect($response->headers->getCookies())
|
|
->first(fn ($cookie) => $cookie->getName() === config('session.cookie'));
|
|
|
|
expect($sessionCookie)->not->toBeNull();
|
|
expect($sessionCookie->isHttpOnly())->toBeTrue('Session cookie should be HttpOnly');
|
|
expect($sessionCookie->getSameSite())->toBe('lax', 'Session cookie should have SameSite=lax');
|
|
});
|