Doppelte Escape-Sequenz innerhalb einer URL: Das Anforderungsfiltermodul ist so konfiguriert, dass eine Anforderung abgelehnt wird, die eine doppelte Escape-Sequenz enthält


86

In meiner ASP.NET MVC-Anwendung versuche ich, eine URL wie die folgende zu implementieren:

/ product / tags / für + Familien

Wenn ich versuche, meine Anwendung mit Standardkonfigurationen auszuführen, wird folgende Meldung mit dem 404.11-Antwortcode angezeigt:

HTTP-Fehler 404.11 - Nicht gefunden

Das Anforderungsfiltermodul ist so konfiguriert, dass eine Anforderung abgelehnt wird, die eine doppelte Escape-Sequenz enthält.

Ich kann diesen Fehler umgehen, indem ich den folgenden Code in meine web.config implementiere:

  <system.webServer>
    <security>
      <requestFiltering allowDoubleEscaping="true" />
    </security>
  </system.webServer>

Also, jetzt bekomme ich keine 404.11.

Was ich mich frage, ist, welche Art von Sicherheitslücken ich mit dieser Implementierung öffne.

Übrigens ist meine Anwendung unter .Net Framework 4.0und läuft unter IIS 7.5.


Ist es möglich, /product/tags/for%20familiesstattdessen die gewünschte Ressource zu erreichen ? Dann haben Sie eine Problemumgehung für IDs, die Leerzeichen enthalten. Oder bin ich hier komplett weg?
Anders Tornblad

@atornblad ein bisschen aus, denke ich. Meine Frage: Ich frage mich, welche Art von Sicherheitslücken ich mit dieser Implementierung öffne.
Tugberk

5
IIS setzt auf das Zeichen "+", das das Standardverhalten von Microsoft ist.
Todd Shelton

Antworten:


56

Die Sicherheitslücken, die Sie möglicherweise öffnen, haben mit der Code-Injection zu tun - HTML-Injection, JavaScript-Injection oder SQL-Injection.

Die Standardeinstellungen schützen Sie vor Angriffen, indem Sie nicht zulassen, dass gängige Injektionsstrategien funktionieren. Je mehr Standardsicherheit Sie entfernen, desto mehr müssen Sie darüber nachdenken, was Sie mit den Eingaben tun, die über URLs, GET-Anforderungsabfrageringe, POST-Anforderungsdaten, HTTP-Header usw. bereitgestellt werden.

Wenn Sie beispielsweise dynamische SQL-Abfragen basierend auf dem idParameter Ihrer Aktionsmethode erstellen, gehen Sie wie folgt vor:

public ActionResult Tags(string id)
{
    var sql = "SELECT * FROM Tags Where tagName = '" + id + "'";
    // DO STUFF...
}

(... was keine gute Idee ist), der vom .NET Framework eingerichtete Standardschutz kann einige der gefährlicheren Szenarien stoppen, z. B. den Benutzer, der diese URL anfordert:

/product/tags/1%27;drop%20table%20Tags;%20--

Die ganze Idee ist, jeden Teil von URLs und anderen Eingaben in Aktionsmethoden als mögliche Bedrohungen zu behandeln. Die Standardsicherheitseinstellung bietet Ihnen einen Teil dieses Schutzes. Jede von Ihnen geänderte Standardsicherheitseinstellung öffnet sich für ein wenig mehr potenzielle Fehler, die Sie manuell behandeln müssen.

Ich gehe davon aus, dass Sie keine SQL-Abfragen auf diese Weise erstellen. Aber das hinterhältigere Zeug kommt, wenn Sie Benutzereingaben in Ihrer Datenbank speichern und sie später anzeigen. Der böswillige Benutzer könnte JavaScript oder HTML in Ihrer Datenbank speichern, die nicht codiert sind, was wiederum andere Benutzer Ihres Systems bedrohen würde.


6

Sicherheitsrisiko

Die Einstellung allowDoubleEscapinggilt nur für den path(cs-uri-stem) und wird am besten durch OWASP Double Encoding erklärt . Die Technik wird verwendet, um Sicherheitskontrollen durch zweimaliges URL-Codieren der Anforderung zu umgehen. Verwenden Sie Ihre URL als Beispiel:

/product/tags/for+families --> /product/tags/for%2Bfamilies --> /product/tags/for%252Bfamilies

Angenommen, es gibt Sicherheitskontrollen speziell für /product/tags/for+families. Es kommt eine Anforderung an, für /product/tags/for%252Bfamiliesdie dieselbe Ressource vorhanden ist, die jedoch von den oben genannten Sicherheitskontrollen nicht überprüft wird. Ich habe den allgemeinen Begriff der Sicherheitskontrollen verwendet, da dies beispielsweise die Anforderung eines authentifizierten Benutzers, die Suche nach SQLi usw. sein kann.

Warum blockiert IIS?

Das Pluszeichen (+) ist ein reserviertes Zeichen gemäß RFC2396 :

Viele URI enthalten Komponenten, die aus bestimmten Sonderzeichen bestehen oder durch diese begrenzt sind. Diese Zeichen werden als "reserviert" bezeichnet, da ihre Verwendung innerhalb der URI-Komponente auf ihren reservierten Zweck beschränkt ist. Wenn die Daten für eine URI-Komponente mit dem reservierten Zweck in Konflikt stehen würden, müssen die widersprüchlichen Daten maskiert werden, bevor der URI gebildet wird.

  reserved    = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" |
                "$" | ","

Wade Hilmo hat einen ausgezeichneten Beitrag mit dem Titel Wie IIS Zeichen in URLs blockiert . Es gibt viele Informationen und Hintergrundinformationen. Der Teil speziell für das Pluszeichen lautet wie folgt:

Erlaube allowDoubleEscaping / VerifyNormalization scheint also ziemlich einfach zu sein. Warum habe ich gesagt, dass es Verwirrung stiftet? Das Problem ist, wenn ein '+' Zeichen in einer URL angezeigt wird. Das Zeichen '+' scheint nicht maskiert zu sein, da es kein '%' enthält. RFC 2396 merkt es auch als reserviertes Zeichen an, das in eine URL aufgenommen werden kann, wenn es in Escape-Form vorliegt (% 2b). Wenn allowDoubleEscaping jedoch auf den Standardwert false festgelegt ist, wird es auch in maskierter Form blockiert. Der Grund dafür ist historisch: In den frühen Tagen von HTTP wurde ein '+' - Zeichen als Abkürzung für ein Leerzeichen angesehen. Einige Canonicalizer konvertieren eine URL, die ein '+' enthält, in ein Leerzeichen, wenn sie eine URL erhalten. Aus diesem Grund betrachten wir ein '+' in einer URL als nicht kanonisch. Ich konnte keinen Hinweis auf einen RFC finden, der diese "+" - Behandlung aufruft.

Aus eigener Erfahrung weiß ich, dass bei IIS-Protokollen Anforderungsbereiche durch ein Pluszeichen ersetzt werden. Ein Pluszeichen im Namen kann beim Parsen von Protokollen zu Verwirrung führen.

Lösung

Es gibt drei Möglichkeiten, dies zu beheben, und zwei Möglichkeiten, das Pluszeichen weiterhin zu verwenden.

  1. allowDoubleEscaping=true- Dies ermöglicht eine doppelte Flucht für Ihre gesamte Website / Anwendung. Je nach Inhalt kann dies gelinde gesagt unerwünscht sein. Der folgende Befehl wird gesetzt allowDoubleEscaping=true.

    appcmd.exe set config "Default Web Site" -section:system.webServer/security/requestFiltering /allowDoubleEscaping:True
    
  2. alwaysAllowedUrls- Request Filtering bietet einen Whitelist-Ansatz. Durch Hinzufügen dieses URL-Pfads zu alwaysAllowedUrls wird die Anforderung nicht durch andere Einstellungen für die Anforderungsfilterung überprüft und in der IIS-Anforderungspipeline fortgesetzt. Hier besteht die Sorge, dass die Anforderungsfilterung die Anforderung nicht überprüft auf:

    • Anforderungslimits: maxContentLength, maxUrl, maxQueryString
    • Verben
    • Abfrage - Parameter für Abfragezeichenfolgen werden nicht überprüft
    • Doppelte Flucht
    • High-Bit-Zeichen
    • Filterregeln anfordern
    • Header-Limits anfordern

    Der folgende Befehl hinzufügen , /product/tags/for+familiesum alwaysAllowedUrlsauf der Standard-Website.

    appcmd.exe set config "Default Web Site" -section:system.webServer/security/requestFiltering /+"alwaysAllowedUrls.[url='/product/tags/for+families']"
    
  3. Umbenennen - ja, benennen Sie einfach die Datei / Ordner / Controller / etc. Um. wenn möglich. Dies ist die einfachste Lösung.


Um DoubleEscaping während der Entwicklung mit IIS Express zu ermöglichen, habe ich Folgendes
DeveloperDan

3

Ich habe dafür eine Arbeit gemacht. Wenn Sie also die geschriebene Zeichenfolge in die URL für (IIS) einfügen möchten, müssen Sie sie von Schmutz befreien: {";", "/", "?", ":", "@", "&", " = "," + "," $ ",", "}; und wenn Sie es beschreiben und erneut verwenden möchten, müssen Sie es erneut verschmutzen, bevor Sie es beschreiben (um das gewünschte Ergebnis zu erhalten).

Hier ist mein Code, ich hoffe er hilft jemandem:

 public static string cleanUpEncription(string encriptedstring)
        {
            string[] dirtyCharacters = { ";", "/", "?", ":", "@", "&", "=", "+", "$", "," };
            string[] cleanCharacters = { "p2n3t4G5l6m","s1l2a3s4h","q1e2st3i4o5n" ,"T22p14nt2s", "a9t" , "a2n3nd","e1q2ua88l","p22l33u1ws","d0l1ar5","c0m8a1a"};

            foreach (string dirtyCharacter in dirtyCharacters)
            {
                encriptedstring=encriptedstring.Replace(dirtyCharacter, cleanCharacters[Array.IndexOf(dirtyCharacters, dirtyCharacter)]);
            }
            return encriptedstring;
        }

        public static string MakeItDirtyAgain(string encriptedString)
        {
            string[] dirtyCharacters = { ";", "/", "?", ":", "@", "&", "=", "+", "$", "," };
            string[] cleanCharacters = { "p2n3t4G5l6m", "s1l2a3s4h", "q1e2st3i4o5n", "T22p14nt2s", "a9t", "a2n3nd", "e1q2ua88l", "p22l33u1ws", "d0l1ar5", "c0m8a1a" };
            foreach (string symbol in cleanCharacters)
            {
                encriptedString = encriptedString.Replace(symbol, dirtyCharacters[Array.IndexOf(cleanCharacters,symbol)]);
            }
            return encriptedString;
        }

Was ist pntGlm?
StuperUser

@ SuperUser nur zufällige Zeichen
Mark Dibeh

1
Die Zeichenfolge sollte base64anstelle dieser Substitutionstechnik codiert werden. Beispielsweise verwendet base64die Basisauthentifizierung die Codierung der übermittelten Anmeldeinformationen, da diese Sonderzeichen / reservierte Zeichen enthalten können.
user2320464

Problem mit base64 ist / ist ein base64-Charakter und kann die Routen brechen
Garr Godfrey

1

Ich bin darauf gestoßen, als ich eine API von einer MVC-App aus aufgerufen habe. Anstatt die Sicherheitslücke zu öffnen, habe ich meinen Pfad geändert.

Zunächst einmal empfehle ich, diese Einstellung NICHT zu deaktivieren. Es ist besser, das Design der Anwendung / Ressource zu ändern (z. B. den Pfad codieren, die Daten in einem Header oder im Body übergeben).

Obwohl dies ein älterer Beitrag ist, dachte ich, ich würde mitteilen, wie Sie diesen Fehler beheben können, wenn Sie diesen von einem Aufruf einer API mithilfe der HttpUtility.UrlPathEncode- Methode in System.Web erhalten .

Ich verwende RestSharp zum Tätigen von Anrufen, daher verwende mein Beispiel die RestRequest:

var tags = new[] { "for", "family" };
var apiRequest = new RestRequest($"product/tags/{HttpUtility.UrlPathEncode(string.Join("+", tags))}");

Dies erzeugt einen Pfad gleich:

/ product / tags / für% 2Bfamilies

Erstellen Sie in einem anderen Fall KEINE dynamische Abfrage, die auf den Eingaben eines Benutzers basiert. Sie sollten immer einen SqlParameter verwenden . Aus Sicherheitsgründen ist es außerdem äußerst wichtig, die Werte mit der entsprechenden Codierung zurückzugeben, um Injektionsangriffe zu verhindern.

~ Prost


0

Codieren Sie die verschlüsselte Zeichenfolge getrennt:

return HttpServerUtility.UrlTokenEncode(Encoding.UTF8.GetBytes("string"));

Dekodieren Sie die verschlüsselte Zeichenfolge getrennt:

string x = Encoding.UTF8.GetString(HttpServerUtility.UrlTokenDecode(id));
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.