Apache absichern

Apache absichern

Viele Webserver und deren Webapplikation laufen ohne tiefgreifendere Konfigurationen. Dabei verpasst man die Chance sich und seine Besucher besser vor Angriffen zu schützen. Nur wenige Einstellungen erwarten eine wirklich tief gehende Kenntnis über deren Funktion und ermöglicht somit den meisten Admins recht einfach eine ordentlich robusten Webserver zu betreiben.

Die Konfigurationen sind in den Distributionen leider alle unterschiedlich strukturiert d.h. man sollte seinen Apache schon etwas kennen gelernt haben. Letztlich hat man eine Apache-Konfiguration, die z.B. bei Debian/Ubuntu unter /etc/apache2/apache2.conf liegt und unter RedHat/CentOS unter /etc/httpd/conf.d/httpd.conf. Dort sollten nur Apache relevante Einstellungen erfolgen, keine Modulkonfigurationen! Die Modulkonfigurationen wie z.B. TLS, Caching, FCGI usw. erfolgen in der Regel in den eigenen Konfigurationen. Doch nicht alle nötigen Einstellungen sind zwingen in diesen Dateien zu erfolgen, sondern können auch in einer VirtualHost speziell für eine (Sub)Domain hinterlegt werden. Wie ihr seht müsst ihr etwas flexibel sein und die jeweilige Konfiguration in eurem System suchen bzw. explizit dort setzen wo ihr sie benötigt.

Apache Header

In der Grundeinstellung posaunt der Apache stets seine Versionsnummer und evtl. Module im Header raus. Das ist für Angreifer die einfachste Einladung und muss abgestellt werden. Mit der Option “Servertoken”, kann die Ausgabe gesteuert werden. Stellt daher den Servertoken auf “Prod”, damit wird der Header des Dienstes auf die Ausgabe “Apache” reduziert. Die Version des Apaches kann man dennoch über Tools ermitteln, es erschwert nur die Erkennung und reduziert “DriveBy”-Angriffe.

Servertoken Prod

Apache Signatur

Ebenfalls eine völlig Unsitte ist die Option “ServerSignature”. Sie gibt ebenfalls Versionsummern und bei Bedarf sogar die Mailadresse des hinterlegten ServerAdmins aus. Diese Ausgabe sollte man auch hier unterbinden.

ServerSignature off

Trace

Die Option TRACE wird für Test- und Diagnoseanfragen im Proxymodus gebraucht und hat, meiner Meinung nach, nichts in öffentlichen Netzen zu suchen. Sollte man den Dienst nutzen wollen, dann sollte man ihn explizit absichern.

TraceEnable off

ProxyRequest

Wer seinen Apache als internen Proxy nutzt bzw. das Proxy-Modul aktiviert hat, sollte die Option “ProxyRequest” deaktivieren, ansonsten wird der Apache als Open-Proxy genutzt und fremde Inhalte aus dem Netz werden vom Apache ausgeliefert.

ProxyRequest off

Status

Status ist ein Modul das nichts auf einem produktiven Server suchen hat. Man kann mit dem Modul z.B. Sitzungsdaten auslesen und gehört, wenn überhaupt, nur abgesichert auf öffentliche Webserver. Wer mit dem Modul nichts verbindet, soll darauf achten das es deaktiviert ist – der Regelbetrieb des Webserver wird nicht beeinträchtigt.

Debian/Ubuntu: a2dismod status

TLS/SSL

Standardinstallation haben meist kein TLS aktiviert. Wenn es aktiviert ist hat das Protokoll meist eine viel zu hohe Toleranz bei der Verschlüsselung und führt das ganze wiederum ad absurdum. Um TLS umfassender zu erklären, möchte ich noch einen eigenständigen Artikel schreiben, daher hier nur eine kurzer VirtualHost-Eintrag, womit man aktuell gut dar steht

#SSL
SSLEngine on
SSLProxyEngine on
SSLHonorCipherOrder On

#SSL - Protokoll/Chipher
SSLProtocol ALL -SSLv2 -SSLv3
SSLCipherSuite “EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH EDH+aRSA !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4”
SSLCertificateFile /etc/apache2/ssl/.crt
SSLCACertificateFile /etc/apache2/ssl/.bundle
SSLCertificateKeyFile /etc/apache2/ssl/.key

Wer möchte, kann seine Konfiguration unter https://ssllabs.com/ssldb/ testen.

Wenn du mehr über Zertifikate wissen möchtest, ich habe in meinem Blog das Thema X509 Zertifikate angeschnitten

HSTS

Mit HTTP Strict Transport Security kann man festlegen, ob der Client/Browser die (Sub-)Domain nur via TLS ereichen soll. Nach der ersten Verbindung mit dem Server, wird im Client (z.B. Chrome und FireFox) die HSTS-Option gesetzt und selbst wenn jetzt eine HTTP-URL der (Sub-)Domain geöffnet wird, wird automatisch auf der Clientseite schon auf HTTPS umgestellt. Diese Option reduziert die Möglichkeit, dass man per DNS Manipulationen dem Client eine gefälschte Seite unter jubeln kann. Diese Option benötigt das Header-Modul.

Header always append Strict-Transport-Security “max-age=31536000 includeSubDomains;”

Mit der Option sollte man vorsichtig handeln, da diese im globalen Kontext alle Internetseiten auf einem Apache dazu zwingen ein TLS Konfiguration anzubieten. Ist dem nicht so, wird der Client die Verbindung mit einem Fehler quittieren. Wer einige Domains in unterschiedlicher Konfiguration auf seinem Server hat, kann die Header-Anweisung auch gezielt in einer VirtualHost unterbringen. Die letzte Option in der obigen Header-Anweisung “includeSubDomains”, sollte nur mit Bedacht gesetzt werden - sie ist optional.

Die Funktion HSTS geht sogar noch einen Schritt weiter: Mit der Option “preload” und einem Eintrag unter https://hstspreload.appspot.com/, wird die Domain in einer HSTS-Preload-Liste der Browser hinterlegt - Damit ist die Domain, für Browser, nur noch via HTTPS erreichbar.

Damit gesetzte Cookies nicht von Scripten genutzt werden können, kann man im Apache einen entsprechenden Header setzen. Man reduziert damit erheblich die Möglichkeit eines XSS Angriffs.

Header always edit Set-Cookie (.*) “$1; HTTPOnly; Secure”

OCSP

Online Certificate Status Protocol prüft, ob das vom Server ausgelieferte Zertifikat noch gültig ist. Ist dem nicht so, wird eine entsprechende Meldung an den Client gesendet. Die Prüfung des Zertifikates erfolgt, vom Webserver selbst, direkt beim CA-Aussteller via HTTP. Evtl. benötigt eure Firewall ein weiteres RuleSet für das OCSP-Protokoll.

SSLUseStapling on
SSLStaplingResponderTimeout 5
SSLStaplingReturnResponderErrors off
SSLStaplingCache shmcb:${APACHE_LOG_DIR}/ocsp(128000)

X-Frame-Options

Mit dieser Option lässt es sich unterbinden, dass die eigene Seite und teile davon in Frames dargestellt werden können. Damit verhindert man z.B. die Darstellung der eigenen Seite unter einer anderen Domain. Diese Sicherheitsoption ist in fast allen neueren Browser aktiviert, kann aber gezielt umgangen werden. Es ist eine Sicherheitsfunktion für den Browser-Nutzer.

Header always append X-Frame-Options SAMEORIGIN;

Es gibt folgende Optionen

  • DENY
    Es ist verboten die Seite in einem Frame darzustellen.
  • SAMEORIGIN
    Nur der eigene Domain ist dies erlaubt.
  • ALLOW-FROM
    Mit Angabe welche Domain dies dürfen.

X-Content-Type-Options

Diese Option teilt dem Browser (InternetExplorer und Chrome) mit, dass er z.B. CSS-Dateien nur als solchen nutzen soll, wenn die Datei auch den entsprechenden MIME-Typ “text/css” entspricht - die Logik gilt auch für Scripte.

Header set X-Content-Type-Options: “nosniff”

Content-Security-Policy (CSP)

Mit CSP wird festgelegt, woher welche Ressourcen genutzt werden dürfen. Die Option ist recht Komplex und sollte sehr bedacht eingesetzt werden. Wenn ihr externe Ressourcen nutzt und diese auf bestimmte URIs oder URLs beschränken möchtet, kann man das mit CSP recht genau definieren.

Header set Content-Security-Policy “default-src ‘self’; script-src https://apis.google.com

Optionen

  • default-src
    Gilt für alle Regeln, wenn diese nicht nachstehend expliziet überschrieben werden
  • script-src
    Definiert aus welcher Quelle Skripts ausgeführt werden dürfen
  • object-src
    Definiert aus welcher Quelle Plugins ausgeführt werden dürfen
  • style-src
    Definiert aus welcher Quelle CSS geladen werden dürfen
  • img-src
    Definiert aus welcher Quelle Bilder geladen werden dürfen
  • media-src
    Definiert aus welcher Quelle Bilder & Videos geladen werden dürfen
  • frame-src
    Definiert aus welcher Quelle Frames eingbunden werden dürfen
  • font-src
    Definiert aus welcher Quelle Schriften geladen werden dürfen
  • connect-src
    Definiert aus welcher URI/URL XHR, WebSockets und EventSource genutzt werden dürfen
  • form-action
    Definiert aus welcher Quelle Formulare ausgelöst werden dürfen
  • sandbox
    Specifies an HTML sandbox policy that the user agent applies to the protected resource
  • script-nonce
    Erlaubt nur die Ausführung von Skripten, wenn ein nonce Element definiert ist.
  • plugin-types
    Definiert ein Set an Plugins, die aufgerufen/eingebetet werden dürfen
  • reflected-xss
    Instructs a user agent to activate or deactivate any heuristics used to filter or block reflected cross-site scripting attacks, equivalent to the effects of the non-standard X-XSS-Protection header
  • report-uri
    Spezifiert eine URL, wohin der Browser Regelverstöße senden soll.

Werte

  • ’none’
    Der Einsatz ist nicht erlaubt
  • ‘self’
    Nur der Quelle ist es erlaubt
  • ‘unsafe-inline’
    Erlaubt inline JavaScript und CSS
  • ‘unsafe-eval’
    Erlaubt Text-to-JavaScript Techniken wie eval

Als Werte können ebenfalls URIs, URLs oder Protokolle angegeben werden

Einen guten Einblick gibt die W3C Spezifikation unter http://www.w3.org/TR/CSP/. Der Einsatz ist nicht immer ganz unproblematisch, da die typischen Browser (IE/IOS/Opera) wie immer der Technik nicht folgen können/wollen. Einen guten Überblick zeigt die folgende Seite http://caniuse.com/#feat=contentsecuritypolicy

Subresource Integrity (SRI)

Diese Einstellung betrifft zwar nicht den Apache selbst, da ich aber überhaupt kein Fan von extern eingebunden Ressourcen bin, erwähne ich hier die Möglichkeit das ganze etwas abzumildern. Neben der Sicherheit leidet meistens auch noch der Datenschutz, daher unterlasst das einbinden von externen Ressourcen, Bitte! Wer es unbedingt tun muss, sollte zu mindestens die externen Ressourcen hashen und diesen beim include in der Webseite mit angeben. Das ist das absolute Minimum, um euren Besuchern das minimale Gefühl zu geben, das euch eure Besucher irgendetwas etwas Wert sind. Die folgenden Schritte können für Javascript und auch für CSS Einbindungen genutzt werden.

Um einen Hash für eigene Includes zu generieren, müsst ihr wie folgt einen Aufruf absetzen. Dieser erzeugt einen Hash über die externe Ressource und verbastelt den in eine Base64 Code. Den Hash tragt ihr dann in das Attribute “integrity” ein. Die Angabe “crossorigin=‘anonymous’” verhindert die Übertragung eines Cookies an den externen Server.

curl -s https://code.jquery.com/jquery-3.1.0.min.js | \\ openssl dgst -sha384 -binary | \\ openssl base64 -A

Ausgabe

R4/ztc4ZlRqWjqIuvf6RX5yb/v90qNGx6fS48N0tRxiGkqveZETq72KgDVJCp2T

HPKP - Host Public Key Pinning

Das ist ein etwas komplexeres Thema, daher habe ich dazu einen eigenen Blogbeitrag verfasst -> HPKP - Host Public Key Pinning. Es geht bei HPKP darum, dass man von seine Zertifikate einen Hash erzeugt und diesen im Seiten-Header an den Browser ausliefert. Wenn sich nun das Zertifikat oder der Hash ändert, weil der Server kompromittiert wurde oder der Besucher einer MitM-Attacke ausgesetzt ist, wird die Verbindung vom Browser abgebrochen. Eine sehr sinnvolle Funktion !

Ein Beispiel Header aus meiner Serverkonfiguration mit zwei Hashes (Zertifikat und Backup-Zertifikat)

Header always set Public-Key-Pins: “\\ pin-sha256=“blkZK/B+V0Z1jRdyB9D5beoGZ1lG8UQC90csvz04k9A=”; \\ pin-sha256=“FNnbbJOO+WDQ3FnyaB+mVeVc6gvAtD/9TIgOwP1PMqE=”; \\ max-age=5184000;”

Referrer

Um die Privatssphäre besser zu schützen, kann man den Browser dazu auffordern, beim Aufruf einer URL bzw. Links, keinen Verweis mitzusenden woher der Aufruf kam. Das ist in er Regel eine interessante Information für Webseitenbetreiber oder eine nützliche Information für Javascripte, allerdings sollte die Privatssphäre höcher gewichtet werden. Die Option kann auch auf die eigene Domain eingeschränkt werden.

add_header Referrer-Policy “no-referrer”;

Hier sind einige Referrer-Optionen:

  • no-referrer
    Es wird beim einer Anfrage kein Referrer übergeben
  • no-referrer-when-downgrade
    Wenn die Verbindung auf HTTP gedowngraded wird, wird kein Referrer übergeben.
  • origin
    Übergibt nur den Domainnamen, nicht die gesamt URL. Dies gilt für verschlüsselte sowie unverschlüsselte Verbindungen
  • origin-when-cross-origin
    Innerhalb der Domain wird die gesamte URL übergeben, ansonsten nur der Domainname
  • same-origin
    Es wird nur innerhalb der Domain ein Referrer übergeben
  • strict-origin
    Übergibt den Referrer nur bei verschlüsselten Verbindungen
  • strict-origin-when-cross-origin
    Innerhalb der Domain wird die gesamte URL übergeben, ansonsten nur der Domainname. Das gilt allerdings nur, wenn es sich um eine verschlüsselte Verbindung handelt.
  • unsafe-url
    Übergibt auch bei nicht verschlüsselten Verbindungen innerhalb der eigenen Domain einen Referrer