ASP.NET-Sicherheit

Sichern Ihrer ASP.NET-Anwendungen

Adam Tuliper

In einer früheren Ausgabe habe ich darüber geschrieben, wie wichtig es ist, Sicherheitsmaßnahmen in Webanwendungen zu integrieren. Außerdem haben wir einige Arten von Angriffen betrachtet, zum Beispiel SQL-Einschleusung und die Manipulierung von Parametern, und ich habe erklärt, wie sie sich verhindern lassen (msdn.microsoft.com/magazine/hh580736). Um unseren Anwendungsschutz abzurunden, gehe ich in diesem Artikel auf zwei weitere gängige Angriffsformen ein, das siteübergreifende Skripting (XSS) und die websiteübergreifende Anforderungsfälschung (CSRF).

Sie fragen sich u. U., warum man nicht einfach einen herkömmlichen Sicherheitsscanner verwenden kann. Scanner können erfolgreich tief hängende Früchte aufspüren und sie eignen sich prima zum Auffinden von Anwendungs- und Systemkonfigurationsproblemen, aber sie kennen Ihre Anwendung nicht so gut wie Sie! Aus diesem Grund ist es unerlässlich, dass Sie sich mit potenziellen Sicherheitslücken befassen und sich die Zeit nehmen, Ihre Anwendungen daraufhin zu prüfen und Sicherheitsmaßnahmen in den Lebenszyklus der Softwareentwicklung einzubauen.

Siteübergreifendes Skripting

Worum handelt es sich? XSS oder siteübergreifendes Skripting (cross-site scripting, CSS) ist ein Angriff, bei dem ein Skript im Rahmen einer Browsersitzung zu böswilligen Zwecken in Code eingeschleust wird. Dies geschieht in der Regel, ohne dass der Benutzer es bemerkt. Diese Angriffsform ist unter anderem ins Rampenlicht gerückt, da ein bekanntes soziales Netzwerk betroffen war, wobei im Namen der Benutzer plötzlich ohne deren Zustimmung Inhalte veröffentlicht wurden. Wenn ein Angreifer schädliche Skripts veröffentlicht und den Browser zur Ausführung zwingen kann, werden diese Skripts bei der Sitzung eines Opfers ausgeführt, wodurch der Angreifer im Prinzip jede beliebige Aktion im DOM durchführen kann, zum Beispiel gefälschte Anmeldedialogfelder einblenden oder Cookies stehlen. Mit einem solchen Angriff kann sogar ein HTML-Keylogger auf der aktuellen Seite installiert werden, der dann ununterbrochen Eingaben aus diesem Fenster an eine Remotesite sendet.

Wie wird dies ausgenutzt? XSS wird über verschiedene Methoden ausgenutzt, die alle darauf basieren, dass die Ausgabe ohne oder mit falschem Escaping übernommen wird. Sehen wir uns einmal eine Anwendung an, die dem Benutzer eine einfache Statusmeldung anzeigen soll. Typischerweise wird diese Meldung durch die Abfragezeichenfolge in Abbildung 1 weitergegeben.

Query String Message
Abbildung 1 – Abfragezeichenfolge für die Meldung

Dieses Verfahren wird häufig nach einer Umleitung angewendet, damit dem Benutzer eine Art Statusmeldung angezeigt wird, beispielsweise die in Abbildung 1 angezeigte Meldung, dass das Profil gespeichert wurde. Die Meldung wird aus der Abfragezeichenfolge gelesen und auf der Seite angezeigt. Bei nicht HTML-codierter Ausgabe kann jeder an Stelle der Statusmeldung problemlos JavaScript einschleusen. Diese Art von Angriff gilt als reflektierter XSS-Angriff, da der Inhalt der Abfragezeichenfolge einfach auf der Seite gerendert wird. Bei einem persistenten Angriff wird das schädliche Skript gespeichert, für gewöhnlich in einer Datenbank oder einem Cookie.

In Abbildung 1 sehen Sie, dass für diesen URI ein MSG-Parameter verwendet wird. Die Webseite für diesen URI würde Code wie den folgenden enthalten, damit die Variable ohne Codierung einfach auf der Seite angezeigt werden kann:

<div class="messages"> <%=Request.QueryString["msg"]%></div>

Wenn Sie die Zeichenfolge „Profile Saved“ (Profil wurde gespeichert) durch das in Abbildung 2 angezeigte Skript ersetzen, wird im Browser basierend auf dem Skript aus der Abfragezeichenfolge die Warnungsfunktion als Popup angezeigt. Der Schlüssel zum Missbrauch im vorliegenden Fall ist die Tatsache, dass die Ergebnisse nicht HTML-codiert sind und das <script>-Tag vom Browser tatsächlich als gültiges JavaScript analysiert und ausgeführt wird. Das hatte der Entwickler ganz sicher nicht im Sinn!

Injecting Script into the URI
Abbildung 2 – Einschleusen von Skriptcode in den URI

OK, es wird also eine Warnung als Popup angezeigt. Na und? Führen wir dieses Beispiel also noch etwas weiter aus, wie in Abbildung 3 gezeigt. Wie Sie sehen, habe ich den Angriff hier aus Klarheitsgründen gekürzt. Diese Syntax stimmt nicht ganz, aber durch eine kleine Änderung würde sie zu einem echten Angriff.

Creating a Malicious Attack
Abbildung 3 – Entwerfen eines schädlichen Angriffs

Bei einem derartigen Angriff würde Benutzern ein gefälschtes Anmeldedialogfeld angezeigt, in das sie unbedarft ihre Anmeldeinformationen eingeben würden. In diesem Fall wird ein Remoteskript heruntergeladen, was normalerweise in den Standardsicherheitseinstellungen eines Browsers zugelassen wird. Diese Art Angriff kann theoretisch überall passieren, wo eine nicht codierte oder bereinigte Zeichenfolge an einen Benutzer zurückgegeben werden kann.

Abbildung 4 zeigt einen Angriff an, bei dem ein ähnliches Skript wie auf einer Entwicklungssite angezeigt wird, auf der Benutzer Kommentare zu Produkten abgeben können. Anstatt einer Produktbesprechung hat jedoch jemand schädlichen JavaScript-Code als Kommentar gespeichert. Das Skript zeigt nun jedem Benutzer dieser Webseite ein Dialogfeld zur Anmeldung an, mit dem es Anmeldeinformationen erfasst und an eine Remotesite sendet. Hierbei handelt es sich um einen persistenten XSS-Angriff. Das Skript wird in der Datenbank gespeichert und jedem Besucher der Seite angezeigt.

A Persistent XSS Attack Showing a Fake Dialog
Abbildung 4 – Ein persistenter XSS-Angriff mit gefälschtem Dialogfeld

Eine andere Art, wie XSS ausgenutzt wird, ist die Verwendung von HTML-Elementen, wenn dynamischer Text in HTML-Tags zulässig ist. Beispiel:

<img onmouseover=alert([user supplied text])>

Wenn ein Angreifer Text wie zum Beispiel „onmouseout=alert(docu­ment.cookie)“ einschleust, wird dadurch das folgende Tag im Browser erstellt, der auf den Cookie zugreift:

<img onmouseover=alert(1) onmouseout=alert(document.cookie) >

Es gibt zwar kein <script>-Tag für die potenzielle Filterung von Eingaben und auch kein Escaping, aber hier haben wir ganz und gar gültigen JavaScript-Code, mit dem ein Cookie gelesen werden kann, und zwar möglicherweise ein Authentifizierungscookie. Es gibt fallspezifische Möglichkeiten, die Sicherheit zu erhöhen, aber aufgrund dieses Risikos sollte komplett verhindert werden, dass irgendeine Benutzereingabe diesen Inlinecode hier erreicht.

Wie kann XSS verhindert werden? Die strikte Einhaltung der folgenden Regeln verhindert die meisten, wenn nicht sogar alle, XSS-Angriffe in Ihrer Anwendung:

  1. Stellen Sie sicher, dass jegliche Ausgabe HTML-codiert ist.

  2. Lassen Sie nicht zu, dass von einem Benutzer eingegebener Text in die Attributzeichenfolge eines HTML-Elements gelangen kann.

  3. Verhindern Sie die Verwendung von Internet Explorer 6 in Ihrer Anwendung, indem Sie Request.Browser wie unter msdn.microsoft.com/library/3yekbd5b beschrieben aktivieren.

  4. Seien Sie über das Verhalten der verwendeten Steuerung im Bild, und bringen Sie in Erfahrung, ob die Ausgaben HTML-codiert werden. Ist dies nicht der Fall, müssen Sie die an die Steuerung gesendeten Daten codieren.

  5. Verwenden Sie die AntiXSS-Bibliothek von Microsoft (Anti-Cross Site Scripting), und legen Sie sie als HTML-Standardencoder fest.

  6. Verwenden Sie das AntiXSS-Objekt Sanitizer (das separat heruntergeladen werden muss und weiter hinten in diesem Artikel erläutert wird) für den Aufruf von GetSafeHtml oder GetSafeHtmlFragment, bevor HTML-Daten in der Datenbank gespeichert werden. Codieren Sie die Daten erst, nachdem sie gespeichert wurden.

  7. Legen Sie bei Verwendung von Web Forms nicht „EnableRequestValidation=false“ auf Ihren Webseiten fest. Leider wird in vielen Beiträgen in Benutzergruppen im Internet dazu geraten, diese Einstellung zu deaktivieren, falls es zu Fehlern kommt. Dabei gibt es einen guten Grund für diese Einstellung. Sie stoppt beispielsweise die Anforderung, wenn die Zeichenfolge „<X“ an den Server zurückgegeben wird. Wenn Ihre Steuerelemente HTML-Code an den Server zurückgeben und die in Abbildung 5 dargestellte Fehlermeldung angezeigt wird, sollten Sie die Daten idealerweise codieren, bevor Sie sie für den Server bereitstellen. Dieses Szenario kommt bei Verwendung von WYSIWYG-Steuerelementen häufig vor, und die meisten zeitgemäßen Versionen codieren HTML-Daten ordnungsgemäß, bevor sie sie an den Server zurückgeben.

    Server Error from Unencoded HTML
    Abbildung 5 – Serverfehler aufgrund nicht codierter HTML-Daten

  8. Wenn Sie mit ASP.NET MVC 3-Anwendungen arbeiten und HTML-Daten an das Modell zurückgegeben werden müssen, sollten Sie nicht ValidateInput(false) verwenden, um die Anforderungsüberprüfung zu deaktivieren. Fügen Sie der Modelleigenschaft einfach [AllowHtml] hinzu:

public class BlogEntry
{
  public int UserId {get;set;}
  [AllowHtml]
  public string BlogText {get;set;}
}

Manche Produkte suchen nach <script> und anderen Wortkombinationen oder regulären Ausdrucksmustern in Zeichenfolgen, um XSS zu erkennen. Diese Produkte können zusätzliche Prüfungen bereitstellen, sind aber aufgrund der zahlreichen vorhandenen Angriffsvarianten nicht komplett zuverlässig. Werfen Sie einen Blick auf den XSS-Spickzettel unter ha.ckers.org/xss.html, dann sehen Sie, wie schwierig es sein kann, Angriffe zu erkennen.

Um die Lösungen zu verstehen, nehmen wir einmal an, dass ein Angreifer ein Skript eingeschleust hat, das in einer Variablen in unserer Anwendung gelandet ist. Die Einschleusung ist entweder über die Abfragezeichenfolge oder über ein Formularfeld erfolgt (siehe folgende Beispiele):

string message = Request.QueryString["msg"];

oder

string message = txtMessage.Text;

Zwar versieht ein TextBox-Steuerelement seine Ausgabe mit HTML-Codierung, aber die Text-Eigenschaft wird nicht codiert, wenn sie aus Code gelesen wird. Wenn eine dieser Codezeilen verwendet wird, enthält die Meldungsvariable die folgende Zeichenfolge:

message = "<script>alert('bip')</script>"

Auf einer Webseite, die Code wie den folgenden enthält, wird der JavaScript-Code nur deshalb im Browser des Benutzers ausgeführt, weil der folgende Text auf die Seite geschrieben wurde:

<%=message %>

In HTML codierte Ausgabe stoppt diesen Angriff in seinen Anfängen. Abbildung6 zeigt die wichtigsten Optionen zum Codieren der risikobehafteten Daten an.

Mit diesen Optionen wird die im Beispiel dargestellte Art eines Angriffs verhindert, und Sie sollten diese Optionen in Ihren Anwendungen einsetzen.

Abbildung 6 – Optionen für die HTML-Codierung

ASP.NET (MVC oder Web Forms) <%=Server.HtmlEncode(message) %>
Web Forms (ASP.NET 4-Syntax) <%: message %>
ASP.NET MVC 3 Razor @message
Datenbindung

Leider enthält die Datenbindungssyntax noch keine integrierte Codierungssyntax. Dies ist erst ab der nächsten Version von ASP.NET vorgesehen (in Form von <%#: %>). Verwenden Sie bis dahin:

<%# Server.HtmlEncode(Eval("PropertyName")) %>

Bessere Codierung

Aus der AntiXSS-Bibliothek im Microsoft.Security.Application-Namespace:

Encoder.HtmlEncode(message)

Es ist wichtig, dass Sie Ihre Steuerelemente kennen. Welche Steuerelemente versehen Daten mit HTML-Codierung und welche nicht? Ein TextBox-Steuerelement baut automatisch HTML-Code in die gerenderte Ausgabe ein, ein LiteralControl-Steuerelement hingegen nicht. Dieser Unterschied ist wichtig! Ein Textfeld, dem folgender Code zugewiesen ist...

yourTextBoxControl.Text = "Test <script>alert('bip')</script>";

...rendert den Text ordnungsgemäß auf der Seite in Form von:

Test &lt;script&gt;alert(&#39;bip&#39;)&lt;/script&gt;

Im Gegensatz dazu bewirkt

yourLiteralControl.Text = "Test <script>alert('bip')</script>";

dass eine JavaScript-Warnung auf der Seite angezeigt wird, in der auf ein XSS-Risiko hingewiesen wird. Die entsprechende Lösung lautet einfach:

yourLiteralControl.Text = Server.HtmlEncode(
    "Test <script>alert('bip')</script>");

Bei Verwendung von Datenbindung in Web Forms sieht das Ganze schon komplizierter aus. Betrachten wir das folgende Beispiel:

<asp:Repeater ID="Repeater1" runat="server">
    <ItemTemplate>
      <asp:TextBox ID="txtYourField" Text='<%# Bind("YourField") %>'
        runat="server"></asp:TextBox>
    </ItemTemplate>
  </asp:Repeater>

Ist diese Syntax anfällig? Nein. Zwar sieht der Inlinecode so aus, als könne er das Skript ausgeben oder aus den Anführungszeichen ausbrechen, aber die Codierung ist tatsächlich vorhanden. 

Und wie sieht es hier aus?

<asp:Repeater ID="Repeater2" runat="server">
  <ItemTemplate>
    <%# Eval("YourField") %>
  </ItemTemplate>
</asp:Repeater>

Ist die Syntax anfällig? Ja. Die Datenbindungssyntax <%# %> gibt keine HTML-Codierung aus. Dies ist die Fehlerbehebung:

<asp:Repeater ID="Repeater2" runat="server">
  <ItemTemplate>
    <%#Server.HtmlEncode((string)Eval("YourText"))%>
  </ItemTemplate>
</asp:Repeater>

Beachten Sie, dass es bei Verwendung von Bind in diesem Szenario nicht möglich ist, den Parameter mit Server.HtmlEncode zu umschließen. Dies liegt an der internen Kompilierung von Bind in Form von zwei separaten Aufrufen. Folgende Syntax verursacht einen Fehler:

<asp:Repeater ID="Repeater2" runat="server">
  <ItemTemplate>
    <%#Server.HtmlEncode((string)Bind("YourText"))%>
  </ItemTemplate>
</asp:Repeater>

Wenn Sie Bind verwenden und den Text nicht einem Steuerelement mit HTML-Codierung zuweisen (zum Beispiel dem TextBox-Steuerelement ), empfiehlt sich stattdessen die Verwendung von Eval, damit Sie den Aufruf von Server.HtmlEncode wie im vorherigen Beispiel angegeben umschließen können.

Dieses Konzept der Datenbindung ist in ASP.NET MVC nicht vorhanden, deshalb müssen Sie wissen, ob die HTML-Hilfsfunktionen Codierung bereitstellen. Die Hilfsfunktionen für Beschriftungen und Textfelder stellen HTML-Codierung bereit. Dieser Code

@Html.TextBox("customerName", "<script>alert('bip')</script>")
@Html.Label("<script>alert('bip')</script>")

wird beispielsweise folgendermaßen gerendert:

<input id="customerName" name="customerName" type="text"
  value="&lt;script>alert(&#39;bip&#39;)&lt;/script>" />
<label for="">&lt;script&gt;alert(&#39;bip&#39;)&lt;/script&gt;</label>

Ich habe weiter oben schon mal AntiXSS erwähnt. Die aktuelle Version der AntiXSS-Bibliothek ist 4.1 Beta 1, eine sehr schöne Neufassung, die im Hinblick auf die Sicherheit einen besseren HTML-Encoder als den von ASP.NET bereitstellt. Nicht, dass an es an Server.HtmlEncode etwas auszusetzen gäbe, aber der Schwerpunkt liegt auf Kompatibilität, nicht auf Sicherheit. AntiXSS verwendet einen anderen Ansatz zur Codierung. Weitere Informationen finden Sie unter msdn.microsoft.com/security/aa973814.

Die Betaversion ist unter bit.ly/gMcB5K verfügbar. Und schauen Sie mal nach, ob AntiXSS schon aus der Betaphase heraus ist. Wenn dies nicht der Fall ist, müssen Sie den Code herunterladen und kompilieren. Jon Galloway hat dazu einen hervorragenden Beitrag unter bit.ly/lGpKWX verfasst.

Sie können einfach den folgenden Aufruf starten, um den AntiXSS-Encoder zu verwenden:

<%@ Import Namespace="Microsoft.Security.Application" %>
...
...
<%= Encoder.HtmlEncode(plainText)%>

In ASP.NET MVC 4 wurde ein großartiges neues Feature hinzugefügt, mit dem Sie den ASP HTML-Standardencoder außer Kraft setzen und stattdessen den AntiXSS-Encoder verwenden können. Zu dem Zeitpunkt, da dies geschrieben wird, brauchen Sie Version 4.1. Da diese Version derzeit in der Betaphase ist, müssen Sie den Code herunterladen, kompilieren und der Bibliothek als Verweis auf Ihre Anwendung hinzufügen. Das Ganze sollte nicht mehr als fünf Minuten dauern. Fügen Sie dann in der Datei web.config im Abschnitt <system.web> die folgende Zeile hinzu:

<httpRuntime encoderType=
  "Microsoft.Security.Application.AntiXssEncoder, AntiXssLibrary"/>

Nun wird jeder Aufruf zur HTML-Codierung, der über eine der in Abbildung 6 aufgeführten Syntaxstrukturen erfolgt, einschließlich der Razor-Syntax für ASP.NET MVC 3, durch die AntiXSS-Bibliothek codiert. Das nenne ich austauschbar!

Diese Bibliothek enthält außerdem ein Sanitizer-Objekt, das zur HTML-Bereinigung vor der Speicherung in einer Datenbank verwendet werden kann. Dies ist äußerst hilfreich, wenn Sie Benutzern einen WYSIWYG-Editor für die Bearbeitung von HTML-Code zur Verfügung stellen. Durch diesen Aufruf wird versucht, ein Skript aus der Zeichenfolge zu entfernen:

using Microsoft.Security.Application;
...
...
string wysiwygData = "before <script>alert('bip ')</script> after ";
string cleanData = Sanitizer.GetSafeHtmlFragment(wysiwygData);
This results in the following cleaned string that can then be saved to the database:
cleanData = "before  after ";

Websiteübergreifende Anforderungsfälschung (CSRF)

Worum handelt es sich? Eine websiteübergreifende Anforderungsfälschung (cross-site request forgery, CSRF, was man wie „Sea Surf“ ausspricht) ist ein Angriff, bei dem jemand die Vertrauensstellung zwischen Ihrem Browser und einer Website ausnutzt, um in der Sitzung des nichtsahnenden Benutzers einen Befehl auszuführen. Sich diese Art Angriff ohne weitere Angaben vorzustellen, ist ein bisschen schwierig, deshalb geht's gleich ans Eingemachte.

Wie wird dies ausgenutzt? Nehmen wir an, dass John als Admin­istrator für die Website PureShoppingHeaven autorisiert ist. PureShoppingHeaven besitzt eine URL, die für den Administratorzugriff beschränkt ist und zulässt, dass über diese URL weitergegebene Informationen eine Aktion ausführen können, zum Beispiel einen neuen Benutzer zu erstellen wie in Abbildung 7 dargestellt.

Passing Information on the URL
Abbildung 7 – Übergabe von Informationen an die URL

Wenn ein Angreifer John dazu bringen kann, diese URL über eine von verschiedenen Methoden anzufordern, sendet der Browser die Anforderung an den Server, wobei alle Authentifizierungsinformationen mitgesendet werden, die sich im Cache befinden oder gerade in Johns Browser verwendet werden, einschließlich der Windows-Authentifizierung.

Hierbei handelt es sich um ein einfaches Beispiel, aber CSRF-Angriffe können wesentlich ausgeklügelter sein und zusätzlich zu GET-Anforderungen auch POST-Anforderungen für Formulare enthalten. Außerdem können sie gleichzeitig andere Angriffsformen ausnutzen, zum Beispiel XSS-Angriffe.

Nehmen wir einmal an, John besucht ein anfälliges, bereits kompromittiertes soziales Netzwerk. Möglicherweise hat ein Angreifer unter Ausnutzung einer XSS-Schwachstelle JavaScript-Code auf der Seite gespeichert, sodass nun in der Sitzung von John die URL AddUser.aspx angefordert wird. Dieses Abbild von Fiddler (fiddler2.com) zeigt nach Johns Besuch dieser Website, dass der Browser außerdem ein benutzerdefiniertes Cookie zur Websiteauthentifizierung sendet:

GET http://pureshoppingheaven/AddUser.aspx?userName=hacked&pwd=secret HTTP/1.1
Host: pureshoppingheaven
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)
Cookie: CUSTOMERAUTHCOOKIE=a465bc0b-e1e2-4052-8292-484d884229ab

Dies alles geschieht, ohne dass John davon etwas merkt. Hierbei muss man wissen, dass der Browser immer gültige Cookies oder Authentifizierungsdaten sendet. Ist Ihnen schon einmal aufgefallen, dass in Ihrem E-Mail-Client Bilder nicht standardmäßig geladen werden? Damit sollen zum Beispiel CSRF-Angriffe verhindert werden. Wenn Sie eine E-Mail im HTML-Format erhalten, die ein eingebettetes Bildtag wie das folgende enthält, wird die entsprechende URL angefordert, und der Server führt die Aktion aus, sofern Sie für diese Website authentifiziert sind:

<img src='yoursite/createuser.aspx?id=hacked&pwd=hacked' />

Falls Sie ein Administrator für „yoursite“ und bereits authentifiziert sind, sendet der Browser ohne zu Zögern die GET-Anforderungen zusammen mit jeglichen Anmeldeinformationen weiter. Für den Server ist dies eine gültige Anforderung von einem authentifizierten Benutzer, und er führt diese Anforderung aus, ohne dass Sie jemals etwas davon erfahren, da es keine gültige Bildausgabe gibt, die in Ihrem E-Mail-Client gerendert werden könnte.

Wie kann CSRF verhindert werden? Um CSRF-Angriffe zu verhindern, müssen Sie zunächst bestimmte Regeln befolgen:

  1. Stellen Sie sicher, dass eine Anforderung nicht einfach wiedergegeben werden kann, indem ein Benutzer auf einen Link für eine GET-Anforderung klickt. Die HTTP-Spezifikationen für GET-Anforderungen setzen voraus, dass GET-Anforderungen nur zum Abrufen verwendet werden und nicht für Statusänderungen.
  2. Stellen Sie sicher, dass eine Anforderung nicht wiedergegeben werden kann, indem ein Angreifer mithilfe von JavaScript eine POST-Anforderung für Formulare nachahmt.
  3. Verhindern Sie, dass Aktionen aufgrund von GET-Anforderungen ausgeführt werden. Lassen Sie zum Beispiel nicht zu, dass Datensätze über eine URL erstellt oder gelöscht werden. Dazu sollte idealerweise irgendeine Interaktion von Seiten des Benutzers erforderlich sein. Zwar werden dadurch keine ausgereifteren formularbasierten Angriffe verhindert, aber es wird ein Großteil von simplen Angriffen vermieden, wie ein Angriff aus dem Beispiel mit dem E-Mail-Bild, und es wird verhindert, dass einfache Links auf von XSS betroffenen Websites eingebettet werden.

Um Angriffe über Web Forms zu verhindern, muss man anders vorgehen als bei ASP.NET MVC. Bei Web Forms kann das MAC-Attribut ViewState signiert werden. Dies hilft beim Schutz gegen Fälschungen, sofern Sie EnableViewStateMac nicht auf false festlegen. Außerdem sollten Sie Ihr ViewState-Attribut für die aktuelle Benutzersitzung signieren und verhindern, dass es in einer Abfragezeichenfolge weitergegeben wird. Auf diese Weise werden so genannte One-Click-Angriffe abgeblockt (siehe Abbildung 8).

Abbildung 8 – Verhindern eines One-Click-Angriffs

void Page_Init(object sender, EventArgs e)
{
  if (Session.IsNewSession)
  {
    // Force session to be created;
    // otherwise the session ID changes on every request.
    Session["ForceSession"] = DateTime.Now;
  }
  // 'Sign' the viewstate with the current session.
  this.ViewStateUserKey = Session.SessionID;
  if (Page.EnableViewState)
  {
    // Make sure ViewState wasn't passed on the querystring.
    // This helps prevent one-click attacks.
    if (!string.IsNullOrEmpty(Request.Params["__VIEWSTATE"]) &&
      string.IsNullOrEmpty(Request.Form["__VIEWSTATE"]))
    {
      throw new Exception("Viewstate existed, but not on the form.");
    }
  }
}

Ich weise hier deshalb einen zufällig generierten Sitzungswert zu, um sicherzustellen, dass die Sitzung hergestellt wird. Sie können eine beliebige temporäre Sitzungskennung verwenden, aber die Kennung für die ASP.NET-Sitzung ändert sich mit jeder Anforderung, bis Sie letztendlich eine Sitzung erstellen. Hier soll die Sitzungskennung nicht mit jeder Anforderung geändert werden, deshalb muss sie festgelegt werden, indem man eine neue Sitzung erstellt.

ASP.NET MVC enthält eine eigene Gruppe interner Hilfsfunktionen für den Schutz gegen CSRF-Angriffe. Dabei werden eindeutige Token verwendet, die mit der Anforderung übergeben werden. Diese Hilfsfunktionen verwenden neben einem erforderlichen ausgeblendeten Formularfeld auch einen Cookiewert, wodurch das Fälschen einer Anforderung um einiges erschwert wird. Diese Schutzmaßnahmen sind leicht zu implementieren, und sie sind ein absolutes Muss für Ihre Anwendungen! Gehen Sie folgendermaßen vor, um in Ihrer Ansicht @Html.AntiForgery­Token() innerhalb Ihrer <form>-Syntax hinzuzufügen:

@using (Html.BeginForm())
{
  @Html.AntiForgeryToken();
  @Html.EditorForModel();
  <input type="submit" value="Submit" />
}
Decorate any controllers that accept post data with the [Validate­AntiForgeryToken], like so:
[HttpPost]
[ValidateAntiForgeryToken()]
public ActionResult Index(User user)
{
  ...
}

Erläuterungen zu Sicherheitslücken

In diesem Artikel haben wir uns mit siteübergreifendem Skripting (XSS) und der websiteübergreifenden Anforderungsfälschung (CSRF) beschäftigt, zwei geläufigen Arten von Hackingangriffen auf Webanwendungen. Zusammen mit den beiden Angriffsarten, die letzten Monat erläutert wurden, SQL-Einschleusung und Manipulierung von Parametern, besitzen Sie nun gute Kenntnisse in Bezug auf Sicherheitslücken bei Anwendungen.

Außerdem haben Sie gesehen, wie einfach Sie Sicherheitsmaßnahmen in Ihre Anwendungen integrieren können, um Schutz gegen einige der geläufigsten Angriffsarten zu bieten. Wenn Sie schon Sicherheitsmaßnahmen in Ihren Lebenszyklus der Softwareentwicklung integriert haben, zolle ich Ihnen Respekt. War das bislang nicht der Fall, ist es jetzt an der Zeit, damit anzufangen! Sie können Ihre vorhandenen Anwendungen seiten- oder modulweise überwachen und in den meisten Fällen ganz einfach umgestalten. Und vergessen Sie nicht, Ihre Anwendungen mit SSL zu schützen, um Sniffer-Angriffe auf Ihre Anmeldeinformationen zu verhindern. Denken Sie vor, während und nach der Entwicklungsphase immer an die Sicherheit.

Adam Tuliper ist Softwarearchitekt bei Cegedim und entwickelt seit mehr als 20 Jahren Software. Er ist nationaler INETA Community Speaker und hält regelmäßig Vorträge auf Konferenzen und in .NET-Benutzergruppen. Sie finden ihn auf Twitter unter twitter.com/AdamTuliper. Seinen Blog finden Sie unter completedevelopment.blogspot.com, und seine neue Website heißt secure-coding.com. Weitere ausführliche Informationen zum Schutz vor Hacking für Ihre ASP.NET-Anwendungen finden Sie in seiner bald erscheinenden Videoreihe Pluralsight.

Unser Dank gilt dem folgenden technischen Experten für die Durchsicht dieses Artikels: Brad Dorrans