Leider gibt es immer mal wieder Applikationen, welche sich nicht an Best Practices im Webdesign orientieren und es unter Umständen nötig machen ein anderes System anzupassen so das sie funktionieren. Kürzlich hatte ich so einen Fall, bei dem ein SAP System welches die Authentisierung via ADFS (mit dem SAML Protkoll) durchführt, die Login Seite von ADFS als iFrame eingebettet hat. In diesem Beitrag zeige ich eine Möglichkeit, wie das einbetten nur für gewisse URLs zugelassen werden kann.

Seit ADFS 2019 (und auch als Backport in ADFS 2016 hinzugefügt) werden diverse HTML Security Header der Antwort an den Client hinzugefügt. Darunter befindet sich auch der Header X-Frame-Options welcher hilft ein Clickjacking Versuch zu unterbinden. Standartmässig ist dieser Header von ADFS auf deny gesetzt. Gemäss der Dokumentation von Microsoft soll der Header entfernt werden können (wovon natürlich dringend abzuraten ist!) aber ein Blick in die Entwickler Konsole von Edge zeigt mir, dass ADFS in diesem Fall den Default mit X-Frame-Options=deny schickt anstatt wie erwartet den Header gar nicht zu senden.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
[vfed01]: PS C:\Users\pri\Documents> Get-AdfsResponseHeaders
 ResponseHeaders           : {[Strict-Transport-Security, max-age = 31536000], [X-Content-Type-Options, nosniff], [X-XSS-Protection, 1; mode=block]}
 ResponseHeadersEnabled    : True
 PublicKeyPinningEnabled   : False
 PublicKeyPrimary          :
 PublicKeySecondary        :
 PublicKeyPinningReportUri :
 AdditionalPublicKeys      : {}
 CORSEnabled               : False
 CORSTrustedOrigins        : {}

edge_frame_options.png

Um mögliche Lösungen zu testen habe ich eine kleine statische Seite mit ADFS als iFrame eingebettet erstellt.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My Super App</title>
</head>
<body>
    <iframe src="https://adfs.irbe.ch/adfs/ls/idpinitiatedsignon" height=1024 width=768></iframe>
</body>
</html>

Eine Möglichkeit wäre mit dem Header X-Frame-Options allow-from https:// goapp.dockernet.ch die Einbettung zu erlauben. Dies hat allerdings zwei Nachteile, zum Ersten ist die Direktive allow-from von vielen Browsern nicht unterstützt X-Frame-Options – HTTP | MDN (mozilla.org) und zum Zweiten kann nur eine URL erlaubt werden, was also wenn mehrere Applikationen dieses Bedürfnis haben?

Es gibt einen anderen Header Content-Security-Policy Content Security Policy (CSP) – HTTP | MDN (mozilla.org), mit dem verschiedene sicherheitsbezogene Inhalt Einstellungen vorgenommen werden können. Darunter fällt auch die frame-ancestors Direktive, mit der verschiedene URLs und sogar mit Wildcard (*) angegeben werden können CSP: frame-ancestors – HTTP | MDN (mozilla.org). Dieser Header wird von allen gängigen Browser ausser dem Internet Explorer unterstützt. Also ein neuer Versuch mit diesem Header.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
[vfed01]: PS C:\Users\pri\Documents> Set-AdfsResponseHeaders -SetHeaderName Content-Security-Policy -SetHeaderValue "frame-ancestors 'self' *.dockernet.ch"
 [vfed01]: PS C:\Users\pri\Documents> Get-AdfsResponseHeaders
 ResponseHeaders           : {[Strict-Transport-Security, max-age = 31536000], [X-Content-Type-Options, nosniff], [X-XSS-Protection, 1; mode=block], [Content-Security-Policy, frame-ancestors 'self' *.dockernet.ch]}
 ResponseHeadersEnabled    : True
 PublicKeyPinningEnabled   : False
 PublicKeyPrimary          :
 PublicKeySecondary        :
 PublicKeyPinningReportUri :
 AdditionalPublicKeys      : {}
 CORSEnabled               : False
 CORSTrustedOrigins        : {}

edge_csp.png

Und siehe da die Einbettung klappt ohne Probleme. In der Entwickler Konsole wird der Hinweis ausgegeben, dass die Content-Security-Policy den X-Frame-Options Header übersteuert wie in der CSP Dokumentation auf Mozilla Developer erwähnt. Mit dem gesetzten Header habe ich die Einbettung für alle Subdomains unter dockernet.ch erlaubt, die Liste kann für weitere Domains ergänzt werden.