XSS a través de JSON: ¿Por qué una aplicación web no desinfecta el hash de parámetros entrantes o los valores JSON salientes de etiquetas maliciosas como Script?

9

Recientemente, trabajando en una aplicación web basada en Rails para una empresa, tuve que analizar la vulnerabilidad de XSS. Resulta que la aplicación, en algunos lugares, podría tomar una etiqueta HTML (por ejemplo, <script>jscodehere</script> directamente como un parámetro en las solicitudes GET o POST.

Luego se puede acceder a este parámetro a través del hash de parámetros de la aplicación (el hash donde todos los datos de clave / valor entrantes están disponibles a partir de la solicitud).

Ahora, la vulnerabilidad XSS se deriva del hecho de que el sitio también pone a disposición los datos de muchas de sus páginas en una versión JSON (por ejemplo, /cart/1.json ).

A través de algunos mecanismos que no entiendo completamente (supongo que esto es técnicamente "¿Reflejado XSS"?), el código <script> no saneado que luego se abrió camino en el JSON se puede usar para comprometer máquinas personales y otros sitios , a través de ejecución involuntaria.

Mi pregunta es, ¿por qué este no es un sistema opt-in? Rails ahora está en la versión 4, por lo que me sorprende que aún se deba crear una solución manualmente, pero esto se aplicaría a cualquier marco de aplicación web. Una cosa es permitir que los parámetros ingresen sin ser saneados por defecto (quizás las etiquetas HTML se usarán en la página de perfil de un usuario y se requiere el formato) - y creo que Rails también realiza un barrido de la acción de representación real, limitando el resultado De forma predeterminada, solo para etiquetas html "seguras".

Sin embargo, cuando se procesa JSON, no se realiza tal desinfección / limpieza, tal vez porque cuando la respuesta JSON se crea y analiza, está demasiado personalizada para hacerlo, pero no entiendo completamente por qué

1) Algunos mecanismos incorporados no están en su lugar

2) No se ha hablado más sobre esto; no pude encontrar discusión sobre el paso inseguro de etiquetas HTML / Script en la representación JSON de las aplicaciones Rails o Sinatra en la web (solo pude encontrar una pequeña cantidad de información acerca de la desinfección el hash de params, por lo que los valores de desinfección en el modo IN, que posiblemente sea mejor, pero puede que no funcione para todo, ya que es una solución única para todos, es posible que desee conservar algunas etiquetas HTML pero solo eliminarlas etiquetas <script> , por ejemplo).

3) Por qué, en el mundo de Ruby, al menos, solo hay una biblioteca que existe para desinfectar (la gema de desinfección, y realmente solo funciona en tipos de datos String; tienes que escribir tu propio código recursivo para desinfectar un Hash, como el hash params, ¡y parece que tampoco hay nada escrito en esto!). Rails tiene un desinfectante incorporado, pero se considera inferior a esta gema desinfectante de terceros, y no es tan flexible cuando se trata de tener algunos niveles de rigor en cuanto a cómo desinfectar (una cuerda).

¿Estoy malinterpretando la validez de la inyección en JSON como una vulnerabilidad, o se ha pasado por alto esta vulnerabilidad porque JSON no es una característica principal de todas las aplicaciones web?

Resultado final: usé un filtro anterior en el controlador principal de la aplicación en el back-end para sanear el hash params cada vez que sale de una solicitud, usando la biblioteca Sanitize.

Sin embargo, creo que esto ralentizó significativamente la aplicación porque tiene que ocurrir en cada solicitud, y el Desinfectante esencialmente ejecuta una serie de llamadas de expresiones regulares de forma recursiva en el hash. De esta manera, las etiquetas nunca ingresan a la base de datos, y tampoco pueden hacerlo a través de JSON, pero es un golpe costoso en cuanto al rendimiento. ¿Hay una mejor manera?

    
pregunta rcd 19.12.2015 - 10:05
fuente

2 respuestas

8

Esto a menudo se menciona en todas partes, en parte porque todos repiten el mantra de que la respuesta es el saneamiento de entrada. No lo es Es peligroso, propenso a los insectos y necesita desaparecer. Por supuesto, siempre debe verificar si las longitudes de entrada corresponden correctamente a sus columnas apropiadas.

Entrada de desinfección frente a salida de desinfección.

La entrada de desinfección brinda a las personas una falsa sensación de seguridad, ya que hay muchas formas de evitarlo y porque es difícil de implementar correctamente, lo que obliga a los desarrolladores a buscar en Google una implementación obsoleta que puede o no ser segura. Por este motivo, es mejor desinfectar salida .

Parte de la razón por la que esto se hace más tarde es porque desea conservar los datos correctos, pero también para protegerse contra los ataques de inyección de SQL. Los ataques de inyección de SQL son en gran parte derrotados por declaraciones preparadas, que no son realmente insumos de saneamiento. Debe reemplazar todas las etiquetas de script y salidas peligrosas con entidades html .

Este es un ejemplo de reemplazo de posibles caracteres de script con entidades html en la salida, no en la entrada:

  1. < se convierte en &lt; , aún se muestra como < en la página, pero sin alterar el diseño o la base de datos.

  2. > se convierte en &gt; , aún se muestra como > en la página, pero sin alterar el diseño o la base de datos.

Entonces, ¿por qué no sanear la entrada? ¿Qué pasa si lo implementamos correctamente?

La mayoría de los desarrolladores no son expertos en seguridad de TI. La mayoría de los desarrolladores no tendrían ni idea de qué hacer en esta área. Al enseñarles estos dos métodos comunes de protección de datos, ahorrará tiempo de desarrollo y aumentará significativamente la seguridad general de su aplicación web. Mejor aún, ayuda a sus desarrolladores a comprender por qué es necesario, en lugar de por qué se necesitan 2340939403424 diferentes tipos de saneamiento de entrada, y previene muchos problemas de implementación que aparecerán invariablemente más adelante.

Como dije antes, buscar en Google funciones de saneamiento de entradas obsoletas no es seguridad. Esa es una falsa sensación de seguridad. Debe comprender qué es aceptable y qué no, y el proceso por el que pasan los datos.

Con el saneamiento de salida, no tienes que preocuparte por que ocurra algún error extraño más adelante en el camino que olvidaste. No tiene que meterse con toneladas de diferentes funciones complicadas que podrían implementarse incorrectamente y dar una falsa sensación de seguridad. Tampoco debe preocuparse por la inyección de scripts.

Pero, ¿qué pasa si reemplazamos todas las entidades html antes de que se inserten? Si lo intentas en el lado del cliente, cualquiera podría modificar la solicitud. Si lo verificas en el back-end antes de ponerlos en la base de datos, eso también podría funcionar ... pero luego hay un problema :

¿Qué sucede si hay un campo que requiere que se coloque una entidad HTML real en él? Digamos un empaque, una dirección, o algo tonto como eso. Tal vez sea un nombre de archivo, tal vez sea algo que has implementado de una manera.

Ejemplo de por qué la entrada de saneamiento chupa

¿Quizás alguien tiene un teclado divertido que usa un apóstrofe diferente para su nombre o dirección? Esto podría dejar algunas bases de datos abiertas al contrabando basado en Unicode.

¿Quizás necesitas un registro que tenga < or > dentro de él? ¿Qué vas a hacer? ¿Buscar por la entidad html? Eso es bastante ineficiente, y requiere muchos trucos para funcionar correctamente en muchas bases de datos.

Tal vez el nombre de alguien tenga un apóstrofe, por ejemplo, Rory O'Cune . Con el saneamiento de entrada, estás destruyendo su nombre y requiriendo más código para resolverlo. ¿Qué pasa si uno de sus empleados está buscando por apellidos y no puede encontrarlo porque se ha reducido a OCune ? Esto es horrible.

Esa es otra razón por la que utiliza consultas parametrizadas y no ingresa el saneamiento. Con declaraciones preparadas y saneamiento de salida, puede hacer esto:

SELECT * FROM [table] WHERE [last_name] = @Lastname -- (or ?)

La variable de parámetro / límite @Lastname (sería un ? en Java) se traducirá correctamente a O'Cune . No se requieren negocios divertidos. No hay errores para cazar. Es infinitamente más seguro, y solo puede generar el html entity si es un carácter que rompe páginas.

Entonces, ¿por qué Ruby no arregla esto automáticamente?

¿Por qué deberían? Todavía no he encontrado ninguna implementación de JSON en cualquier idioma que elimine automáticamente estas etiquetas de script. ¿Qué sucede si desea usar JSON para mostrar etiquetas de script por alguna extraña razón en su sitio web?

Al eliminar esta función, está impidiendo que alguien genere código HTML a través de JSON, lo que sospecho podría romper muchas cosas para mucha gente.

Por lo tanto, la respuesta es hacerlo usted mismo . Reemplace esas etiquetas de script con entidades HTML antes de que se serialicen y devuelvan.

    
respondido por el Mark Buffalo 19.12.2015 - 23:31
fuente
8

Hacer los insumos seguros es mejor hacerlo lo más tarde posible. Es decir, cuando los datos se envían a la página. En general, los datos de entrada de "desinfección" son malos porque es imposible distinguir entre datos buenos y datos malos en esta etapa (como usted dice, si está permitiendo que sus usuarios ingresen HTML, el marco no puede distinguir la diferencia entre HTML que está destinado a estar allí vs HTML que no está). Incluso con el script en la entrada, a veces esto puede ser válido (piense en los cuadros de texto StackOverflow / StackExchange que contienen código).

Tan tarde como sea posible, entonces su aplicación debería estar codificada en el formato en que esté la salida. Por ejemplo, HTML o JSON. Con el signo anterior y & se convierte en &amp; para que se muestre correctamente para su visualización, para este último se debe usar un codificador JSON que convertirá de & a \x26 dentro de una cadena JSON.

El JSON en sí no es un riesgo XSS ya que el script no se ejecuta en un navegador desde una solicitud JSON (JSONP es otro asunto, ya que estos se incluyen con las referencias del src del script en lugar de cargarlos como datos). El riesgo de XSS con JSON es cuando JavaScript en la página intenta crear o completar elementos HTML con los datos JSON recuperados. El propio JavaScript debe codificar HTML los datos o usar miembros de objetos seguros para completar el DOM (por ejemplo, textContent ).

La desinfección se puede realizar como una capa adicional, sin embargo, el enfoque debe ser la codificación adecuada. Por ejemplo, es posible que desee validar del lado del servidor que un código postal o código postal solo contiene caracteres alfanuméricos y el carácter de espacio. Para campos más complejos, esta no es una opción sin limitar gravemente sus capacidades de entrada.

Algunos marcos intentan sanear globalmente los datos, como .NET con el uso de solicitar validación . Sin embargo, se encuentran vulnerabilidades todo el tiempo, incluyendo esta muy reciente . En resumen, no funciona y causa problemas funcionales para los idiomas que lo intentan. Tampoco ofrece protección contra XSS en los datos que se recuperan de otras fuentes que no sean la aplicación en sí.

    
respondido por el SilverlightFox 19.12.2015 - 10:35
fuente

Lea otras preguntas en las etiquetas