security - tipos - La mejor forma de manejar la seguridad y evitar XSS con las URL ingresadas por el usuario
tipos de vulnerabilidades xss (8)
Tenemos una aplicación de alta seguridad y queremos permitir a los usuarios ingresar URL que otros usuarios verán.
Esto introduce un alto riesgo de hacks XSS: un usuario podría ingresar javascript que otro usuario termine ejecutando. Como tenemos datos confidenciales, es esencial que esto nunca suceda.
¿Cuáles son las mejores prácticas para lidiar con esto? ¿Hay alguna lista blanca de seguridad o patrón de escape lo suficientemente bueno?
Cualquier consejo sobre el tratamiento de las redirecciones (por ejemplo, el mensaje "este enlace sale de nuestro sitio" en una página de advertencia antes de seguir el enlace)
¿Existe un argumento para no apoyar los enlaces ingresados por el usuario?
Aclaración:
Básicamente nuestros usuarios quieren ingresar:
stackoverflow.com
Y hacer que salga a otro usuario:
<a href="http://stackoverflow.com">stackoverflow.com</a>
Lo que realmente me preocupa es que usen esto en un hack XSS. Es decir, que ingresan:
alerta (''hackeado!'');
Para que otros usuarios obtengan este enlace:
<a href="alert(''hacked!'');">stackoverflow.com</a>
Mi ejemplo es solo para explicar el riesgo: soy consciente de que las URL de JavaScript y de JavaScript son diferentes, pero al permitirles ingresar estas últimas, es posible que ejecuten las primeras.
Se sorprenderá de cuántos sitios puede romper con este truco: HTML es aún peor. Si saben manejar enlaces, ¿también sabrán desinfectar <iframe>
, <img>
y referencias CSS inteligentes?
Estoy trabajando en un entorno de alta seguridad: un solo hack XSS podría generar grandes pérdidas para nosotros. Estoy feliz de poder producir un Regex (o usar una de las excelentes sugerencias hasta ahora) que podría excluir todo lo que podría pensar, pero ¿sería suficiente?
¿Qué tal si no se muestran como un enlace? Solo usa el texto.
Combinado con una advertencia para proceder bajo su propio riesgo puede ser suficiente.
Además , ver también ¿Debería desinfectar el marcado HTML para un CMS alojado? para una discusión sobre la desinfección de la entrada del usuario
El proceso de hacer que un enlace sea "seguro" debe pasar por tres o cuatro pasos:
- Unescape / vuelva a codificar la cadena que le han dado (RSnake ha documentado una serie de trucos en que usan escaping y codificaciones UTF).
- Limpie el enlace: las expresiones regulares son un buen comienzo: asegúrese de truncar la cadena o tirarla si contiene un "(o lo que sea que use para cerrar los atributos en su salida); Si está haciendo los enlaces solo como referencias a otra información también puede forzar el protocolo al final de este proceso: si la parte anterior al primer punto no es ''http'' o ''https'', añada ''http: //'' al inicio. Esto le permite crear utilizable enlaces de entrada incompleta como un usuario escribiría en un navegador y te da la última oportunidad de tropezar con cualquier travesura que alguien haya intentado colar.
- Compruebe que el resultado sea una URL bien formada (protocolo: //host.domain [: port] [/ path] [/ [file]] [? QueryField = queryValue] [#anchor]).
- Posiblemente, verifique el resultado contra una lista negra del sitio o intente buscarlo a través de algún tipo de corrector de malware.
Si la seguridad es una prioridad, espero que los usuarios perdonen un poco de paranoia en este proceso, incluso si termina tirando algunos enlaces seguros.
No especifica el idioma de su aplicación, entonces supongo que ASP.NET, y para esto puede usar la Biblioteca de scripts de Microsoft Anti-Cross Site.
Es muy fácil de usar, todo lo que necesitas es incluir y eso es todo :)
Mientras habla sobre el tema, ¿por qué no leen las Pautas de diseño para aplicaciones web seguras?
Si hay otro idioma ... si hay una biblioteca para ASP.NET, tiene que estar disponible también para otro tipo de lenguaje (PHP, Python, ROR, etc.)
Permitir una URL y permitir JavaScript son dos cosas diferentes.
Puede usar un código hexadecimal para convertir la URL completa y enviarla a su servidor. De esa forma, el cliente no entendería el contenido a primera vista. Después de leer el contenido, ¿podría decodificar el contenido URL =? y enviarlo al navegador.
Si crees que las URL no pueden contener código, ¡piénsalo de nuevo!
https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet
Lee eso y llora.
Así es como lo hacemos en :
/// <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+&@#/%?=~_|!:,.;/(/)]", "");
}
Simplemente HTMLEncode los enlaces cuando los muestres. Asegúrese de no permitir javascript:
enlaces. (Lo mejor es tener una lista blanca de protocolos aceptados, por ejemplo, http, https y mailto).
Use una biblioteca, como API OWASP-ESAPI:
- PHP - http://code.google.com/p/owasp-esapi-php/
- Java - http://code.google.com/p/owasp-esapi-java/
- .NET - http://code.google.com/p/owasp-esapi-dotnet/
- Python - http://code.google.com/p/owasp-esapi-python/
Lea lo siguiente:
- https://www.golemtechnologies.com/articles/prevent-xss#how-to-prevent-cross-site-scripting
- https://www.owasp.org/
- http://www.secbytes.com/blog/?p=253
Por ejemplo:
$url = "http://.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 );
Otro ejemplo es usar una función incorporada. La función filter_var de PHP es un ejemplo:
$url = "http://.com"; // e.g., $_GET["user-homepage"];
$sanitized_url = filter_var($url, FILTER_SANITIZE_URL);
Usar filter_var
allows llamadas de JavaScript y filtra esquemas que no son ni http
ni https
. El uso de OWASP ESAPI Sanitizer es probablemente la mejor opción.
Otro ejemplo más es el código de WordPress :
Además, dado que no hay forma de saber dónde se vinculan las URL (es decir, podría ser una URL válida, pero el contenido de la URL podría ser malicioso), Google tiene una API de navegación segura a la que puede llamar:
Hacer rodar su propia expresión regular para el saneamiento es problemático por varias razones:
- A menos que seas Jon Skeet, el código tendrá errores.
- Las API existentes tienen muchas horas de revisión y prueba detrás de ellas.
- Las API de validación de URL existentes consideran la internacionalización.
- Las API existentes se mantendrán actualizadas con estándares emergentes.
Otros asuntos a considerar:
- ¿Qué esquemas se permiten (son
file:///
ytelnet://
acceptable)? - ¿Qué restricciones desea colocar en el contenido de la URL (son aceptables las URL de malware?