2010-09-10 9 views
11

Estoy tratando de desinfectar y XSS prueba alguna entrada HTML del cliente. Estoy usando Python 2.6 con Beautiful Soup. Analizo la entrada, elimino todas las etiquetas y atributos que no están en una lista blanca y transformo el árbol en una cadena.¿Cómo hacer que Beautiful Soup produzca entidades HTML?

Sin embargo ...

>>> unicode(BeautifulSoup('text < text')) 
u'text < text' 

Eso no se ve como HTML válido para mí. Y con mi separador de etiquetas, que abre el camino a toda clase de maldad: serán eliminados

>>> print BeautifulSoup('<<script></script>script>alert("xss")<<script></script>script>').prettify() 
< 
<script> 
</script> 
script>alert("xss")< 
<script> 
</script> 
script> 

Los <script></script> pares, y lo que queda es no sólo un ataque XSS, pero aun así HTML válido.

La solución obvia es reemplazar todos los caracteres < por &lt; que, después del análisis, se encuentran para no pertenecer a una etiqueta (y similar para >&'"). Pero el Beautiful Soup documentation solo menciona el análisis de entidades, no la producción de ellas. Por supuesto, puedo ejecutar un reemplazo sobre todos los nodos NavigableString, pero como podría extrañar algo, preferiría que algún código probado y comprobado hiciera el trabajo.

¿Por qué Beautiful Soup escape < (y otros caracteres mágicos) de forma predeterminada, y cómo lo hago?


N.B. También miré lxml.html.clean. Parece que funciona sobre la base de listas negras, no listas blancas, por lo que no parece muy seguro para mí. Las etiquetas pueden incluirse en la lista blanca, pero los atributos no pueden, y permite demasiados atributos para mi gusto (por ejemplo, tabindex). Además, da un AssertionError en la entrada <SCRIPT SRC=http://ha.ckers.org/xss.js></SCRIPT>. No está bien.

Sugerencias para otras formas de limpiar HTML también son bienvenidas. No soy la única persona en el mundo que intenta hacer esto, pero parece que no hay una solución estándar.

+0

'text Gumbo

+0

Oh, correcto. De todos modos, hace lo mismo con 'text 'que mostré. – Thomas

Respuesta

2

La clase lxml.html.clean.Cleaner sí permite que proporcione una lista blanca de la etiqueta con el argumento allow_tags y permite utilizar la lista blanca atributo precomputed de feedparser con el argumento safe_attrs_only. Y lxml definitivamente maneja las entidades correctamente en la serialización.

+0

Al igual que escribí en la pregunta original, no me permite cambiar la lista de atributos. Por ejemplo, 'tabindex' puede hacer que el sitio se comporte de maneras inesperadas, y con algo de imaginación, los diversos atributos de codificación como' charset' también podrían usarse con fines maliciosos, mientras que raramente (si es que alguna vez) son útiles. Prefiero permitir solo los atributos que son realmente útiles (y usados). – Thomas

+0

Están en la lista de atributos aceptados por el corrector de feed, que es bastante paranoico. Si es más paranoico, puede establecer 'lxml.html.defs.safe_attrs' solo con los atributos que considere seguros. De forma alternativa, si no del todo, probablemente puedas reutilizar la clase 'feedparser._HTMLSanitizer', modificándola para que se adapte a los atributos que deseas permitir. – llasram

+2

No me gusta esa lista. El elemento '

' está en él.Ah, y acabo de detectar un error tipográfico en 'lxml/html/defs.py':' marque' en lugar de 'marquee', todavía presente en la versión svn. He informado un error. No es gran cosa, pero no ayuda a construir confianza ... – Thomas

Cuestiones relacionadas