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.
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.
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.
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.
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.
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.
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 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.config
Datei:
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.
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.
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.
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: