Files
michaelschiemer/docs/components/security/security-headers.md
Michael Schiemer 55a330b223 Enable Discovery debug logging for production troubleshooting
- Add DISCOVERY_LOG_LEVEL=debug
- Add DISCOVERY_SHOW_PROGRESS=true
- Temporary changes for debugging InitializerProcessor fixes on production
2025-08-11 20:13:26 +02:00

13 KiB

Security Headers

Dokumentationshinweis: Diese Dokumentation ist vollständig aktualisiert und stellt die aktuelle Implementierung der Security Headers korrekt dar.

Übersicht

Security Headers sind HTTP-Header, die dazu beitragen, die Sicherheit Ihrer Webanwendung zu verbessern, indem sie dem Browser Anweisungen geben, wie er mit bestimmten Sicherheitsaspekten umgehen soll. Das Framework implementiert automatisch eine umfassende Sammlung von Security Headers, die den aktuellen Best Practices entsprechen und Ihre Anwendung vor verschiedenen Arten von Angriffen schützen.

Hauptkomponenten

SecurityHeaderMiddleware

Die SecurityHeaderMiddleware ist die zentrale Komponente für die Implementierung von Security Headers:

use App\Framework\Http\Middlewares\SecurityHeaderMiddleware;

// In der Bootstrap-Datei oder Router-Konfiguration
$app->addMiddleware(SecurityHeaderMiddleware::class);

Diese Middleware:

  1. Entfernt unsichere Header wie X-Powered-By und Server
  2. Fügt automatisch wichtige Security Headers zu allen HTTP-Antworten hinzu
  3. Passt die Header basierend auf der Umgebung (Entwicklung oder Produktion) an

SecurityHeaderConfig

Die SecurityHeaderConfig-Klasse enthält die Konfiguration für die Security Headers:

use App\Framework\Http\Middlewares\SecurityHeaderConfig;

// Vordefinierte Konfigurationen verwenden
$config = SecurityHeaderConfig::forProduction(); // Strenge Einstellungen für Produktion
$config = SecurityHeaderConfig::forDevelopment(); // Weniger strenge Einstellungen für Entwicklung

// Benutzerdefinierte Konfiguration erstellen
$config = new SecurityHeaderConfig(
    $contentSecurityPolicy,
    $hstsHeader,
    $frameOptions,
    $referrerPolicy,
    $permissionsPolicy,
    $crossOriginEmbedderPolicy,
    $crossOriginOpenerPolicy,
    $crossOriginResourcePolicy
);

Implementierte Security Headers

Content-Security-Policy (CSP)

Die Content Security Policy schützt vor Cross-Site Scripting (XSS) und anderen Code-Injection-Angriffen, indem sie definiert, welche Ressourcen geladen werden dürfen:

Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';

In der Produktionsumgebung wird eine strengere CSP verwendet:

Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none';

Strict-Transport-Security (HSTS)

HSTS zwingt den Browser, nur HTTPS-Verbindungen zu verwenden, selbst wenn der Benutzer versucht, HTTP zu verwenden:

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

Parameter:

  • max-age: Dauer in Sekunden, für die der Browser nur HTTPS verwenden soll (1 Jahr)
  • includeSubDomains: Gilt auch für alle Subdomains
  • preload: Ermöglicht die Aufnahme in die HSTS-Preload-Liste der Browser

X-Frame-Options

Schützt vor Clickjacking-Angriffen, indem es kontrolliert, ob die Seite in einem Frame eingebettet werden darf:

X-Frame-Options: DENY

Optionen:

  • DENY: Die Seite darf nicht in einem Frame eingebettet werden
  • SAMEORIGIN: Die Seite darf nur in einem Frame auf derselben Domain eingebettet werden

X-Content-Type-Options

Verhindert MIME-Sniffing, bei dem Browser den Inhaltstyp einer Ressource erraten:

X-Content-Type-Options: nosniff

Referrer-Policy

Kontrolliert, welche Referrer-Informationen beim Navigieren zu anderen Seiten gesendet werden:

Referrer-Policy: strict-origin-when-cross-origin

Optionen:

  • no-referrer: Keine Referrer-Informationen senden
  • no-referrer-when-downgrade: Keine Referrer-Informationen senden, wenn von HTTPS zu HTTP navigiert wird
  • same-origin: Nur Referrer-Informationen senden, wenn auf derselben Domain navigiert wird
  • strict-origin: Nur die Ursprungs-URL senden und nur bei gleichem Sicherheitsniveau
  • strict-origin-when-cross-origin: Vollständige URL bei gleicher Domain, nur Ursprung bei Cross-Origin und gleichem Sicherheitsniveau

Permissions-Policy

Kontrolliert, welche Browser-Features und APIs die Seite verwenden darf:

Permissions-Policy: camera=(), microphone=(), geolocation=(), interest-cohort=()

Diese Einstellung deaktiviert den Zugriff auf Kamera, Mikrofon, Geolocation und FLoC (Federated Learning of Cohorts).

Cross-Origin-Policies

Eine Gruppe von Headern, die die Interaktion zwischen verschiedenen Ursprüngen kontrollieren:

Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Resource-Policy: same-origin

Diese Header schützen vor verschiedenen Cross-Origin-Angriffen und Informationslecks.

X-Permitted-Cross-Domain-Policies

Kontrolliert, ob Cross-Domain-Richtliniendateien (crossdomain.xml) geladen werden dürfen:

X-Permitted-Cross-Domain-Policies: none

Konfiguration

Umgebungsspezifische Konfiguration

Das Framework bietet vordefinierte Konfigurationen für verschiedene Umgebungen:

// In der SecurityHeaderMiddleware
$config = $this->securityConfig->enableStrictMode
    ? SecurityHeaderConfig::forProduction()
    : SecurityHeaderConfig::forDevelopment();

Die enableStrictMode-Einstellung kann in der Konfigurationsdatei angepasst werden:

// config/security.php
return [
    'headers' => [
        'strict_mode' => true, // Produktionsmodus mit strengeren Einstellungen
        'content_security_policy' => "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';",
        'hsts' => [
            'enabled' => true,
            'max_age' => 31536000, // 1 Jahr
            'include_subdomains' => true,
            'preload' => true,
        ],
    ],
];

Benutzerdefinierte Konfiguration

Sie können die Security Headers auch manuell konfigurieren:

// Eigene Security-Header-Konfiguration erstellen
$config = new SecurityHeaderConfig();
$config->contentSecurityPolicy = "default-src 'self'; script-src 'self' https://trusted-cdn.com;";
$config->frameOptions = "DENY";
$config->referrerPolicy = "strict-origin-when-cross-origin";

// Konfiguration anwenden
$securityHeaderMiddleware = new SecurityHeaderMiddleware($responseManipulator, $config);

Verwendung

Automatische Anwendung

Die Security Headers werden automatisch auf alle Antworten angewendet, wenn die Middleware registriert ist:

// In der Bootstrap-Datei
$app->addMiddleware(SecurityHeaderMiddleware::class);

Anpassung für bestimmte Routen

In einigen Fällen möchten Sie möglicherweise die Security Headers für bestimmte Routen anpassen:

// In einem Controller oder einer Middleware
public function __invoke(MiddlewareContext $context, Next $next): MiddlewareContext
{
    $resultContext = $next($context);
    
    if ($resultContext->hasResponse()) {
        $response = $resultContext->response;
        $headers = $response->headers;
        
        // CSP für eine bestimmte Route anpassen
        $updatedHeaders = $headers->with(
            'Content-Security-Policy',
            "default-src 'self'; script-src 'self' https://trusted-cdn.com;"
        );
        
        $updatedResponse = $this->manipulator->withHeaders($response, $updatedHeaders);
        return $resultContext->withResponse($updatedResponse);
    }
    
    return $resultContext;
}

Prüfen der aktuellen Security Headers

Sie können die aktuellen Security Headers Ihrer Anwendung mit verschiedenen Tools überprüfen:

  1. Browser-Entwicklertools: Überprüfen Sie die Response-Header in der Netzwerk-Ansicht
  2. Online-Tools: Verwenden Sie Dienste wie securityheaders.com oder observatory.mozilla.org
  3. Curl-Befehl: curl -I https://yourdomain.com

Content Security Policy (CSP)

Grundlegende CSP-Direktiven

Die Content Security Policy ist einer der wichtigsten Security Headers und verdient besondere Aufmerksamkeit:

  • default-src: Standardrichtlinie für alle Ressourcentypen
  • script-src: Erlaubte Quellen für JavaScript
  • style-src: Erlaubte Quellen für CSS
  • img-src: Erlaubte Quellen für Bilder
  • font-src: Erlaubte Quellen für Schriftarten
  • connect-src: Erlaubte Ziele für Fetch, XHR, WebSocket
  • media-src: Erlaubte Quellen für Audio und Video
  • object-src: Erlaubte Quellen für Plugins (Flash, PDF)
  • frame-src: Erlaubte Quellen für Frames
  • base-uri: Erlaubte URLs für das base-Element
  • form-action: Erlaubte Ziele für Formularübermittlungen
  • frame-ancestors: Erlaubte übergeordnete Dokumente (ähnlich X-Frame-Options)

CSP-Quellwerte

  • 'self': Ressourcen von derselben Ursprungs-Domain
  • 'none': Keine Ressourcen erlaubt
  • 'unsafe-inline': Inline-Skripte und Styles erlaubt (vermeiden in Produktion)
  • 'unsafe-eval': eval() und ähnliche Funktionen erlaubt (vermeiden in Produktion)
  • 'nonce-<base64-value>': Ressourcen mit entsprechendem Nonce-Attribut
  • 'sha256-<hash>': Ressourcen mit entsprechendem Hash
  • https://example.com: Spezifische Domain
  • https://*.example.com: Alle Subdomains
  • data:: Data-URLs (vorsichtig verwenden)

CSP-Beispiele

Strenge CSP für Produktion:

Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none';

CSP mit externen Ressourcen:

Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.jsdelivr.net; style-src 'self' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https://img.example.com;

CSP mit Nonce für Inline-Skripte:

// In einem Controller
public function showPage(): Response
{
    $nonce = bin2hex(random_bytes(16));
    
    // CSP mit Nonce setzen
    $csp = "default-src 'self'; script-src 'self' 'nonce-{$nonce}';";
    
    return $this->render('page.twig', [
        'nonce' => $nonce,
        'csp' => $csp,
    ]);
}

In der Vorlage:

<script nonce="{{ nonce }}">
    // Dieser Inline-Code ist erlaubt, weil er den korrekten Nonce hat
    console.log('Hello, world!');
</script>

CSP-Reporting

Sie können CSP-Verstöße an einen Endpunkt melden lassen:

Content-Security-Policy: default-src 'self'; report-uri /csp-report;

Oder verwenden Sie den neueren Report-To-Header:

Content-Security-Policy: default-src 'self'; report-to csp-endpoint;
Report-To: {"group":"csp-endpoint","max_age":10886400,"endpoints":[{"url":"/csp-report"}]}

Fehlerbehebung

Häufige Probleme

CSP blockiert legitime Ressourcen

Wenn Ihre Anwendung nicht korrekt funktioniert, weil die CSP legitime Ressourcen blockiert:

  1. Überprüfen Sie die Konsole im Browser auf CSP-Verstöße
  2. Erweitern Sie die CSP um die benötigten Quellen
  3. Verwenden Sie vorübergehend eine weniger strenge CSP während der Entwicklung
// Weniger strenge CSP für Entwicklung
$config->contentSecurityPolicy = "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';";

HSTS-Probleme

Wenn Sie HSTS aktiviert haben und Probleme auftreten:

  1. Beginnen Sie mit einer kurzen max-age (z.B. 300 Sekunden)
  2. Aktivieren Sie includeSubDomains erst, wenn Sie sicher sind, dass alle Subdomains HTTPS unterstützen
  3. Verwenden Sie preload nur, wenn Sie sicher sind, dass Ihre Domain dauerhaft HTTPS unterstützt

Frames werden blockiert

Wenn Ihre Anwendung Frames verwenden muss:

// X-Frame-Options anpassen
$config->frameOptions = "SAMEORIGIN"; // Erlaubt Frames auf derselben Domain

Sicherheitsüberlegungen

Best Practices

  1. Verwenden Sie strenge CSP: Vermeiden Sie 'unsafe-inline' und 'unsafe-eval' in Produktion
  2. Aktivieren Sie HSTS: Erzwingen Sie HTTPS für alle Verbindungen
  3. Regelmäßige Überprüfung: Testen Sie Ihre Security Headers regelmäßig mit Tools wie securityheaders.com
  4. Umgebungsspezifische Konfiguration: Verwenden Sie unterschiedliche Konfigurationen für Entwicklung und Produktion
  5. CSP-Reporting: Implementieren Sie CSP-Reporting, um Verstöße zu erkennen

Bekannte Einschränkungen

  • Ältere Browser unterstützen möglicherweise nicht alle Security Headers
  • Eine zu strenge CSP kann die Funktionalität von Drittanbieter-Skripten beeinträchtigen
  • HSTS kann nicht rückgängig gemacht werden, bis die max-age abgelaufen ist

Weiterführende Informationen