Sur mon application ASP.NET MVC, j'essaie d'implémenter une URL comme ci-dessous:
/ product/tags/for + families
Lorsque j'essaie d'exécuter mon application avec des configurations par défaut, le message 404.11 Response Code suivant s'affiche:
Erreur HTTP 404.11 - Introuvable
Le module de filtrage des demandes est configuré pour refuser une demande contenant une séquence d'échappement double.
Je peux contourner cette erreur en implémentant le code ci-dessous dans mon web.config:
<system.webServer>
<security>
<requestFiltering allowDoubleEscaping="true" />
</security>
</system.webServer>
Donc, maintenant je ne reçois plus aucun 404.11
.
Ce que je me demande, c'est quel genre de failles de sécurité j'ouvre avec cette implémentation.
BTW, mon application est sous .Net Framework 4.0
et en cours d'exécution sous IIS 7.5
.
Les failles de sécurité que vous pouvez ouvrir sont liées à l’injection de code - injection HTML, injection JavaScript ou SQL.
Les paramètres par défaut vous protègent des attaques de manière semi-efficace en empêchant les stratégies d'injection courantes de fonctionner. Plus vous supprimez la sécurité par défaut, plus vous devez penser à ce que vous faites avec les entrées fournies via les URL, les chaînes de requête de requête GET, POST, 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 + "'";
// DO STUFF...
}
(... ce qui est PAS une bonne idée), la protection par défaut mise en place par le framework .NET pourrait arrêter certains des scénarios les plus dangereux. , comme l'utilisateur demandant cette URL:
/product/tags/1%27;drop%20table%20Tags;%20--
L'idée est de traiter chaque partie des URL et autres entrées des méthodes d'action comme des menaces possibles. Le paramètre de sécurité par défaut fournit une partie de cette protection. Chaque paramètre de sécurité par défaut que vous modifiez ouvre un peu plus de potentiel que vous devez gérer manuellement.
Je suppose que vous ne construisez pas de requêtes SQL de cette façon. Mais les choses les plus sournoises viennent lorsque vous stockez les entrées utilisateur dans votre base de données, puis que vous les affichez plus tard. L'utilisateur malveillant peut stocker du code JavaScript ou HTML dans votre base de données non codée, ce qui menacerait d'autres utilisateurs de votre système.
Le paramètre allowDoubleEscaping
ne s’applique qu’à path
(cs-uri-stem) et s’explique mieux par OWASP Double Encoding . La technique est utilisée pour contourner les contrôles de sécurité par URL en codant deux fois la demande. En utilisant votre URL comme exemple:
/product/tags/for+families --> /product/tags/for%2Bfamilies --> /product/tags/for%252Bfamilies
Supposons qu'il existe des contrôles de sécurité spécifiquement pour /product/tags/for+families
. Une demande arrive pour /product/tags/for%252Bfamilies
qui est la même ressource mais qui n’est pas cochée par les contrôles de sécurité susmentionnés. J'ai utilisé le terme généralisé de contrôles de sécurité, car ils peuvent être tels que demander un utilisateur authentifié, rechercher SQLi, etc.
Le signe plus (+) est un caractère réservé par RFC2396 :
De nombreux URI incluent des composants constitués de, ou délimités par, de certains caractères spéciaux. Ces caractères sont appelés "réservés", car leur utilisation dans le composant URI est limitée à leur fonction réservée. Si les données d'un composant URI sont en conflit avec l'objectif réservé, les données en conflit doivent être évitées avant de former l'URI.
reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","
Wade Hilmo a un excellent article intitulé How IIS bloque les caractères dans les URL . De nombreuses informations et arrière-plans sont fournis. La partie spécifique du signe plus est la suivante:
Donc allowDoubleEscaping/VerifyNormalization semble assez simple. Pourquoi ai-je dit que cela crée de la confusion? Le problème est lorsqu'un caractère "+" apparaît dans une URL. Le caractère "+" ne semble pas échapper car il ne comporte pas de "%". De plus, la RFC 2396 le note comme un caractère réservé pouvant être inclus dans une URL lorsque celle-ci est sous forme échappée (% 2b). Mais avec allowDoubleEscaping dont la valeur par défaut est false, nous le bloquerons même sous forme échappée. La raison en est historique: il y a bien longtemps, un caractère "+" était considéré comme un raccourci pour un caractère espace. Certains canoniciens, quand on leur donne une URL contenant un "+", la convertissent en un espace. Pour cette raison, nous considérons qu'un "+" n'est pas canonique dans une URL. Je n’ai trouvé aucune référence à une RFC appelant ce traitement "+", mais il existe de nombreuses références sur le Web qui en parlent comme d’un comportement historique.
D'après ma propre expérience, je sais que lorsque IIS), les espaces de requête sont remplacés par un signe plus. La présence d'un signe plus dans le nom peut entraîner une confusion lors de l'analyse des journaux.
Il existe trois façons de résoudre ce problème et deux de continuer à utiliser le signe plus.
allowDoubleEscaping=true
- Cela permettra une double évasion pour l’ensemble de votre site Web/application. En fonction du contenu, cela pourrait être peu souhaitable. La commande suivante va définir allowDoubleEscaping=true
.
appcmd.exe set config "Default Web Site" -section:system.webServer/security/requestFiltering /allowDoubleEscaping:True
alwaysAllowedUrls
- Le filtrage des demandes offre une approche de liste blanche. En ajoutant ce chemin d'URL à alwaysAllowedUrls, la demande ne sera vérifiée par aucun autre paramètre de filtrage des demandes et continuera dans le pipeline de demandes IIS. Le problème est que le filtrage des demandes ne vérifiera pas la demande. pour:
La commande suivante ajoutera /product/tags/for+families
à alwaysAllowedUrls
sur le site Web par défaut.
appcmd.exe set config "Default Web Site" -section:system.webServer/security/requestFiltering /+"alwaysAllowedUrls.[url='/product/tags/for+families']"
Renommer - oui, il suffit de renommer le fichier/dossier/contrôleur/etc. si possible. C'est la solution la plus simple.
J'ai fait un travail d'arround pour cela. Ainsi, lorsque vous souhaitez insérer la chaîne de caractères indiquée dans l'URL pour (IIS), vous devez la nettoyer: {";", "/", "?", ":", "@", "&", " = "," + "," $ ",", "}; et quand vous voulez le décrypter et l'utiliser à nouveau, vous devez le salir à nouveau avant de le décrypter (pour obtenir le résultat souhaité).
Voici mon code, j'espère que ça aide 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;
}
Je me suis donc heurté à cela lorsque j'appelais une API à partir d'une application MVC. Au lieu d'ouvrir le trou 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, coder le chemin, transmettre les données dans un en-tête ou dans le corps).
Bien que ce soit un article plus ancien, j’ai pensé partager avec vous la façon dont vous pourriez résoudre cette erreur si vous recevez cela depuis un appel à une API en utilisant la méthode HttpUtility.UrlPathEncode dans System.Web .
J'utilise RestSharp pour passer des appels, mon exemple utilise donc RestRequest:
var tags = new[] { "for", "family" };
var apiRequest = new RestRequest($"product/tags/{HttpUtility.UrlPathEncode(string.Join("+", tags))}");
Cela produit un chemin égal à:
/ product/tags/for% 2Bfamilies
Sur une autre note, ne construisez pas une requête dynamique basée sur les entrées d'un utilisateur. Vous devriez toujours utiliser un SqlParameter . De plus, il est extrêmement important, du point de vue de la sécurité, de renvoyer les valeurs avec le codage approprié pour prévenir les attaques par injection.
~ A bientôt