Zur Zeit wird gefiltert nach: ASP.NET
Filter zurücksetzen

23.12.2010
10:58

Es ist doch nicht Ostern, wo hat sich die Basisklasse MembershipProvider versteckt?

Sitze gerade an einer Implementierung eines benutzerdefinierten MembershipProviders. Eigentlich nicht das erste Mal – Verweis auf System.Configuration und System.Web und es kann mit der Realisierung begonnen werden, aber in .NET 4.0 gibt es eine kleine Änderung. Die Basisklasse ist nicht mehr in der Assembly System.Web. Neu wird ein Verweis auf die Assembly System.Web.ApplicationServices benötigt, damit die abstrakte Basisklasse MembershipProvider verwendet werden kann.

Eigener Request Validator in ASP.NET 4.0

Per Zufall bin ich auf eine neue Klasse in .NET 4.0 gestossen. Im März habe ich mir noch Gedanken gemacht, wie die Request Validation abgeschaltet werden kann – gut der Lösungsweg ist in der Fehlermeldung beschrieben – aber es gibt in .NET 4.0 eine neue Klasse mit dem Namen RequestValidator.

Das Problem mit der bisherigen Request Validation, es ist Best Practice diese zu deaktivieren. Unter anderem auch, weil diese bei Eingaben wie a <b bereits eine Ausnahme wirft und den Bearbeitungsprozess beendet. Zudem ist es gelegentlich eine ausdrückliche Anforderung, das einfache HTML-Elemente erfasst werden können.

Abbildung 1 Eine ungefährliche gefährliche Anfrage ;-)
Abbildung 1
Abbildung 2 Abbruch der Anwendung bei einfachen HTML
Abbildung 2

Ab ASP.NET 4.0 besteht nun die Möglichkeit, in diesen Validierungsprozess einzugreifen. Mithilfe der AntiXSS-Library kann so bspw. auf sicheres HTML geprüft werden, dieses zu erlauben und alles andere zu verwerfen und den Verarbeitungsprozess zu beenden. Der Vorteil, die Verarbeitung wird nur noch abgebrochen, wenn die Eingabe HTML enthält, das nicht durch die Prüfung der AntiXSS-Komponente kommt.

Dazu muss von der Klasse RequestValidator abgeleitet und die Methode IsValidRequestString überschreiben werden.

C#
namespace RequestValidation
{
  using System;
  using System.Web;
  using System.Web.Util;
  using Microsoft.Security.Application;

  public class SafeHtmlRequestValidator : RequestValidator
  {
    protected override bool IsValidRequestString(System.Web.HttpContext context, 
        string value, 
        RequestValidationSource requestValidationSource, 
        string collectionKey, 
        out int validationFailureIndex)
    {
      validationFailureIndex = 0;

      if (requestValidationSource == RequestValidationSource.Form)
      {
        if (IsSafeHtmlString(value))
        {
          return true;
        }
      }

      return base.IsValidRequestString(context, 
                 value, 
                 requestValidationSource, 
                 collectionKey, 
                 out validationFailureIndex);
    }

    private static bool IsSafeHtmlString(string value)
    {
      string value1 = HttpUtility.HtmlDecode(AntiXss.GetSafeHtmlFragment(value));
      return value1 == value;
    }
  }
}

Anschliessend wird dieser in der web.config mit Hilfe des httpRuntime-Elements registriert.

web.config
<system.web>
  <httpRuntime requestValidationType="RequestValidation.SafeHtmlRequestValidator"/>
---

Werden die oberen Eingaben wiederholt, so wird der Verarbeitungsprozess nicht mehr beendet. Lediglich wenn Code mit Scriptinhalten eingegeben wird, erzeugt der angepasste Validator einen Fehler und loggt diesen zusätzlich im Event-Log.

Abbildung 3 Eingabe a <b erzeugt keinen Abbruch mehr
Abbildung 3
Abbildung 4 Einfaches HTML wird akzeptiert
Abbildung 4
Abbildung 5 HTML mit Script <img src="" onerror="alert('Test')" /> wird abgebrochen
Abbildung 5
 

Wichtig dabei ist zu beachten, dass diese Variante nicht als alleiniges Sicherheitsmerkmal betrachtet werden darf. Der Angreifer ist immer im Vorteil, er wird die eine oder andere Möglichkeit finden Code einzuschleussen. Bei den frühren ASP.NET-Versionen war das mit der Out of the Box Request Validation nicht anders.

Hier habe ich einen Mittelweg zwischen User Experience und Sicherheit. Encoding von Eingaben müssen trotzdem weiterverwendet werden. Versuche sind wie bereits erwähnt im Event-Log ersichtlich, ein Vorteil zu bisherigen Best Practice: Abschlaten.

ASP.NET 4.0 - Breaking Changes

In bestehenden Umgebungen mit .NET 2.0 bis .NET 3.5 – Anwendungen wird ein Update auf .NET 4.0 ohne ausreichende Vorbereitungen sicherlich interessante Feuerwehrübungen zur Folge haben. Denn mit .NET 4.0 gibt es sie wieder, die Breaking Changes. Ein Vorteil dieser Änderungen im .NET-Framework, es gibt Einstellungsoptionen, damit das Verhalten wieder an die vorherige .NET 2.0 – Umgebung angepasst werden kann. Eine habe ich bereits hier beschrieben. Zur Zeit sind 17 solcher Änderungen gelistet. Eine Änderung, die in bestehenden Umgebungen bei unzureichender Vorbereitung sicherlich amüsant werden kann, ist der neue Default Hashing Algorithmus HMACSHA256, bisher HMACSHA1.

Wer es nicht so weit kommen lassen will, der liest sich besser hier in die Breaking Changes von ASP.NET 4.0 ein.

ASP.NET 4.0 - ValidateRequest Verhalten

Es gibt im .NET 4.0 kleine Detailverbesserungen, die auch interessante Side-Effekte zur Folge haben. Einer dieser Effekte betrifft das Attribut ValidateRequest für Webformulare, das entweder in der web.config bzw. in der Page-Direktive auf den Wert "false" gesetzt werden kann. Im Framework bis .NET 3.5 SP1 wird damit die Prüfung auf gefährlichen Code abgeschaltet. In der Regel sollte das auch nur gemacht werden, wenn die Entwickler wirklich wissen, wie sie sich vor schadhaftem Code schützen können, anderseits bedeutet die Deaktivierung mehr Fluch als Segen. Neu wird die Überprüfung viel früher in der Request Pipeline ausgeführt, um ein verbessertes Sicherheitsverhalten zu gewährleisten. Der Nachteil: Das ValidateRequest-Attribut arbeitet auf Page - Level - Ebene und die Prüfung lässt sich im Standardverhalten nicht mehr deaktivieren.

Abbildung 1: Codeausschnitt mit ValidateRequest="false" in der Direktive
Abbildung 1

Bei Eingabe eines HTML-Tags wird die Verarbeitung trotz ValidateRequest="false" abgebrochen.

Abbildung 2: ASP.NET-Fehlermeldung trotz Deaktivierung von ValidateRequest
Abbildung 2

Damit in ASP.NET 4.0 das vorherige Verhalten erzwungen werden kann, gibt es das Attribut requestValidationMode="2.0" in der httpRuntime-Konfiguration. Das setzen dieser Eigenschaft erfolgt in der web.config. Das Schöne an der Fehlermeldung in Abbildung 2, ich muss nicht lange nach dem Fehler suchen, da in der Beschreibung der Lösungsweg beschrieben ist.

Abbildung 3: Gewünschte Ausgabe
Abbildung 3

Warum deaktiviere ich ValidateRequest?

Interessant sind dabei immer die Philosophien, die hier verschiedene Interpretationen zulassen. Eine davon ist die Regel, dass eine Anwendung bei einem Fehler sofort beendet werden soll. Bei der Interaktion mit einem Anwender hat diese Regel jedoch Auswirkung auf die Benutzbarkeit. Hier heisst es wieder die Fehlerbehandlung muss robust sein und der Benutzer muss die Möglichkeit haben, seinen Fehler zu korrigieren. Mit ValidateRequest=“true“ ist diese Empfehlung nicht so einfach umsetzbar.

Was ist das Problem

Im Hintergrund verrichtet auch die Ereignisanzeige sehr gut ihre Arbeit. Treten solche Fehler auf, werden diese auch protokolliert.

Abbildung 4: Eintrag in der Ereignissanzeige "Anwendung"
Abbildung 4:

Bei Art und Häufigkeit der Fehlermeldungen können Rückschlüsse darüber gezogen werden, ob es sich um einen Eingabefehler oder gezielten Angriffsversuch handelt. Wenn diese Kontrolle deaktiviert wird, ist es empfehlenswert auch den Mehraufwand zu unternehmen, die Validierungsfehler zu protokollieren, damit diese Rückschlüsse weiterhin gezogen werden können.

18.02.2010
22:48

ASPxEditors und Page.Validate()

Die ASPxEditors von DevExpress kommen mit einem eigenen Validierungsmechanismus daher, der sich nicht in das ASP.NET – Modell einfügt. Bei bestehenden Projekten kann das sehr schnell zu einem Fallstrick werden. In der Regel bin ich daran gewöhnt mit Page.Validate zu arbeiten, damit auf der Serverseite die Eingaben validiert werden. Die ASPxEditors werden mit dieser Methode jedoch nicht überprüft, was bei Wartungsarbeiten an bestehenden Projekten schnell einen Mehraufwand zur Folge haben kann.

Die erste Variante wäre also auf das ASP.NET – Modell zurückzugreifen und die Standardvalidatoren zu nutzen. Als Beispiel nehme ich die Textbox, obwohl die ASPxComboBox bzw. das ASPxDateEdit - Control besser dafür geeignet wären.

Abbildung 1: ASPxEditor mit RequiredFieldValidator
Abbildung 1

Mit dieser Variante bettet sich die Validierung in das Standardkonzept ein. Ein Problem dabei ist der Aufwand die Elemente zu stylen. Die ASPxEditors erzeugen eine Tabelle und dadurch ist das Verhalten in der Darstellung anders. Während die Fehlermeldung bei der Standard-Textbox neben dem Eingabefeld angezeigt wird, ist es bei der ASPxTextBox unterhalb auf einer neuen Zeile.

Abbildung 2: Darstellung ohne float
Abbildung 2
Abbildung 3: ASPxTextBox im Native-Mode
Abbildung 3
Abbildung 4: Zusammengesetztes Control aus Label, Textbox und Validierung
Abbildung 4
Abbildung 4: Prüfung beider Validierungsmechanismen im Code-Behind
Abbildung 4
C#
namespace Custom.Web.UI.WebControls
{
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Web.UI;

  public class TestTextBox : DevExpress.Web.ASPxEditors.ASPxTextBox, IValidator
  {
    #region IValidator Member
    public string ErrorMessage
    {
      get
      {
        return this.ErrorText;
      }

      set
      {
        this.ErrorText = value;
      }
    }
    #endregion

    protected override void OnInit(EventArgs e)
    {
      if (this.Page != null)
      {
        this.Page.Validators.Add(this);
      }

      base.OnInit(e);
    }

    protected override void OnUnload(EventArgs e)
    {
      if (this.Page != null)
      {
        this.Page.Validators.Remove(this);
      }

      base.OnUnload(e);
    }
  }
}
Abbildung 5: ASPxTextBox mit Schnittstelle IValidate
Abbildung 5
Abbildung 6: Prüfung für Pflichteingabe
Abbildung 6
Abbildung 7: Prüfung gültige Email
Abbildung 7

Translate this page

Kategorien