Creo que, a diferencia de lo que otros han sugerido, no significa prevención contra la inyección de tipo XSS en HTML. Demostraré con un ejemplo generalizado de una recompensa de errores de XSS que obtuve de un sitio web de los 1000 mejores.
Digamos que tienes una API JSONP (que, desde el principio, es una idea terrible).
Una API del tiempo
Esta API de JSONP devuelve el clima, a través del origen sin utilizar CORS con el que buscamos el lugar donde queremos el clima. JSONP significa que lo carga como un script, como este:
* http://mywebsite.com/use-weather-api.php *
<script>
function weatherCallback(data) { alert(data.weather) }
</script>
<script src='http://example.com/weather-api?place=$_GET["place"]&callback=weatherCallback'></script>
El contenido de este script se generará en función de las entradas, utilizando la devolución de llamada para pasar la respuesta al contexto principal, por ejemplo, si $_GET["place"]
es "london"
:
weatherCallback({"weather": "rainy"})
La función weatherCallback luego se llama con la carga JSON de la API, diciendo que el clima es lluvioso.
Contrapunto: Inyección de HTML
Supongamos que no hacemos desinfección o desinfección contextual en nuestros insumos. Ahora, el XSS más simple y obvio que podemos hacer es enviar un lugar que use inyección de HTML para obtener XSS.
* http://mywebsite.com/use-weather-api.php?place='><script>alert('xss!')</script> *
<script>
function weatherCallback(data) { alert(data.weather) }
</script>
<script src='http://example.com/weather-api?place='><script>alert('xss!')</script>&callback=weatherCallback'></script>
Vea aquí que al agregar ingenuamente el parámetro a nuestro HTML, en la última línea le permitimos al atacante agregar HTML adicional que genera las etiquetas de script adicionales que, a su vez, les permiten agregar código adicional para controlar nuestra página web, también conocida como XSS . Esta es una versión extendida de lo que otros han proporcionado como ejemplo anterior.
La codificación de URL no soluciona esto
Sin embargo, en este caso de ejemplo, deberíamos resolver este no mediante la codificación de URL, pero mediante la codificación HTML. Si reemplazamos $_GET["place"]
con urlencode($_GET["place"])
, entonces es posible que algunos caracteres no se escapen, especialmente '
(porque no es una entidad URL), lo que significa que aún podemos obtener XSS :
* http://mywebsite.com/use-weather-api.php?place='onload='alert(1) *
<script>
function weatherCallback(data) { alert(data.weather) }
</script>
<script src='http://example.com/weather-api?place='onload='alert(1)'callback=weatherCallback'></script>
En este caso, llegamos a XSS inyectando un parámetro separado a nuestra etiqueta <script>
que establece un evento malicioso onLoad
. Podemos hacer esto porque los caracteres especiales HTML clave no se escapan mediante la codificación de URL.
Inyección de parámetros de consulta
Supongamos que ahora tenemos una perfecta desinfección de HTML. La garantía que el sanitario de HTML nos dará es que evita que las cosas que agregamos escapen de las entidades HTML en las que están colocadas, lo que hace que nuestros ataques anteriores fallen. Sin embargo, tenemos un último truco bajo la manga, inyectándolo en el contexto de la URL:
* http://mywebsite.com/use-weather-api.php?place=london%26callback=alert# *
<script>
function weatherCallback(data) { alert(data.weather) }
</script>
<script src='http://example.com/weather-api?place=london&callback=alert#callback=weatherCallback'></script>
En este caso, a pesar de la perfecta desinfección de HTML y la falta de desinfección contextual de la URL, hemos permitido que se inyecten parámetros de consulta adicionales en nuestro URI de solicitud. Tenga en cuenta que &
está codificado en &
, pero se descodificará en &
cuando llegue al analizador de URL del navegador.
Debido a que el parámetro de devolución de llamada 'correcto' se ha 'editado' con #
, y nuestro virus malicioso se ha inyectado, el script generado será:
alert({"weather": "rainy"})
Permitiéndonos llamar a cualquier función como la página web (es decir, XSS). Podemos ir más lejos y, en muchos casos, escribir cualquier javascript que queramos aquí, no solo llamadas de función, por ejemplo:
alert('hello!');({"weather": "rainy"})
Donde nuestros parámetros de consulta son place=london&callback=alert('hello!')#callback=weatherCallback
.
Este es un caso en el que es importante urlencode y luego codificar HTML.
Entonces, ¿qué puedo hacer?
No hagas esto manualmente. Ya no son los días de MySpace. Utilice un sistema de plantillas que proporcione saneamiento contextual . Esto significa que entiende dónde está colocando sus entradas en el HTML y, en su mayor parte, utiliza automáticamente la secuencia correcta de escapes para garantizar que no se produzca una inyección de código malintencionado. Hoy hablamos sobre la sintaxis de URL en la sintaxis HTML, pero a veces tienes una URL dentro de una etiqueta <script>
dentro de HTML, en cuyo caso necesitas que la URL se escape, luego que javascript se escape, luego que HTML se escape. ¡Es enloquecedor!
La mayoría de los buenos sistemas de plantillas lo hacen en estos días. El predeterminado de PHP no, pero hay otras opciones que puedes usar. Asegúrese de que la opción que elija sea segura para XSS.