Some checks failed
🚀 Build & Deploy Image / Determine Build Necessity (push) Failing after 10m14s
🚀 Build & Deploy Image / Build Runtime Base Image (push) Has been skipped
🚀 Build & Deploy Image / Build Docker Image (push) Has been skipped
🚀 Build & Deploy Image / Run Tests & Quality Checks (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Staging (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Production (push) Has been skipped
Security Vulnerability Scan / Check for Dependency Changes (push) Failing after 11m25s
Security Vulnerability Scan / Composer Security Audit (push) Has been cancelled
- Remove middleware reference from Gitea Traefik labels (caused routing issues) - Optimize Gitea connection pool settings (MAX_IDLE_CONNS=30, authentication_timeout=180s) - Add explicit service reference in Traefik labels - Fix intermittent 504 timeouts by improving PostgreSQL connection handling Fixes Gitea unreachability via git.michaelschiemer.de
7.3 KiB
7.3 KiB
LiveComponent Security Model
CSRF-Schutz für LiveComponents
Frage: Sollten wir CSRF grundsätzlich für LiveComponents deaktivieren?
Antwort: Ja, aber mit alternativen Sicherheitsmaßnahmen.
Warum CSRF-Deaktivierung bei LiveComponents sinnvoll ist
1. Technische Inkompatibilität
- LiveComponents senden State per JSON, nicht als Form-Data
- Traditionelle CSRF-Tokens in
<form>-Elementen funktionieren nicht - AJAX-Requests benötigen andere Token-Delivery-Mechanismen
- Token-Rotation würde LiveComponent-State invalidieren
2. Architekturelle Gründe
- Stateless Component Model: Jeder Request enthält vollständigen State
- Component-ID als Identifier: Komponenten sind durch eindeutige IDs identifiziert
- Action-basierte Security: Actions werden explizit auf Component-Ebene validiert
- Version Tracking: Concurrent Update Detection durch Version-Nummern
3. Alternative Sicherheitsmaßnahmen
LiveComponents haben ein eigenes Sicherheitsmodell:
// ComponentAction mit Validierung
final readonly class ComponentAction
{
public function __construct(
public string $componentId, // Eindeutige Component-ID
public string $method, // Explizite Action-Methode
public array $params, // Validierte Parameter
public int $version // Concurrent Update Detection
) {}
}
Implementierte Security-Layer für LiveComponents
1. Origin Validation
// SameSite Cookies + Origin Header Check
if ($request->headers->get('Origin') !== $expectedOrigin) {
throw new SecurityException('Invalid origin');
}
2. X-Requested-With Header
// AJAX-Request Verification
if ($request->headers->get('X-Requested-With') !== 'XMLHttpRequest') {
throw new SecurityException('Invalid request type');
}
3. Component State Integrity
// State Tampering Detection
$hash = hash_hmac('sha256', json_encode($state), $secretKey);
if (!hash_equals($hash, $providedHash)) {
throw new SecurityException('State tampering detected');
}
4. Version-based Concurrency Control
// Prevent Concurrent Update Issues
if ($currentVersion !== $expectedVersion) {
throw new ConcurrentUpdateException('State has changed');
}
Middleware-Konfiguration
CSRF-Middleware Skip
// src/Framework/Http/Middlewares/CsrfMiddleware.php
// Skip CSRF validation for API routes and LiveComponent AJAX endpoints
// LiveComponents use stateless, component-scoped security model instead
if (str_starts_with($request->path, '/api/') ||
str_starts_with($request->path, '/live-component/') ||
str_starts_with($request->path, '/livecomponent/')) {
return $next($context);
}
Honeypot-Middleware Skip
// src/Framework/Http/Middlewares/HoneypotMiddleware.php
// Skip honeypot validation for API routes and LiveComponent AJAX endpoints
if (str_starts_with($request->path, '/api/') ||
str_starts_with($request->path, '/live-component/') ||
str_starts_with($request->path, '/livecomponent/')) {
return;
}
LiveComponent Routes
// Framework Route
#[Route('/live-component/{id}', method: Method::POST)]
public function handleAction(string $id, HttpRequest $request): JsonResult
// Upload Route
#[Route('/live-component/{id}/upload', method: Method::POST)]
public function handleUpload(string $id, HttpRequest $request): JsonResult
Sicherheitsempfehlungen
✅ DO (Implementiert):
- Origin Validation: Same-Origin-Policy durchsetzen
- X-Requested-With Header: AJAX-Requests validieren
- Component State Integrity: State-Hashing implementieren
- Version Control: Concurrent Updates erkennen
- Rate Limiting: API-Rate-Limits für LiveComponent-Endpoints
- Session Validation: Authentifizierte User-Sessions prüfen
❌ DON'T:
- Keine traditionellen CSRF-Tokens in LiveComponent-Requests
- Keine Honeypot-Felder in JSON-Payloads
- Keine Token-Rotation während LiveComponent-Sessions
- Keine Form-basierte Validierung für AJAX-Endpoints
Security Threat Model
Bedrohungen die WEITERHIN abgewehrt werden:
- ✅ Session Hijacking: Session-Cookie mit HttpOnly + Secure Flags
- ✅ XSS Attacks: Content Security Policy + Output Escaping
- ✅ Man-in-the-Middle: HTTPS-Only Communication
- ✅ Replay Attacks: Version-based Concurrency Detection
- ✅ State Tampering: HMAC State Integrity Validation
Bedrohungen die durch CSRF-Skip entstehen könnten:
- ⚠️ Cross-Site Request Forgery: Durch Origin Validation abgedeckt
- ⚠️ Clickjacking: Durch X-Frame-Options Header abgedeckt
- ⚠️ JSON Hijacking: Durch X-Requested-With Header abgedeckt
Alternative Security Implementation
Für kritische Actions (z.B. Zahlungen, Account-Löschung):
// Zusätzliche Action-Level Security
final class CriticalAction extends LiveComponent
{
public function deleteAccount(array $params): ComponentUpdate
{
// 1. Re-Authentication Check
if (!$this->session->recentlyAuthenticated()) {
throw new ReAuthenticationRequired();
}
// 2. Action-Specific Token
$actionToken = $params['action_token'] ?? null;
if (!$this->validateActionToken($actionToken)) {
throw new InvalidActionToken();
}
// 3. Rate Limiting
if ($this->rateLimiter->tooManyAttempts($this->userId)) {
throw new TooManyAttemptsException();
}
// 4. Execute Critical Action
$this->accountService->delete($this->userId);
return ComponentUpdate::withMessage('Account deleted');
}
}
Testing Security
// Security Test Cases
describe('LiveComponent Security', function () {
it('rejects requests without X-Requested-With header', function () {
$response = $this->post('/live-component/datatable:demo', [
'action' => 'sort'
]);
expect($response->status)->toBe(403);
});
it('validates component state integrity', function () {
$tamperedState = ['malicious' => 'data'];
$response = $this->post('/live-component/datatable:demo', [
'action' => 'sort',
'state' => $tamperedState
], [
'X-Requested-With' => 'XMLHttpRequest'
]);
expect($response->status)->toBe(400);
expect($response->json()['error'])->toContain('State tampering');
});
});
Zusammenfassung
CSRF und Honeypot sind für LiveComponents deaktiviert, weil:
- ✅ Technisch inkompatibel mit JSON-basiertem State Management
- ✅ Architektonisch unnötig durch Component-scoped Security Model
- ✅ Durch alternative Maßnahmen ersetzt: Origin Validation, State Integrity, Version Control
- ✅ Best Practice in modernen JavaScript-Frameworks (React, Vue, Angular)
Die Sicherheit wird gewährleistet durch:
- Origin Validation (Same-Origin-Policy)
- X-Requested-With Header Validation
- Component State Integrity (HMAC)
- Version-based Concurrency Control
- Session Validation für authentifizierte Actions
- Optional: Action-Level Tokens für kritische Operations
Dies entspricht dem Security-Model moderner Single-Page Applications und ist die empfohlene Vorgehensweise für AJAX-basierte Component-Systeme.