Web Security für alle: X-Frame-Options
Published on Friday, September 23, 2016 4:00:00 AM UTC in Programming & Security
Ich erinnere mich an eine Zeit, in der es ein Katz- und Maus-Spiel gab zwischen Seitenbetreibern und fragwürdigen "Diensten" im Internet, die fremde Seiten in iFrames eingebettet angezeigt haben - man sprach von "frame busting"-Techniken, um dieses ungebetene Einbetten der eigenen Inhalte loszuwerden. Irgendwann wurde erkannt, dass dieses Einbetten nicht nur inhaltliche Aspekte hat, sondern auch ein ernsthaftes Sicherheitsproblem darstellt: Clickjacking kann dazu genutzt werden, Mausklicks und Tastatureingaben unbemerkt und ungewollt umzuleiten, etwa um Passwörter und ähnliche sensible Daten zu stehlen. Vorhandene Cheat-Sheets zu dem Thema zeigen schon, wie komplex dieses scheinbar einfache Thema ist, und wie wirkungslos viele Versuche, sich dagegen zu wehren.
Die heutzutage empfohlene Variante ist das Senden eines http-Headers namens X-Frame-Options, idealerweise mit dem Hinweis, dass das Einbetten der Seite nicht gestattet ist. Dann übernimmt der Browser die Verantwortung, dass die Seite nicht in Frames oder als Object eingebunden wird, und man muss nicht fehleranfällige eigene Wege per Skripts o.ä. wählen. Die Implementierung ist denkbar einfach.
Umsetzung des X-Frame-Options-Headers in ASP.NET Core
Als Grundlage dient die Basisimplementierung vom letzten Mal. Zunächst einmal gilt es, die Konfiguration und die zugehörigen Klassen zu erweitern:
"SecurityHeadersOptions": {
"XFrameOptions": {
"IsEnabled": true,
"Directive": "DENY"
}
}
public class SecurityHeadersOptions
{
public XFrameOptions XFrame { get; set; }
public class XFrameOptions
{
public bool IsEnabled { get; set; }
public XFrameOptionsDirective Directive { get; set; }
public enum XFrameOptionsDirective
{
DENY,
SAMEORIGIN
}
}
// ...
}
Da der dritte mögliche Wert für die Direktive (ALLOW-FROM
) deprecated ist und künftig falls gewünscht durch den Content-Security-Policy-Header abgebildet werden soll (zu dem Header später mehr), habe ich diese Option gar nicht erst abgebildet. Im Code-Beispiel sieht man übrigens auch, dass .NET Core die Abbildung von Strings (in der appsettings.json) auf die zugehörigen Enum-Werte problemlos meistert, wenn die Konfiguration geladen wird.
Der eigentliche Header wird dann wieder in der Middleware geschrieben, etwa so:
private Task ApplyHeaders(object state)
{
var context = (HttpContext)state;
ApplyHstsHeader(context);
ApplyXFrameOptionsHeader(context); // <= new and shiny header :)
return Task.CompletedTask;
}
private void ApplyXFrameOptionsHeader(HttpContext context)
{
var xFrameOptions = _options.XFrame;
if (!xFrameOptions.IsEnabled)
{
return;
}
context.Response.Headers["X-Frame-Options"] = xFrameOptions.Directive.ToString();
}
// ...
Und das war's in diesem Fall schon. Mit dem Wert DENY
wird das Einbetten der eigenen Seite untersagt, mit SAMEORIGIN
könnte man zumindest noch das Einbetten in andere eigene Seiten erlauben. Mehr Details zur Bedeutung und Handhabung des Headers gibt es wie immer bei Mozilla.
Resultat
Auch diese Verbesserung lässt die eigene Seite wieder in der Bewertungsleiter klettern:
Es wird.
Tags: ASP.NET Core · Clickjacking