El problema
Abusar de las codificaciones de caracteres es un truco popular para hacer que XSS funcione, incluso cuando hay filtros en su lugar. Hay una serie de situaciones diferentes cuando funciona, pero todas comparten prerrequisitos comunes:
- El atacante envía una carga útil en la codificación de caracteres A.
- El servidor que realiza el filtrado o sanitazion está trabajando en la codificación de caracteres B.
- El navegador de las víctimas está interpretando la página como si estuviera en la codificación de caracteres A.
Veamos dos ejemplos de cómo esto puede ocurrir.
Ejemplo # 1: No hay parámetro de codificación en htmlspecialchars
Esta es una vista bastante común en PHP:
echo htmlspecialchars($_GET["query"], ENT_COMPAT | ENT_HTML401);
El problema aquí es el comportamiento predeterminado al que PHP recurre cuando no se especifica ninguna codificación. De el manual :
Si se omite, el valor predeterminado de la codificación varía según la versión de PHP en uso. En PHP 5.6 y versiones posteriores, la opción de configuración default_charset se usa como valor predeterminado. PHP 5.4 y 5.5 utilizarán UTF-8 como predeterminado. Las versiones anteriores de PHP utilizan ISO-8859-1.
Entonces, qué codificación PHP utiliza depende de su versión y configuración. Genial. Así que ahora todo lo que se interpone entre usted y el abismo es alguien que realiza un cambio inocente en php.ini
, o tal vez algo tan simple como una actualización o reinstalación del servidor. A mí también me gusta vivir peligrosamente ... pero no tan peligrosamente.
Tenga en cuenta que este ejemplo no tiene nada que ver con el navegador. Moderno o viejo, no importa, porque el problema es el servidor y no el navegador.
La solución, por supuesto, es especificar la codificación correcta y asegurarse de que se especifique lo mismo en el encabezado HTTP Content-Type
de la respuesta:
echo htmlspecialchars($_GET["query"], ENT_COMPAT | ENT_HTML401, "UTF-8");
Ejemplo # 2: heurísticas del navegador que te muerden
Esto es un problema si su servidor no especifica qué codificación está usando en la respuesta (o si solo lo hace en una etiqueta meta que está demasiado abajo para que el navegador se preocupe por eso). Si no le dice al navegador qué codificación usar, tendrá que adivinar. Desafortunadamente, todos los navegadores no son tan buenos en eso :
Si ciertas cadenas de entrada del usuario (por ejemplo, +ADw-script+AD4-alert(1)+ADw-/script+AD4-
) se repiten lo suficientemente pronto en la página HTML, Internet Explorer puede suponer incorrectamente que la página está codificada en UTF-7. De repente, la entrada del usuario, de otro modo inofensiva, se convierte en HTML activo y se ejecutará.
La carga útil en la cotización es <script>alert(1)</script>
codificada en UTF-7. Un desinfectante que trabaje en UTF-8 no verá nada peligroso en esa carga útil y lo dejará pasar, pero el navegador con el que se engaña para que funcione en UTF-7 todavía lo ejecutará.
Entiendo que es en su mayoría versiones antiguas de IE donde esto es un problema. Pero no estoy seguro, así que me encantaría ver otra respuesta donde se aclare.
EDIT: Consulte La respuesta de Xavier59 para obtener un situación en la que funciona en los navegadores modernos.
La solución
Lo que debes hacer en el servidor es simple en teoría. Debe asegurarse de que siempre se cumpla lo siguiente:
- La codificación de caracteres de la respuesta se establece correctamente en los encabezados HTTP.
- El filtro XSS está funcionando en la misma codificación que se especificó anteriormente.
En la práctica, es sorprendentemente fácil hacerlo mal.