93 votes

Double une séquence d'échappement à l'intérieur d'une URL : Le module de filtrage de requêtes est configuré pour refuser une requête contenant une double séquence d'échappement

Sur mon application ASP.NET MVC, j'essaie de mettre en œuvre une URL comme ci-dessous :

/produit/tags/pour+familles

Lorsque j'essaie d'exécuter mon application avec les configurations par défaut, je reçois ce message avec le code de réponse 404.11 :

Erreur HTTP 404.11 - Non trouvé

Le module de filtrage des requêtes est configuré pour refuser une requête qui contient une double séquence d'échappement.

Je peux contourner cette erreur en implémentant le code ci-dessous à l'intérieur de mon fichier web.config :

Du coup, je ne reçois plus de 404.11.

Ce que je me demande, c'est quels types de failles de sécurité j'ouvre avec cette mise en œuvre.

Au fait, mon application est sous le .Net Framework 4.0 et s'exécute sous IIS 7.5.

0 votes

Est-il possible d'accéder à la ressource souhaitée en utilisant /produit/étiquettes/pour%20les%20familles à la place ? Vous avez donc une solution de contournement pour les identifiants contenant des espaces. Ou ai-je complètement faux ici ?

0 votes

@atornblad un peu hors sujet je suppose. Ma question : ce que je me demande, c'est de quels types de failles de sécurité j'ouvre avec cette implémentation.

5 votes

IIS jette sur le caractère "+", qui est le comportement par défaut de Microsoft.

59voto

atornblad Points 5599

Les failles de sécurité que vous pourriez ouvrir sont liées à l'injection de code - l'injection HTML, l'injection JavaScript ou l'injection SQL.

Les paramètres par défaut vous protègent de manière semi-efficace contre les attaques en ne permettant pas aux stratégies d'injection courantes de fonctionner. Plus vous supprimez de sécurité par défaut, plus vous devez réfléchir à ce que vous faites avec les entrées fournies via les URL, les chaînes de requête GET, les données de requête POST, les en-têtes HTTP, etc...

Par exemple, si vous construisez des requêtes SQL dynamiques basées sur le paramètre id de votre méthode d'action, comme ceci :

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

(...ce qui est UNE IDÉE À NE PAS SUIVRE), la protection par défaut mise en place par le framework .NET pourrait stopper certains scénarios plus dangereux, comme l'utilisateur demandant cette URL :

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

L'idée générale est de considérer chaque partie des URL et autres entrées des méthodes d'action comme des menaces possibles. Les paramètres de sécurité par défaut fournissent une certaine protection à cet égard. Chaque paramètre de sécurité par défaut que vous modifiez ouvre la voie à un peu plus de risques potentiels que vous devez gérer manuellement.

Je suppose que vous ne construisez pas des requêtes SQL de cette façon. Mais les problèmes plus sournois surviennent lorsque vous stockez les entrées de l'utilisateur dans votre base de données, puis les affichez ultérieurement. L'utilisateur malveillant pourrait stocker du JavaScript ou du HTML dans votre base de données qui sortira non codé, menaçant ainsi les autres utilisateurs de votre système.

8voto

user2320464 Points 291

Risque de sécurité

Le paramètre allowDoubleEscaping s'applique uniquement au chemin (cs-uri-stem) et est mieux expliqué par OWASP Double Encoding. La technique est utilisée pour contourner les contrôles de sécurité en encodant l'URL de la requête deux fois. En utilisant votre URL comme exemple :

/produit/tags/pour+familles --> /produit/tags/pour%2Bfamilles --> /produit/tags/pour%252Bfamilles

Supposons qu'il y ait des contrôles de sécurité spécifiques pour /produit/tags/pour+familles. Une requête arrive pour /produit/tags/pour%252Bfamilles qui est la même ressource bien qu'elle ne soit pas vérifiée par les contrôles de sécurité mentionnés ci-dessus. J'ai utilisé le terme généralisé de contrôles de sécurité car ils pourraient être n'importe quoi, comme exiger un utilisateur authentifié, vérifier les injections SQL, etc.

Pourquoi IIS bloque-t-il ?

Le signe plus (+) est un caractère réservé selon RFC2396 :

De nombreux URI incluent des composants constitués de certain caractères spéciaux. Ces caractères sont appelés "réservés", car leur utilisation dans le composant de l'URI est limitée à leur objectif réservé. Si les données d'un composant de l'URI entrent en conflit avec l'objectif réservé, les données en conflit doivent être échappées avant de former l'URI.

  réservé    = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" |
                "$" | ","

Wade Hilmo a publié un excellent article intitulé Comment IIS bloque les caractères dans les URLs. Beaucoup d'informations et de contexte sont fournies. La partie spécifique pour le signe plus est la suivante :

Donc allowDoubleEscaping/VerifyNormalization semble assez simple. Pourquoi ai-je dit que cela cause de la confusion ? Le problème survient lorsque le caractère ‘+’ apparaît dans une URL. Le caractère ‘+’ ne semble pas être échappé, car il n'implique pas de ‘%’. De plus, le RFC 2396 le note comme un caractère réservé pouvant être inclus dans une URL lorsqu'il est sous forme échappée (%2b). Mais avec allowDoubleEscaping réglé sur sa valeur par défaut de false, nous le bloquons même en forme échappée. La raison pour cela est historique : Au tout début de HTTP, un caractère ‘+’ était considéré comme une forme abrégée d'un espace. Certains normalisateurs, lorsqu'ils reçoivent une URL contenant un ‘+’, le convertiront en un espace. Pour cette raison, nous considérons un ‘+’ comme non canonique dans une URL. Je n'ai pas pu trouver de référence à un RFC qui mentionne ce traitement du ‘+’, mais il existe de nombreuses références sur le web qui en parlent comme d'un comportement historique.

D'après mes propres expériences, je sais qu'avec IIS, lorsqu'une requête est enregistrée, les espaces sont substitués par un signe plus. Avoir un signe plus dans le nom peut causer de la confusion lors de l'analyse des logs.

Solution

Il existe trois façons de corriger cela et deux façons d'utiliser quand même le signe plus.

  1. allowDoubleEscaping=true - Cela permettra le double échappement pour l'ensemble de votre site/application. Selon le contenu, cela pourrait être indésirable pour le moins. La commande suivante définira allowDoubleEscaping=true.

    appcmd.exe set config "Default Web Site" -section:system.webServer/security/requestFiltering /allowDoubleEscaping:True
  2. alwaysAllowedUrls - Le filtrage de requêtes offre une approche de liste blanche. En ajoutant ce chemin d'URL à alwaysAllowedUrls, la requête ne sera pas vérifiée par d'autres paramètres de filtrage de requêtes et continuera dans le pipeline de requêtes IIS. Le souci ici est que le filtrage de requêtes ne vérifiera pas la requête pour :

  • Limites de requêtes : maxContentLength, maxUrl, maxQueryString
  • Verbes
  • Requêtes - les paramètres de chaîne de requête ne seront pas vérifiés
  • Double échappement
  • Caractères haute-bits
  • Règles de filtrage de requêtes
  • Limites d'en-tête de requête

La commande suivante ajoutera /produit/tags/pour+familles à alwaysAllowedUrls sur le site Web par défaut.

    appcmd.exe set config "Default Web Site" -section:system.webServer/security/requestFiltering /+"alwaysAllowedUrls.[url='/produit/tags/pour+familles']"
  1. Renommer - oui, il suffit de renommer le fichier/dossier/contrôleur/etc. si possible. C'est la solution la plus simple.

0 votes

Pour autoriser le DoubleEscaping lors du développement avec IIS Express, voici ce que j'ai fait : stackoverflow.com/q/56463044/381082

0 votes

@user2320464 - excellent summary. ATTENTION AUX LECTEURS : NE définissez PAS "allowDoubleEscaping=true" : ce n'est tout simplement pas une bonne idée. Les alternatives incluent l'utilisation de Uri.EscapeUriString() ou Uri.EscapeDataString()

1 votes

@paulsm4, comme l'indique le post, avec allowDoubleEscaping défini sur sa valeur par défaut de false, nous bloquerons [+] même sous forme échappée. J'ai testé cela avec EscapeUriString et EscapeDataString et un + échappé ne passe toujours pas.

5voto

mark dibe Points 185

J'ai créé une solution temporaire pour cela. Donc, lorsque vous souhaitez insérer la chaîne chiffrée dans l'URL pour (IIS), vous devez la nettoyer des caractères spéciaux :{ ";", "/", "?", ":", "@", "&", "=", "+", "$", "," }; et lorsque vous voulez la déchiffrer et l'utiliser à nouveau, vous devez la rendre sale à nouveau avant de la déchiffrer (pour obtenir le résultat voulu) .

Voici mon code, j'espère qu'il aidera quelqu'un :

 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;
        }

0 votes

Qu'est-ce que pntGlm ?

0 votes

@StuperUser juste des caractères aléatoires

1 votes

La chaîne doit être encodée en base64 au lieu d'utiliser cette technique de substitution. Par exemple, l'authentification de base utilise le base64 pour encoder les informations d'identification soumises car elles peuvent contenir des caractères spéciaux/réservés.

2voto

VdesmedT Points 6831

Vérifiez cet article intéressant sur le type de porte que vous ouvrez vraiment : http://blogs.iis.net/thomad/archive/2007/12/17/iis7-rejecting-urls-containing.aspx

2voto

Rogala Points 81

Donc, j'ai rencontré ce problème lorsque j'appelais une API depuis une application MVC. Au lieu d'ouvrir la faille de sécurité, j'ai modifié mon chemin.

Tout d'abord, je recommande de NE PAS désactiver ce paramètre. Il est plus approprié de modifier la conception de l'application/ressource (par exemple, encoder le chemin, passer les données dans un en-tête ou dans le corps).

Même s'il s'agit d'une ancienne publication, j'ai pensé partager comment vous pourriez résoudre cette erreur si vous la recevez lors d'un appel à une API en utilisant la méthode HttpUtility.UrlPathEncode dans System.Web.

J'utilise RestSharp pour effectuer des appels, donc mon exemple utilise la RestRequest :

var tags = new[] { "for", "famille" };
var requêteApi = new RestRequest($"produit/tags/{HttpUtility.UrlPathEncode(string.Join("+", tags))}");

Cela produit un chemin égal à :

/produit/tags/for%2Bfamilies

En outre, NE construisez PAS une requête dynamique en fonction des entrées d'un utilisateur. Vous DEVRIEZ toujours utiliser un SqlParameter. De plus, il est extrêmement important d'un point de vue sécurité de renvoyer les valeurs avec le codage approprié pour éviter les attaques par injection.

0 votes

+1 pour recommander de ne pas désactiver "allowDoubleEscaping", et pour recommander d'utiliser toujours un SqlParameter si nécessaire. Cependant, je recommanderais d'utiliser Uri.EscapeUriString au lieu d'une liste de packages tiers comme RestSharp.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X