model-view-controller - spec - what is html
escape html/XSS en la entrada vs salida (2)
El error original
No confunda el saneamiento del producto con la validación.
Si bien <script>alert(1);</script>
es un nombre de usuario perfectamente válido, definitivamente se debe escapar antes de mostrarse en el sitio web.
Y sí, existe una "lógica de presentación" , que no está relacionada con la " lógica de negocios de dominio" . Y dicha lógica de presentación es lo que trata la capa de presentación. Y las instancias de View
en particular. En un MVC bien escrito, las Vistas son objetos en toda regla (al contrario de lo que RoR trataría de decirle), que, cuando se aplican en contexto web, hacen malabares con varias plantillas.
Sobre tus razones
Los diferentes formatos de salida deben ser manejados por diferentes vistas. Las reglas y restricciones, que rigen HTML, XML, JSON y otros formatos, son diferentes en cada caso.
Siempre necesita almacenar la entrada original (desinfectada para evitar inyecciones, si no está usando declaraciones preparadas), porque alguien podría necesitar editarla en algún momento.
Y almacenar original y la versión "pública" de xss-safe es inútil. Si desea almacenar resultados desinfectados, porque se necesitan demasiados recursos para desinfectarlos cada vez, entonces ya está orinando en el árbol equivocado. Este es un caso, cuando utiliza caché, en lugar de contaminar la base de datos.
De todo lo que he visto, parece que la convención para escaparse html en el contenido ingresado por el usuario (con el propósito de prevenir XSS) es hacerlo cuando se renderiza contenido. La mayoría de los lenguajes de plantillas parecen hacerlo de manera predeterminada, y he encontrado cosas como esta respuesta de stackoverflow argumentando que esta lógica es el trabajo de la capa de presentación.
Entonces mi pregunta es, ¿por qué es este el caso? Para mí, parece más limpio escapar en la entrada (es decir, la validación de formulario o modelo) para que pueda trabajar bajo la suposición de que todo lo que se encuentra en la base de datos es seguro para mostrar en una página, por las siguientes razones:
Variedad de formatos de salida: para una aplicación web moderna, puede estar usando una combinación de renderizado html del lado del servidor, una aplicación web javascript con ajax / JSON y una aplicación móvil que recibe JSON (y que puede o no tener algunas vistas web, que pueden ser aplicaciones de JavaScript o html procesado por el servidor). Entonces tienes que lidiar con html escapando por todos lados. Pero la entrada siempre se instanciará como un modelo (y validada) antes de guardarse en db, y todos sus modelos pueden heredar de la misma clase base.
Ya debe tener cuidado con los datos de entrada para evitar ataques de inyección de código (siempre que esto se abstraiga normalmente del cursor ORM o db, pero aún así), así que ¿por qué no preocuparse también de que html escape aquí para no tener que preocuparse por nada? relacionado con la seguridad en la salida?
Me encantaría escuchar los argumentos sobre por qué se prefiere html escapar en el procesamiento de la página
Además de lo que ya se ha escrito:
Precisamente porque tiene una variedad de formatos de salida, y no puede garantizar que todos ellos necesiten escapes de HTML. Si está publicando datos a través de una API JSON, no tiene idea de si el cliente lo necesita para una página HTML o una salida de texto (por ejemplo, un correo electrónico). ¿Por qué deberías obligar a tu cliente a deshacer el "
Jack & Jill
" para obtener "Jack & Jill"?Estás corrompiendo tus datos por defecto.
Cuando alguien hace una búsqueda de palabra clave para ''amplificador'', obtienen "Jack & Jill". ¿Por qué? Porque corrompiste tus datos.
Supongamos que una de las entradas es una URL:
http://example.com/?x=1&y=2
. Desea analizar esta URL y extraer el parámetroy
, si existe. Esto falla silenciosamente, porque su URL se ha dañado enhttp://example.com/?x=1&y=2
.
Simplemente es la capa incorrecta para hacerlo: las cosas relacionadas con HTML no deberían mezclarse con el manejo HTTP sin formato. La base de datos no debe almacenar elementos relacionados con un posible formato de salida.
XSS y SQL Injection no son los únicos problemas de seguridad, existen problemas para cada salida con la que se trata, como el sistema de archivos (pense extensiones como ''.php'' que hace que los servidores web ejecuten código) y SMTP (piense en caracteres de nueva línea) y cualquier cantidad de otros Pensar que puede "lidiar con la seguridad con los datos ingresados y luego olvidarse de eso" disminuye la seguridad. Más bien debería delegar escapes a servidores específicos que no confían en sus datos de entrada.
No debería estar escapando HTML "por todos lados". Deberías hacerlo exactamente una vez por cada salida que lo necesite, como con cualquier escape para cualquier back-end. Para SQL, debe hacer SQL escapándose una vez , lo mismo ocurre con SMTP, etc. Por lo general, no escapará; utilizará una biblioteca que lo maneje por usted.
Si está utilizando frameworks / bibliotecas sensibles, esto no es difícil. Nunca aplico manualmente escapes SQL / SMTP / HTML en mis aplicaciones web, y nunca tengo vulnerabilidades de inyección XSS / SQL. Si su método de creación de páginas web requiere que recuerde aplicar el escape, o que termine con una vulnerabilidad, lo está haciendo mal.
Hacer escapes en el nivel de entrada form / http no garantiza la seguridad, porque nada garantiza que los datos no entren en su base de datos o sistema desde otra ruta. Debe asegurarse manualmente de que todas las entradas de su sistema estén aplicando el escape de HTML.
Puede decir que no tiene otras entradas, pero ¿qué sucede si su sistema crece? A menudo es demasiado tarde para volver atrás y cambiar su decisión, porque para este momento tiene una gran cantidad de datos y puede tener compatibilidad con interfaces externas, por ejemplo, API públicas de las que preocuparse, que todos esperan que los datos sean escapes de HTML.
Incluso las entradas web al sistema no son seguras, porque a menudo tiene otra capa de codificación aplicada, por ejemplo, puede necesitar una entrada codificada en base64 en algún punto de entrada. Su escaneo automático de HTML se perderá cualquier HTML codificado dentro de esos datos. Por lo tanto, tendrá que volver a escanear HTML, y recuerde hacerlo, y lleve un registro de dónde lo ha hecho.
He ampliado estos aquí: http://lukeplant.me.uk/blog/posts/why-escape-on-input-is-a-bad-idea/