2008-10-15 20 views
39

Tenemos una aplicación de alta seguridad y queremos permitir que los usuarios ingresen las URL que verán otros usuarios.La mejor manera de manejar la seguridad y evitar XSS con las URL ingresadas por el usuario

Esto introduce un alto riesgo de hacks XSS - un usuario podría ingresar javascript que otro usuario termina ejecutando. Como tenemos datos confidenciales, es esencial que esto nunca suceda.

¿Cuáles son las mejores prácticas al lidiar con esto? ¿Hay alguna lista blanca de seguridad o patrón de escape lo suficientemente bueno?

Cualquier consejos sobre cómo tratar con los cambios de dirección ("este enlace ocurre fuera de nuestro sitio de" mensaje en una página de advertencia antes de seguir el enlace, por ejemplo)

¿Hay un argumento para no apoyar enlaces introducidos por el usuario en absoluto?


Aclaración:

Básicamente nuestros usuarios quieren de entrada:

stackoverflow.com

Y tenerlo salida a otro usuario:

<a href="http://stackoverflow.com">stackoverflow.com</a> 

Lo que realmente me preocupa es que lo usen en un hack XSS. Es decir. ingresaron:

alerta ('hacked!');

Así otros usuarios a obtener este enlace:

<a href="alert('hacked!');">stackoverflow.com</a> 

Mi ejemplo es sólo para explicar el riesgo - Soy muy consciente de que JavaScript y direcciones URL son cosas diferentes, pero dejándolos entrada de este último se puede ser capaz de ejecutar el primero.

Se sorprenderá de la cantidad de sitios que puede romper con este truco: HTML es aún peor. Si saben manejar enlaces, ¿saben también desinfectar , <img> y referencias CSS inteligentes?

Estoy trabajando en un entorno de alta seguridad: un solo hack XSS podría ocasionarnos pérdidas muy elevadas. 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?

+1

Necesito el segundo comentario de Nick @ - Javascript no es sinónimo de una URL.¿Estás seguro de que no se trata de desinfectar las entradas de los usuarios y evitar que los datos ingresados ​​se ejecuten si realmente se trata de un código? – warren

+0

De hecho, sé que javascript! = Url. Pero la mayoría de los lugares en los que puede obtener una URL puede incluir javascript en línea. – Keith

+0

Puedes secundarlo upmodding it. Mi respuesta es muy relevante. –

Respuesta

41

Si pensar que las URL no pueden contener código, ¡piénselo de nuevo!

https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet

leído que, y llorar.

Así es como lo hacemos desbordamiento de pila:

/// <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+&@#/%?=~_|!:,.;\(\)]", ""); 
} 
+2

Gran enlace. Es hora de agregar nuevos casos de prueba ... – Mnebuerquo

+0

He visto ese enlace antes - es parte de lo que me preocupa con esto. Tenemos que ser muy cuidadosos ya que un solo hack XSS podría costarnos mucho. Su solución basada en Regex parece haber funcionado bien en SO, sin duda. ¿Lo consideraría seguro para, por ejemplo, aplicaciones bancarias? – Keith

+0

no tan bien, podría decir Keith, it does not accept special chars in the URL, que con la reescritura de URL es seguro pasar como:

http://www.gynækologen.dk/Undersøgelser_og_behandlinger.aspx
balexandre

-7

Permitir una URL y permitir JavaScript son 2 cosas diferentes.

+1

No, no lo son, si la URL se muestra de nuevo en la página. –

+0

?? un localizador uniforme de recursos no es Javascript, mostrar la URL en la página no tiene nada que ver con Javascript – warren

+2

Eso es lo que solía pensar, también. Confía en mí en esto: estás equivocado. Y si crees que tienes razón, estás en un gran problema. –

1

¿Qué le parece no mostrarlos como un enlace? Solo usa el texto.

Combinado con una advertencia para que proceda bajo su propio riesgo, puede ser suficiente.

Además - véase también Should I sanitize HTML markup for a hosted CMS? para una discusión sobre desinfección de entrada del usuario

+0

Esa es una idea que pensamos, definitivamente segura, pero nuestros usuarios son relativamente de baja tecnología. Realmente les gustaría los enlaces en los que pueden hacer clic. – Keith

+0

comprensible, los prefiero en general, pero copiar/pegar * no * me toma un par de segundos decidir si * REALMENTE * quiero hacerlo – warren

+0

Eso tampoco es seguro. Todavía podrían encontrar una forma de insertar una etiqueta de script. –

2

No se especifica el idioma de su aplicación, a continuación, voy a presumir ASP.NET, y para ello se puede utilizar el Microsoft Anti-Cross Site Scripting Library

Es muy fácil de usar, todo lo que necesita es un include y eso es todo :)

Mientras estás en el tema, ¿por qué no se da una lectura en Design Guidelines for Secure Web Applications

Si cualquier otro idioma .... si hay una biblioteca para ASP.NET, tiene que estar disponibles también para otro tipo de lenguaje (PHP, Python, ROR, etc)

+0

Estamos específicamente en C# 3.5 y ASP.Net - Voy a revisa esa biblioteca. – Keith

3

Sólo HtmlEncode los enlaces cuando los de salida. Asegúrese de no permitir los enlaces javascript:. (Es mejor tener una lista blanca de protocolos que son aceptados, por ejemplo, http, https, y mailto.)

+4

La lista blanca es necesaria, porque IE permite tabular caracteres en el protocolo, es decir, java & x09script: funciona en IE y puentea las listas negras. – Kornel

9

El proceso de hacer un enlace "seguro" debe pasar por tres o cuatro pasos:

  • Unescape/vuelve a codificar la cadena que se te ha asignado (RSnake ha documentado una serie de trucos en http://ha.ckers.org/xss.html que usan escaping y codificaciones UTF).
  • Limpie el enlace: Las expresiones regulares son un buen comienzo: asegúrese de truncar la cadena o tírela 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 para crear enlaces utilizables a partir de entradas incompletas como un usuario escribiría en un navegador y le 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, controle el resultado en contra una lista negra del sitio o intenta buscarla 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.

6

utilizar una biblioteca, tales como API OWASP-ESAPI:

Lea la siguiente:

Por ejemplo:

$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); 

Otro ejemplo es utilizar una función incorporada. La función de PHP filter_var es un ejemplo:

$url = "http://stackoverflow.com"; // e.g., $_GET["user-homepage"]; 
$sanitized_url = filter_var($url, FILTER_SANITIZE_URL); 

Usando filter_varallows llamadas JavaScript, y filtra los esquemas que no son ni http ni https. Usar el OWASP ESAPI Sanitizer es probablemente la mejor opción.

Otro ejemplo es el código de WordPress:

Además, puesto que no hay forma de saber dónde los enlaces URL (es decir, que podría ser una dirección URL válida, pero el contenido de la URL podría ser traviesa), Google tiene una API safe browsing puede llamar:

rodar su propia expresión regular para el saneamiento es problemático por varias razones:

  • A menos que esté Jon Skeet, el código tiene errores.
  • Las API existentes tienen muchas horas de revisión y pruebas 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.

Otras cuestiones a considerar:

  • Qué esquemas qué permites (son file:///telnet:// y aceptable)?
  • ¿Qué restricciones desea colocar en el contenido de la URL (son aceptables las URL de malware?
+0

Saludos, pero el problema aquí es que OWASP tampoco es Jon Skeet. No quiero hacer lo mío, mi verdadera pregunta es sobre hasta qué punto se puede confiar en cualquiera de estos.Verificará el OWASP, pero _definitivamente no confío en ninguna seguridad integrada en PHP! _ – Keith

+0

Si puede, pruebe la API de Navegación segura de Google. Puede que no sea apropiado para su situación, pero si el código fuente está disponible, podría servir como un excelente punto de partida. –

+1

Esta es la única respuesta con código real que no se ha señalado como inseguro. En mi humilde opinión, la mejor respuesta. – antinome

-1

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.

+0

No veo por qué eso ayudaría, no hay un problema con la ejecución del código en el servidor. El problema es que el código _se ve_ como un enlace al servidor, pero ejecuta XSS malicioso cuando el usuario hace clic en él. Mi pregunta es si (dada la gran variedad de posibles permutaciones de ataque) siempre puede haber una verificación lo suficientemente estricta como para estar seguros de que el contenido XSS no puede pasar. – Keith

+0

Todo lo que he reunido desde mi entendimiento es que siempre hay una manera de superar el filtrado XSS. – Shashi

+1

Nada es 100% seguro, pero nuestros clientes desean enlaces de alta seguridad y de usuario, y quiero saber la mejor manera de hacerlo. – Keith

Cuestiones relacionadas