Verhindern von XSS in ASP.NET

Viele Website-Sicherheitsprobleme entstehen durch zu hohes Vertrauen in den Benutzer. Die meisten Benutzer Ihrer Webanwendung werden nur das tun, was sie tun müssen, ein neugieriger oder böswilliger Benutzer möchte häufig die Grenzen des Zugriffs schieben. An diesen Rändern treten häufig Sicherheitslücken in Ihrer Anwendung auf. Ich habe bereits in ASP.NET-Apps über das Verhindern zweier allgemeiner Arten von Sicherheitsanfälligkeiten, SQL Injection und Cross Site Request Forgery, geschrieben. In diesem Artikel wird das Verhindern von Cross Site Scripting, einer dritten häufigen Art von Sicherheitsanfälligkeit in Websites, beschrieben.

Ein modernes Framework trägt zwar wesentlich dazu bei, diese Angriffe zu erschweren, aber ich glaube, wir sollten zunächst ein Verständnis dafür haben, wie eine App funktioniert ist anfällig für einen Angriff. Sehen wir uns zunächst an, was Cross Site Scripting ist und wie es genutzt werden kann.

Was ist Cross Site Scripting?

Cross Site Scripting (oft als XSS abgekürzt) ermöglicht das Einfügen von schädlichen Skripts in eine ansonsten vertrauenswürdige Website. Diese Injektion erfolgt ohne Wissen des Benutzers. Das eingespritzte Skript wird so ausgeführt, als stamme es von der ursprünglichen Website. Das schädliche Skript kann somit auf alle Ressourcen der gehosteten Website zugreifen, auf die der Benutzer Zugriff hätte, wie z. B. Cookies oder Sitzungstoken.

Die Eröffnung eines Cross-Site-Scripting-Angriffs erfolgt, wenn eine Webanwendung Eingaben von Benutzern oder externen Ressourcen anzeigt, ohne sie ordnungsgemäß zu überprüfen oder zu kodieren. Bei den meisten Cross-Site-Scripting-Angriffen versucht der Angreifer, JavaScript in die Webseite eines vertrauenswürdigen Servers einzufügen. Der Angreifer kann auch versuchen, HTML, Flash oder andere Elemente einzufügen, die vom Browser ausgeführt werden. Unabhängig vom Skript bleibt es das Ziel, dass der Browser den Code des Angreifers ausführt.

Ein anhaltender XSS-Angriff

Es gibt drei Kategorien von Cross-Site-Scripting-Angriffen, unterteilt nach Injektionsmethode und Methode zur Verhinderung des Angriffs. Bei der ersten Angriffsart wird das Skript permanent auf dem Zielserver gespeichert und wird daher als permanenter Cross-Site-Scripting-Angriff bezeichnet. Bei diesem Angriff wird versucht, das schädliche Skript in etwas einzubetten, z. B. einen in einer Datenbank gespeicherten Forumsbeitrag oder ein scheinbar harmloses Feld, z. B. die Homepage eines Benutzers der Datenbank. Wenn das Skript beibehalten wird, wird jeder Besucher der Website, der den Beitrag, die Nachricht oder ein anderweitig gefährdetes Element anzeigt, zu einem potenziellen Opfer des Angriffs.

Angreifer, die diese Art von Angriff versuchen, zielen im Allgemeinen auf Kommentarfelder, Foren, soziale Medien und andere Felder, in denen etwas willkürliche Eingaben des Endbenutzers erwartet werden und ein normaler Teil der Anwendung sind. Der Angreifer kann das Skript in einen ansonsten gültigen Teil einer Konversation in ein Forum aufnehmen. Jedes Mal, wenn jemand den Beitrag anzeigt, wird das Skript ausgeführt.

Ein reflektierter XSS-Angriff

Bei der zweiten Art des Cross-Site-Scripting-Angriffs, der als reflektiertes Cross-Site-Scripting bezeichnet wird, übermittelt der Angreifer das injizierte Skript an die anfällige Site, sodass es sofort an den Benutzer zurückgegeben wird. Übliche Methoden hierfür sind Zielseiten, auf denen Benutzereingaben Bestandteil der Ausgabe einer Seite werden. Eine Suchseite kann dem Benutzer die Suchbegriffe anzeigen und könnte einen Anlass für diesen Angriff bieten. Das in die Eingabe eines Benutzers eingegebene Skript sollte niemals von der Webanwendung gespeichert werden.

DOM-basierte Angriffe

Der dritte Cross Site Scripting-Angriff erfolgt vollständig im Browser. Die Angriffe funktionieren durch Manipulieren des internen Modells der Webseite im Browser, das als DOM bezeichnet wird, und werden als DOM-basierte Angriffe bezeichnet. Dies wiederum ermöglicht es dem Angreifer, schädlichen Code auszuführen, der vom Server zurückgegebene Code wird jedoch von der Webseite in ausführbares JavaScript umgewandelt.

Letztendlich handelt es sich bei einem Cross Site Scripting-Angriff um einen Cross Site Scripting-Angriff, unabhängig davon, wie er bereitgestellt wird. Da der eingefügte Code von einem ansonsten vertrauenswürdigen Server stammt, kann er häufig unter den Berechtigungen der Site ausgeführt werden. Es kann daher so aussehen, als wäre es ein nativer Code auf der Website. 

Ein erfolgreicher Cross Site Scripting-Angriff kann den Zugriff auf Cookies auf einer Webseite ermöglichen. Diese Cookies können vertrauliche Informationen enthalten, einschließlich Sitzungskennungen, die es dem Angreifer ermöglichen, den angegriffenen Benutzer als Identität auszugeben. Der Angriff kann auch den HTML-Inhalt einer Seite ändern, um ein falsches Anmeldeformular anzuzeigen und die Anmeldeinformationen des Benutzers zu stehlen. Der Angreifer kann den gesamten Inhalt der Seite prüfen und senden, um sensible Informationen wie Kontonummern zu erfassen. Bei einem fortgeschritteneren Angriff könnte ein Schlüssellogger installiert werden, der alle auf der Webseite eingegebenen Informationen an einen Angreifer sendet.

Schutz vor Cross Site Scripting-Angriffen

Um das Cross Site Scripting zu mildern, müssen Sie keiner Eingabe eines Benutzers oder einer anderen externen Quelle vertrauen. Die Webanwendung muss diese Daten unabhängig von der Quelle als potenziell gefährlich behandeln. Schauen wir uns einige Methoden an, die spezifisch für ASP.NET sind, um diese Angriffe mithilfe von Komponenten, die in das Framework integriert sind, und frei verfügbaren Bibliotheken zu verhindern.

Alle Eingaben überprüfen

Die Webanwendung sollte alle Eingaben in die Anwendung überprüfen, bevor sie verwendet werden. Genau wie bei anderen Injektionsangriffen wie SQL Injection. Die Anwendung validiert diese Eingabe vorzugsweise gegen eine weiße Liste akzeptabler Werte. Bei der Überprüfung werden unerwartete Komponenten der Eingabe durch einen codierten Wert entfernt oder ersetzt. Eine Blacklisting-Methode, die nur eine Liste bekannter unerwünschter Zeichen entfernt, kann verwendet werden, ist jedoch anfälliger für neue Angriffsmethoden.

Wenn wir wissen, dass ein Wert immer eine Ganzzahl sein sollte, können Sie die Eingabe mit einem Code wie dem folgenden überprüfen:

int memberId; if (! int.TryParse (externalValue, out memberId)) return RedirectToAction ("InputError");  

Wenn das Framework das zuvor abgerufene nicht analysieren kann externalValue Als Ganzzahl wird der Code auf eine Seite umgeleitet, die einen Fehler anzeigen würde. Ansonsten wissen wir das Mitgliedsnummer enthält einen ganzzahligen Wert. Dieser Prozess funktioniert auch mit anderen Basistypen. Einige häufigere Typen bieten auch Methoden zur Validierung der Informationen. Das Netz Uri Klasse enthält eine Methode IsWellFormedUriString das kann eine URL überprüfen. Dies würde die Überprüfung ermöglichen, dass der Homepageeintrag eines Benutzers vor der Anzeige eine gültige URL enthält.

var userHomePage = userRecord ["Homepage"]; if (! Uri.IsWellFormedUriString (newUrl, UriKind.Absolute)) Model.homepage = "none";  else Model.homepage = Html.Encode (userHomePage);  

Andere und komplexere Datentypen erfordern eine komplexere Validierung. Bei der Überprüfung eines Kreditkartennummernfelds können alle Zeichen in der Zeichenfolge, die keine Ziffern sind, entfernt werden. Die Überprüfung komplexerer Zeichenfolgen kann reguläre Ausdrücke erfordern. Die Validierung einer Klasse kann auch komplexere Prüfungen erfordern.

ASP.NET-Anforderungsüberprüfung

ASP.NET bietet effektiven Schutz vor reflektierten Angriffen mithilfe der Anforderungsüberprüfung. Wenn ASP.NET Markup oder Code in einer Anforderung erkennt, wird eine Ausnahme "potenziell gefährlicher Wert wurde erkannt" ausgelöst und die Verarbeitung der Anforderung beendet.

Es ist zwar wertvoll, es gibt jedoch Zeiten, in denen Sie diese Werte in einer Anforderung zulassen müssen. Ein allgemeines Beispiel ist die Ermöglichung der Rich-Text-Eingabe in einem Formular. In diesen Fällen wird die Validierung von Anforderungen leider zu oft für die gesamte Site deaktiviert. Eine bessere Lösung deaktiviert diese Validierung nur, wenn dies erforderlich ist. In früheren Versionen von ASP.NET hinzufügen validateRequest = "false" zum Seite Die Direktive in Webforms würde die Validierung für eine Seite deaktivieren. In ASP.NET MVC das Hinzufügen von [ValidateInput (false)] Attribut für eine Controller-Aktion deaktiviert die Validierung für diese Aktion, während Sie die [AllowHtml] Attribut deaktiviert die Validierung für ein Feld.

ASP.NET 4.0 hat die Anforderungsüberprüfung auf verschiedene Weise geändert. Diese und spätere Versionen des Frameworks werden früh in der HTTP-Anforderung validiert. Die Überprüfung gilt auch für alle ASP.NET-Anforderungen und nicht nur für diese .aspx Seitenanfragen. Dies umfasst auch benutzerdefinierte HTTP-Module. Seiten, die auf das ursprüngliche Verhalten angewiesen sind, können durch Festlegen von die ältere Methode wiederherstellen requestValidationMode Attribut in der web.config Datei zu Version 2,0.

 

Noch besser ist es, dies nur für Seiten zu deaktivieren, wo dies erforderlich ist. Verwenden Sie dazu die Syntax in web.configDatei:

     

ASP.NET 4.5 fügte die Möglichkeit hinzu, die Validierung zu verschieben, bis die Daten abgerufen wurden. Einstellen der requestValidationMode Attribut in Ihrem web.config Datei zu Version 4,5 aktiviert dieses neue Verhalten.

 

ASP.NET 4.5 fügte auch das hinzu HttpRequest.Unvalidiert Eigentum. Die Verwendung dieser Eigenschaft ermöglicht bei Bedarf einen einfacheren Zugriff auf den nicht validierten Formularwert. Durch die Kombination der verzögerten Validierung und der Nicht validiert können Sie bei Bedarf auf die nicht validierten Werte zugreifen, andere Formulareingaben jedoch schützen.

HTML kodieren

Bevor Sie externe Daten auf einer Webseite anzeigen, sollte Ihr HTML-Code so codiert sein, dass er vom Browser nicht verarbeitet wird. Nehmen Sie als Beispiel eine ASP.NET-Seite, die geschrieben wird, damit eine Nachricht zur Anzeige weitergegeben werden kann, z. B. eine Statusaktualisierung. Eine Anwendung könnte diese Seite verwenden, um dem Benutzer anzuzeigen, dass sein Konto fehlerfrei erstellt wurde. Die URL für diese Seite sieht normalerweise ähnlich aus http: // appname / placeorder / Account + erstellt. Die resultierende Seite zeigt dem Benutzer die Nachricht mit einem Feld an, zum Beispiel:

<%= Html.Label("Message", Model.message) %> 

… Und zeigt als:

Wenn wir den URL-Aufruf in ändern http: / appname / placeorder /, Wir bekommen jetzt etwas anderes.

Das Skript könnte natürlich alles sein und nicht nur die harmlose Alarmbox, die hier angezeigt wird. Request Validation würde die obigen Beispiele einfangen und vor der Anzeige eine Ausnahme zurückgeben. Wenn diese Option deaktiviert ist, verhindert das Kodieren der Ausgabe den Angriff.

Mit ASP.NET können Daten leicht verschlüsselt werden, um Angriffe zu verhindern. Frühe Versionen von MVC, die die Webform-Syntax verwenden, enthielten häufig Code wie diesen, der kein HTML-Code enthielt.

<%= status >

Sie mussten die Ausgabe manuell codieren, sodass HTML in ein Anzeigeformat konvertiert werden konnte. Also die < Zeichen wird zur Zeichenfolge <. Das Html.Encode Funktion liefert diese Konvertierung. Die sicherere Form von Code wird somit zu:

<%= Html.Encode(status) >

ASP.NET MVC führte später eine Syntax ein, um dies in einem Schritt durch Ersetzen durchzuführen <= mit <: So kann der Code verkürzt werden auf:

<%: status >

Bei Verwendung der Razor-Ansichts-Engine ist die gesamte Ausgabe HTML-codiert, sofern Sie nicht ausdrücklich eine Methode verwenden, um sie nicht zu codieren. In Razor wird der Code, der dem obigen entspricht, zu:

@Status

Razor verarbeitet automatisch die HTML-Codierung der Zeichenfolge Status enthält. Wenn Sie die Rohdaten rendern müssen, können Sie das verwenden HTML.Raw () Methode. Um das Ergebnis ohne Codierung anzuzeigen, können wir Folgendes verwenden:

@ Html.Raw (Status)

In diesem Beispiel würde der obige Code unsere Anwendung anfällig machen nochmal. Es gibt also einige Umstände, unter denen Sie die Ausgabe nicht kodieren sollten. Wenn Sie diese Funktion für ein Feld deaktivieren, müssen Sie besonders darauf achten, dass die Daten vor der Anzeige bereinigt werden. Glücklicherweise gibt es eine Bibliothek, die dabei hilft, und Sie können Ihre Anwendung außerdem vor Cross-Site-Scripting schützen.

AntiXSS-Bibliothek

Wenn Sie eine ASP.NET-Anwendung schreiben, sollten Sie die AntiXSS-Bibliothek für ASP.NET verwenden. Auf der Projektwebsite bietet "AntiXSS eine Vielzahl von Kodierungsfunktionen für Benutzereingaben, einschließlich HTML, HTML-Attributen, XML, CSS und JavaScript."

Die Bibliothek enthält Methoden, die darauf abzielen, externe Daten basierend auf der beabsichtigten Verwendung dieser Daten zu desinfizieren. Diese Methoden verwenden den bevorzugten Whitelist-Ansatz. Das bedeutet, dass verschlüsselte Daten, die für ein HTML-Attribut bestimmt sind, so bereinigt werden können, dass sie nur gültige Daten für ein HTML-Attribut enthalten. Das traditionelle ASP.NET HtmlEncode Methoden verwenden den Blacklist-Ansatz, der nur bestimmte, potenziell gefährliche Zeichen codiert.

Microsoft hat damit begonnen, Kernroutinen aus dieser Bibliothek in ASP.NET 4.5 in eine neue aufzunehmen System.Web.Security.AntiXss Namespace. Sie können das Framework auch so einrichten, dass diese AntiXSS-Methoden anstelle der integrierten Codierungsroutinen verwendet werden. Sie tun dies, indem Sie die encoderType Attribut von httpRuntime in dem web.config Datei für die Anwendung:

 

Wenn Ihre Anwendung eine signifikante Anzeige externer Daten durchführt, trägt die Verwendung von AntiXSS dazu bei, Ihre Anwendung vor Cross-Site-Scripting zu schützen. Wenn Sie ASP.NET 4.5 verwenden, können Sie durch Ändern der Anwendung zur Verwendung der neuen AntiXSS-Methoden für die Standardkodierung Ihre Webanwendung noch mehr schützen.

In Summe

Cross-Site-Scripting zu verhindern, ist schwieriger als es zunächst scheint. OWASP listet über 80 Vektoren auf, die mit Cross-Site-Scripting-Angriffen angegriffen werden können. Diese Organisation weist diese Schwachstellen auch als dritte in ihrer Liste der zehn häufigsten Schwachstellen auf.

Wenn Sie nicht sicherstellen, dass alle externen Daten, die in Ihre Anwendung einbezogen werden, ordnungsgemäß geschützt werden, oder wenn Sie Eingaben nicht vor dem Platzieren auf einer Ausgabeseite überprüfen, bleibt Ihre Webanwendung für Cross Site Scripting anfällig. In ASP.NET kann dies folgendermaßen erfolgen:

  1. Überprüfen Sie alle externen Eingaben für Ihre Anwendung, bevor Sie sie auf einer Webseite anzeigen.
  2. Verwenden Sie Request Validation überall dort, wo Ihre Anwendung sie nicht ausdrücklich deaktivieren muss, z. B. ein Formular, das Rich-HTML-Eingaben zulässt. Wenn Sie nicht validierte Informationen zulassen müssen, lassen Sie die Validierung an allen anderen Stellen in Ihrer Anwendung.
  3. Kodieren Sie HTML-Code, bevor Sie externe Daten auf einer Webseite anzeigen
  4. Verwenden Sie die in ASP.NET 4.5 enthaltenen AntiXSS-basierten Methoden und die AntiXSS-Bibliothek für ältere Versionen von ASP.NET.