Nous avons une application haute sécurité et nous voulons permettre aux utilisateurs de saisir des URL que d'autres utilisateurs verront.
Cela introduit un risque élevé de piratage XSS - un utilisateur peut éventuellement entrer du code JavaScript qu'un autre utilisateur finira par exécuter. Puisque nous détenons des données sensibles, il est essentiel que cela ne se produise jamais.
Quelles sont les meilleures pratiques en la matière? Une liste blanche de sécurité ou un modèle d’échappement est-il suffisant?
Tout conseil sur le traitement des redirections (message "ce lien sort de notre site" sur une page d'avertissement avant de suivre le lien, par exemple)
Existe-t-il un argument pour ne pas supporter du tout les liens saisis par l'utilisateur?
Clarification:
Fondamentalement, nos utilisateurs veulent entrer:
stackoverflow.com
Et le faire sortir à un autre utilisateur:
<a href="http://stackoverflow.com">stackoverflow.com</a>
Ce qui me préoccupe vraiment, c’est qu’ils utilisent cela dans un hack XSS. C'est à dire. ils entrent:
alerte ('piraté!');
Donc, les autres utilisateurs obtiennent ce lien:
<a href="alert('hacked!');">stackoverflow.com</a>
Mon exemple est juste pour expliquer le risque - je sais bien que javascript et les URL sont des choses différentes, mais en les laissant entrer ce dernier, ils pourraient peut-être exécuter le premier.
Vous seriez surpris de voir combien de sites vous pouvez briser avec cette astuce - HTML est encore pire. S'ils savent manipuler des liens, savent-ils également comment désinfecter les références <iframe>
, <img>
et CSS intelligentes?
Je travaille dans un environnement hautement sécurisé - un simple piratage XSS pourrait nous occasionner de très lourdes pertes. Je suis heureux de pouvoir produire un regex (ou d'utiliser l'une des excellentes suggestions jusqu'à présent) qui puisse exclure tout ce à quoi je peux penser, mais est-ce suffisant?
Si vous pensez que les URL ne peuvent pas contenir de code, détrompez-vous!
https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet
Lisez cela et pleurez.
Voici comment nous le faisons sur Stack Overflow:
/// <summary>
/// returns "safe" URL, stripping anything outside normal charsets for URL
/// </summary>
public static string SanitizeUrl(string url)
{
return Regex.Replace(url, @"[^-A-Za-z0-9+&@#/%?=~_|!:,.;\(\)]", "");
}
Pour rendre un lien "sûr", vous devez suivre trois ou quatre étapes:
Si la sécurité est une priorité, j'espère que les utilisateurs pardonneront un peu de paranoïa dans ce processus, même s'il finit par jeter des liens sûrs.
Utilisez une bibliothèque, telle que l'API OWASP-ESAPI:
Lisez ce qui suit:
Par exemple:
$url = "http://stackoverflow.com"; // e.g., $_GET["user-homepage"];
$esapi = new ESAPI( "/etc/php5/esapi/ESAPI.xml" ); // Modified copy of ESAPI.xml
$sanitizer = ESAPI::getSanitizer();
$sanitized_url = $sanitizer->getSanitizedURL( "user-homepage", $url );
Un autre exemple consiste à utiliser une fonction intégrée. La fonction PHP filter_var en est un exemple:
$url = "http://stackoverflow.com"; // e.g., $_GET["user-homepage"];
$sanitized_url = filter_var($url, FILTER_SANITIZE_URL);
Utiliser filter_var
permet les appels javascript et filtre les régimes qui ne sont ni http
ni https
. L'utilisation de OWASP ESAPI Sanitizer est probablement la meilleure option.
Encore un autre exemple est le code de WordPress :
De plus, comme il n’existe aucun moyen de savoir où l’URL est liée (par exemple, il peut s’agir d’une URL valide, mais le contenu de cette URL peut être malicieux), Google dispose d’une API navigation sûre que vous pouvez appeler:
Faire rouler sa propre regex pour l'assainissement pose problème pour plusieurs raisons:
Autres questions à prendre en compte:
file:///
et telnet://
sont-ils acceptables)?Vous ne spécifiez pas la langue de votre application, je présume alors ASP.NET et vous pouvez utiliser pour cela la Bibliothèque de scripts anti-site multiple de Microsoft
Il est très facile à utiliser, tout ce dont vous avez besoin est un include, et c'est tout :)
Pendant que vous êtes sur le sujet, pourquoi ne pas lire/ Directives de conception pour les applications Web sécurisées
S'il existe une autre langue .... s'il existe une bibliothèque pour ASP.NET, elle doit également être disponible pour d'autres types de langage (PHP, Python, ROR, etc.)
Juste HTMLEncode les liens lorsque vous les sortez. Assurez-vous de ne pas autoriser les liens javascript:
. (Il est préférable d’avoir une liste blanche de protocoles acceptés, tels que http, https et mailto.)
Pourquoi ne pas les afficher sous forme de lien? Il suffit d'utiliser le texte.
Combiné avec un avertissement de procéder à vos propres risques peut suffire.
addition - voir aussi Devrais-je nettoyer le balisage HTML pour un CMS hébergé? pour une discussion sur la désinfection des entrées de l'utilisateur
Dans mon projet écrit en JavaScript, j'utilise cette regex comme liste blanche:
url.match(/^((https?|ftp):\/\/|\.{0,2}\/)/)
la seule limite est que vous devez placer ./ devant les fichiers du même répertoire, mais je pense pouvoir vivre avec cela.
Pour les pythonistes, essayez Scrapy's w3lib .
OWASP ESAPI est antérieur à Python 2.7 et est archivé sur le le code Google maintenant disparu .