Permissions-Policy: HTTP-Security-Header zum Schutz vor Feature-Missbrauch
Heutzutage verfügen Webbrowser über diverse Funktionalitäten und Schnittstellen, wie z.B. zum Zugriff auf Kamera, Mikrofon oder Standortdaten des Endgeräts eines Benutzers. In Verbindung mit XSS-Lücken könnten Angreifer, oder eingebundene 3rd-Party-Ressourcen diese Features zweckentfremden bzw. missbrauchen. Zum Schutz davor kann der HTTP-Security-Header Permissions-Policy (ursprünglich Feature-Policy) zum Einsatz kommen. Hiermit lassen sich für eine Website und deren eingebundene Ressourcen einzelne Features explizit sowie gezielt aktivieren, deaktiveren bzw. einschränken.
Näheres zur Permissions-Policy und wie ihr diese auf eurer Website bzw. in eurer Webanwendung einsetzen könnt, erfahrt ihr in diesem Beitrag.
Permissions-Policy - Beschreibung & Funktionsweise
Mit der Permissions-Policy kann dem Webbrowser mitgeteilt werden, welche Origins (Herkunft, die sich zusammengesetzt aus Schema, Hostname und Port) auf welche Features Zugriff haben. Die Policy kann auf Top-Level-Ebene global für die ganze Website als auch einzeln für eingebettete iframe
-Elemente definiert werden.
Die Permissions-Policy kann dazu verwendet werden, die Sicherheit als auch die Benutzerfreundlichkeit (Usability) der eigenen Website zu erhöhen. Im Folgenden einige Beispiele, die sich mit der Permissions-Policy umsetzen lassen:
- Abgreifen von sensiblen Daten verhindern, in dem der Zugriff auf Mikrofon, Kamera, Standort etc. des Benutzers bzw. dessen Endgerät deaktiviert wird.
- Das automatische Abspielen von Videos, die durch 3rd-Party-Ressourcen eingebunden werden, unterbinden.
- Die Verwendung von veralteten sowie benutzerunfreundlichen APIs, wie z.B. synchrone XHR-Anfragen, verhindern.
Eine Permissions-Policy setzt sich aus einer oder mehreren Policy-Direktiven zusammen. Eine solche Direktive wiederum besteht aus einem Feature-Namen und einer sogenannten "AllowList". Um dem Webbrowser die zu verwendende Policy mitzuteilen, gibt es zwei Möglichkeiten:
- per HTTP-Header
- per
allow
-Attribut beiiframe
-Elementen
Als HTTP-Header innerhalb einer HTTP-Antwort sieht das z.B. wie folgt aus:
Das o.a. Beispiel sorgt dafür, dass die aufgerufene Webseite und alle eingebundenen Ressourcen keinen Zugriff auf Kamera und Mikrofon haben. Für alle anderen Features, die nicht spezifiert wurden, gilt weiterhin die Standardeinstellung.
Beispiel - Permissions-Policy in Aktion
An einem einfachen Beispiel soll die Funktionsweise verdeutlich werden. Angenommen ihr ruft eine Webseite mit folgendem Inhalt (nur ein Ausschnitt) auf:
Ohne Einsatz der Permissions-Policy würde der Webbrowser beim Klick auf den Button das myElement
-Element im Vollbildmodus anzeigen. (Es wird vorausgesetzt, dass der Webbrowser einen FullScreen-Modus unterstützt und dieser nicht generell deaktiviert ist.)
Mithilfe der Permissions-Policy lässt sich das Fullscreen-Feature gezielt deaktivieren. Beim Klick auf den Button würde der Webbrowser den Fullscreen-Modus nicht starten:
Auf folgenden Websites könnt ihr die Permissions-Policy (Feature-Policy) und die verschiedenen unterstützten Feature-Policy-Direktiven ausprobieren:
Policy-Direktiven im Detail
Da es recht viele Policy-Direktiven gibt, beschränke ich mich im Folgenden auf die gebräuchlichsten Direktiven. Ein Liste aller Direktiven und möglichen Werte findet ihr hier: Permissions-Policy-Direktiven.
Der generelle Aufbau einer Policy-Direktive ist wie folgt: <Feature-Name> <AllowList>
.
AllowList-Werte:
*
Feature ist für die Webseite und alle eingebetteten Ressourcen unabhängig der Herkunft (Origin) verwendbar.
self
Feature ist für die Webseite und alle eingebetteten Ressourcen mit der selben Herkunft verwendbar (vgl. Same Origin Policy (SOP)).
'src'
(nur für allow
-Attribut eines iframe
relevant)
Feature ist nur für die eingebundene Webseite und deren eingebundene Ressourcen verwendbar, wenn die Herkunft der des src
-Attributs des iframe
-Elements entspricht. Für das allow
-Attribut ist das der Standardwert für ein spezifiertes Feature ohne explizite "AllowList"-Angabe.
'none'
Feature ist generell deaktiviert und damit weder von der Webseite noch eingebundenen Ressourcen verwendbar.
origin(s)
Feature ist für die Webseite und alle eingebetteten Ressourcen verwendbar, wenn die Herkunft einer der angegebenen Origins (z.B. https://beispiel.de) entspricht. Bei Angabe mehrerer Origins werden diese durch ein Leerzeichen getrennt.
Die Werte *
und 'none'
können nur alleine angegeben werden. Die anderen können durch Leerzeichen getrennt kombiniert für ein Feature definiert werden.
Jedes von der Permissions-Policy unterstützte Feature hat einen von den folgenden Werten als Standarwert:
*
self
'none'
Die Standardwerte der einzelnen Features könnt ihr auf folgender Webseite nachschlagen: Permissions-Policy-Direktiven
Feature-Namen: (wie bereits erwähnt nur einige ausgewählte)
camera
Bestimmt, inwieweit der Zugriff auf die Kamera des Benutzers gestattet ist.
geolocation
Bestimmt, inwieweit der Zugriff auf die Standortdaten-API verfügbar ist.
microphone
Bestimmt, inwieweit der Zugriff auf das Mikrofon des Benutzers gestattet ist.
usb
Bestimmt, inwieweit der Zugriff auf die WebUSB-API verfügbar ist.
Eine vollständige Liste aller unterstützten Feature findet ihr hier: unterstützte Features
HTTP-Header vs allow-Attribut eines irame-Elements
Abweichend von der ursprünglichen Feature-Policy hat der HTTP-Header bei der Permissions-Policy immer Vorrang bzw. gibt den Standard vor. Wenn der Zugriff auf die Kamera global per HTTP-Header deaktiviert ist, dann hat eine Aktivierung des Features für ein irame
per allow
-Attribut keine Auswirkung.
Details hierzu: Header and allow attribute combine differently.
Webbrowser-Unterstützung
Die gängigen Webbrowser unterstützen bereits die doch vergleichsweise noch neue Permissions-Policy. Teilweise muss diese aber auch erst noch explizit in den Webbrowser-Einstellungen aktiviert werden. Zudem muss man sagen, dass ein Großteil der Webbrowser aktuell noch die alte Feature-Policy-Syntax und nicht die neue Permissions-Policy-Syntax unterstützen. Aus diesem Grund ist es ratsam, für eine gewisse Übergangszeit beide HTTP-Header zu senden,
- Feature-Policy-Unterstützung: caniuse.com
- Permissions-Policy-Unterstützung: caniuse.com
Permissions-Policy übertragen
Um den Webserver anzuweisen, den Feature- bzw. Permissions-Policy-Header zum Client mitzusenden, ist dieser entsprechend zu konfigurieren:
Apache:
In der Konfigurationsdatei von Apache oder in der .htaccess
ist folgende Anweisung zu hinterlegen:
nginx:
Analog dazu ist für nginx in der Konfigurationsdatei Folgendes einzufügen:
Weiterhin kann die Permissions-Policy gezielt für einzelne Frames definiert werden:
Permissions-Policy von codingblatt.de
Ich verwende derzeit sowohl den Feature- als auch Permissions-Policy-Header mit folgenden Policy-Direktiven:
- camera=()
- geolocation=()
- gyroscope=()
- magnetometer
- microphone=()
- usb=()
Prinzipiell könnte ich aber auch darauf verzichten, weil ich generell weder 3rd-Party-Ressourcen noch JavaScript in meinem Blog eingebunden habe. Aus "Best-Practice"-Gründen sende ich die Header aber mit.
Weiterführende Informationen
Weiterführende Informationen zum Thema Feature-/Permissions-Policy findet ihr auf folgenden Webseiten:
- Mozilla Developer Network: Feature-Policy
- Mozilla Developer Network: Using Feature Policy
- Permissions Policy Explainer
Fazit
Als Ergänzung zur Content-Security-Policy kann die Permissions-Policy die Sicherheit eurer Website bzw. Webanwendung zusätzlich erhöhen. Nur weil z.B. euer eigener JavaScript-Code Zugriff auf die Kamera haben muss, müsst ihr nicht unbedingt einem 3rd-Party-Skript, welches ihr bspw. über ein CSN eingebunden habt, den Kamerazugriff erlauben.
Zusätzlich kann die Permissions-Policy dazu diesen, eine gute Usability zu gewährleisten. So kann z.B. sichergestellt werden, dass Videos nicht automatisch abgespielt werden, keine veralteten Grafikformate zum Einsatz kommen, keine UI-blockierenden synchronen XHR-Anfragen verwendet werden etc.