kulturbanause Blog

Responsive Design, WordPress, Konzeption, HTML, CSS, JS & UX/UI …

Website-Sicherheit mit HTTP Security-Header erhöhen

Mit Hilfe von HTTP Security-Headern lässt sich die Sicherheit einer Website deutlich verbessern. Es gibt verschiedene HTTP Security-Header, die wir hier im Einzelnen erklären wollen. Einige dieser Header sind sehr einfach in eine Website einzubinden, andere sind komplexer und benötigen etwas mehr Konfigurationsarbeit. Wir zeigen, wie man für Websites die HTTP Security-Header aktiviert und konfiguriert. Dabei gehen wir unter anderem auf die Integration der Header in WordPress ein, beschreiben aber auch den Weg ohne WordPress.

Workshops & Schulungen von kulturbanause

Intensive Trainings mit hohem Praxisbezug.

Online-Schulungen (remote per Video)

Inhouse-Schulungen

Öffentliche Schulungstermine

Was sind HTTP Security-Header?

Fordert ein Browser eine Seite von einem Webserver an, dann antwortet der Webserver mit der Auslieferung der Seite und sendet außerdem einen HTTP-Response-Header mit dem Inhalt.
Neben Metadaten wie Zeichensätzen und Fehlercodes können auch sicherheitsrelevante Einstellungen gesendet werden. Diese schreiben dem Browser vor, wie er sich zu verhalten hat. Sicherheit ist leider ein gern vernachlässigtes Thema bei vielen Website-Betreibern. Man sollte sich unbedingt mit dieser Thematik beschäftigen, wenn man nicht Opfer einer Hacker-Attacke werden möchte. Über die HTTP Security-Header kann man dies oftmals recht einfach umsetzen.

Welche Header gibt es und was können sie?

X-Frame-Options (XFO)

Dieser Header verhindert, dass die Seite in einen Frame in einer anderen Seite geladen werden kann. Nicht unbedingt für die eigene Sicherheit, aber was Content-Diebstahl, Missbrauch etc. betrifft, sicher sehr hilfreich. Mit dem Wert »deny« wird keinerlei Laden in einem Frame zugelassen, mit »sameorigin« nur »in sich selbst«.

X-Frame-Options: DENY

X-XSS-Protection

Dieser Header verhindert das bekannte »Cross Site Scripting«, das gefürchtete Laden von fremden Scripten in die Website. Damit wird ggf. bösartiges JavaScript im Browser ausgeführt, ohne dass der Benutzer es überhaupt mitbekommt. Die »1« schaltet den Schutz ein, »mode=block« blockiert das Rendern der gesamten Seite, wenn ein fremdes Script erkannt wird.

X-XSS-Protection: 1; mode=block

X-Content-Type-Options

Dem Browser wird normalerweise mitgeteilt, welche Dateiformate er jeweils laden soll, also z. B. HTML oder JPG. Wenn das nicht angegeben wird, soll der Browser »raten«. Das kann man ausnutzen und so andere Formate einschleusen, die Schaden anrichten können. Mit dem Setzen dieses Headers untersagt man dem Browser das »sniffen« und unterbindet diese Angriffsmöglichkeit.

X-Content-Type-Options: nosniff

HTTP Strict-Transport-Security (HSTS)

Dieser Header informiert den Browser, dass die Seite nur per HTTPS aufgerufen werden darf. Voraussetzung ist hierbei natürlich, dass die Seite über ein SSL-Zertifikat verfügt.

Über den Parameter »max-age« wird die Zeit (in Sekunden) angegeben, in der der Browser sich merken soll, das die Seite nur über HTTPS aufgerufen werden darf. Mit »includeSubdomains« werden alle Subdomains mit in diese Regel eingeschlossen.

Strict-Transport-Security: max-age=<expire-time>; includeSubdomains

Referrer-Policy

Dieser Header steuert, ob der Referrer-Wert bei ausgehenden Links übergeben werden darf. Das heißt, darf der Browser einer Seite mitteilen, von welcher Seite der Benutzer gekommen ist. Mit dem Wert »no-referrer« verbietet man das komplett.

Dieser Header ist nicht direkt für die »Sicherheit« der Website verantwortlich aber in Bezug auf den Datenschutz schon interessant.

Referrer-Policy: no-referrer

Feature-Policy

Dieser Header hat nicht so sehr die Sicherheit der Website oder der Betreiber im Mittelpunkt, sondern vielmehr die Datensicherheit des Besuchers. In heutigen Zeiten ein Feature, das man nicht hoch genug einschätzen kann. Man kann den Einsatz von Mikrofon oder Kamera, den Abruf des Standorts, die Nutzung der Vibrationsfunktion u. a. unterbinden oder zulassen.

Feature-Policy: <directive> <allowlist>

Content-Security-Policy (CSP)

Dieser Security-Header umfasst viele Konfigurationsmöglichkeiten. Mit der Content-Security-Policy kann man detailliert festlegen, welche Inhaltstypen überhaupt ausgeliefert werden dürfen und von welchen Quellen. Das macht ihn so mächtig, dass man beim Setzen der Parameter sehr aufpassen sollte. Hier ist es ausschlaggebend, welche konkreten Rahmenbedingungen für eine Website gelten.

Soll die Website beispielsweise nur eigene Scripte und Scripte von Google erlauben, muss man dem Parameter »script-src« die Werte »self« und »https://www.google.com« zuweisen. Nach diesem Muster ordnet man allen weiteren Parametern ebenfalls die Werte zu. Eine Liste aller Parameter findet ihr hier.

Content-Security-Policy: default-src 'self'; script-src 'self' https://www.google.com; img-src 'self'; style-src 'self'; font-src 'self'; object-src 'none'; frame-src 'self'; worker-src 'self'; connect-src 'self';

Security Report erhalten

Durch den Einsatz des Content-Security-Policy Headers erstellt man eine Whitelist für alle erlaubten Quellen. Da dies sehr komplex ist, kann es durchaus passieren, dass man anfänglich nicht alle Quellen erfasst hat. Hierbei ist es hilfreich, einen »Security Report« einzurichten, der Informationen über geblockte Inhalte erfasst und in ein Log-File schreibt. Zusätzlich besteht die Möglichkeit, diese Informationen auch via E-Mail zu versenden, sobald ein »Problem« auftritt.

Content-Security-Policy: report-uri /security-report.php

Zum Erstellen dieses Security-Reports muss folgender Code in eine PHP-Datei übernommen werden und im Verzeichnis eurer Website abgelegt werden. Der Pfad zur Datei wird dann als Endpunkt hinter dem Parameter »report-uri« an den Content-Security-Policy Header angehangen.

<?php
$log_file = dirname(__FILE__) . '/csp-violations.log';
$log_file_size_limit = 1000000; // bytes
$email_address = 'email@domain.dlt';
$email_subject = 'Content-Security-Policy violation';

$current_domain = preg_replace('/www\./i', '', $_SERVER['SERVER_NAME']);
$email_subject = $email_subject . ' on ' . $current_domain;
http_response_code(204); // HTTP 204 No Content

$json_data = file_get_contents('php://input');
if ($json_data = json_decode($json_data)) {
  $json_data = json_encode($json_data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);

  if (!file_exists($log_file)) {
    // Send an email
    $message = "The following Content-Security-Policy violation occurred on " .
    $current_domain . ":\n\n" .
    $json_data .
    "\n\nFurther CSP violations will be logged to the following log file, but no further email notifications will be sent until this log file is deleted:\n\n" .
    $log_file;
    mail($email_address, $email_subject, $message,
         'Content-Type: text/plain;charset=utf-8');
  } else if (filesize($log_file) > $log_file_size_limit) {
    exit(0);
  }
  file_put_contents($log_file, $json_data, FILE_APPEND | LOCK_EX);
}
?>

Integration der HTTP Security Header über die .htaccess

Die Integration der Security Header wird standardmäßig über die .htaccess durchgeführt. Das folgende Snippet ist ein Beispiel für diese Integration.

<IfModule mod_headers.c>
  Header set X-Frame-Options "DENY"
  Header set X-XSS-Protection "1; mode=block"
  Header set X-Content-Type-Options "nosniff"
  Header set Strict-Transport-Security "max-age=31536000; includeSubDomains"
  Header set Referrer-Policy "no-referrer"
  Header set Feature-Policy "accelerometer 'none'; ambient-light-sensor 'none'; autoplay 'self'; camera 'none'; encrypted-media 'none'; fullscreen; geolocation 'self'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; midi 'none'; payment 'none'; picture-in-picture 'self'; speaker 'none'; usb 'none'; vr 'none'"
  Header set Content-Security-Policy "default-src 'self'; script-src 'self' https://www.google.com; img-src 'self'; style-src 'self'; font-src 'self'; object-src 'none'; frame-src 'self'; worker-src 'self'; connect-src 'self'; report-uri /security-report.php"
</IfModule>

Integration der HTTP Security Header über WordPress-Hook

Wenn es sich bei der Website um eine WordPress-Umsetzung handelt, können die Security Header mit dem Filter »wp_headers« über die functions.php integriert werden.

if (!empty($_SERVER['HTTPS'])) {
  function kb_add_security_headers($headers) {
    $headers["x-frame-options"] = "deny";
    $headers["x-xss-protection"] = "1; mode=block";
    $headers["x-content-type-options"] = "nosniff";
    $headers["strict-transport-security"] = "max-age=31536000; includeSubDomains";
    $headers["referrer-policy"] = "no-referrer";
    $headers["feature-policy"] = "accelerometer 'none'; ambient-light-sensor 'none'; autoplay 'self'; camera 'none'; encrypted-media 'none'; fullscreen; geolocation 'self'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; midi 'none'; payment 'none'; picture-in-picture 'self'; speaker 'none'; usb 'none'; vr 'none'";
    $headers["content-security-policy"] = "default-src 'self'; script-src 'self' https://www.google.com; img-src 'self'; style-src 'self'; font-src 'self'; object-src 'none'; frame-src 'self'; worker-src 'self'; connect-src 'self'; report-uri ".esc_url(get_template_directory_uri())."/security-report.php";
    return $headers;
  }
  add_filter('wp_headers', 'kb_add_security_headers');
}

Testen der HTTP Security Header

Nach der Integration empfiehlt es sich, die Header auf ihre Funktionsfähigkeit zu testen. Hierfür gibt es einige Tools im Internet.

Links / Quellen

Jetzt bist du gefragt!

Hast du Anregungen, Ergänzungen, einen Fehler gefunden oder ist dieser Beitrag nicht mehr aktuell? Dann freuen wir uns auf deinen Kommentar.

Du kannst diesen Beitrag natürlich auch weiterempfehlen. Wir sind dir für jede Unterstützung dankbar!

Unterstützung bei WordPress-Projekten

Unsere WordPress Agentur ist auf die Entwicklung maßgeschneiderter WordPress-Themes und -Websites spezialisiert. Wenn du Unterstützung bei der Planung, Gestaltung und Entwicklung eines Projekts benötigst, helfen wir gerne weiter.
WordPress-Leistungsangebot →

Das könnte dich auch interessieren

4 Kommentare

  1. Torben Andresen

    Verfasst am 21. Juli 2020 um 15:54 Uhr.

    Moin,

    vielen Dank für einen weiteren tollen Beitrag.

    Diesmal ist mir aber ein kleiner Schreibfehler aufgefallen und zwar im report-uri Script. Im Teil für den E-Mailtext steht: „Further CPS violations“, das müsste aber CSP heißen. Zugegeben, ist wirklich nur eine Winzigkeit. ;)

    • Jonas Hellwig

      Verfasst am 21. Juli 2020 um 18:10 Uhr.

      Vielen Dank – wir haben den Typo korrigiert.

    • Jonas Hellwig

      Verfasst am 27. Juli 2020 um 15:47 Uhr.

      Hallo Torben, Danke für den Hinweis! Ist geändert.

  2. Frank

    Verfasst am 25. Juli 2020 um 12:29 Uhr.

    Ganz herzlichen Dank, dass Du Dein Wissen großzügig und vor allem immer verständlich aufbereitet hier teilst. Seit ich zwei kleine Firmen-Websites betreue, bin ich dankbar für jeden Hinweis zur Verbesserung der Sicherheit.

    Beim Ausprobieren des WordPress-Codes ist mir aufgefallen, dass wohl noch ein kleiner Tippfehler enthalten ist? In der Zeile
    $headers[„content-security-policy“] = „“default-src
    ist hinter dem Gleichheitszeichen ein Anführungszeichen zuviel.

Kommentar verfassen

Dieser Blog lebt vom Feedback der Besucher! Also los, mach mit!
Bitte habe Verständnis dafür, dass Kommentare die mit dem Inhalt dieses Beitrags nichts zu tun haben, gelöscht werden.