Noté un comportamiento que me está costando entender. Considere el siguiente fragmento de código:

<input type="button" value="test" onclick="window.location.href = &quot;foo;bar;&quot;">

Cuando hago clic en el botón de prueba, redirige la página a http://www.example.com/foo;bar ;. Así que todo entre " caracteres se trata como un literal de cadena, como si " eran personajes de citas reales. Mi expectativa sería que, dado que " los caracteres están codificados, no podrían influir en la ejecución del código, por lo que esperaría que el punto y coma entre foo y bar termine la asignación a window.location.href y que javascript vea bar como una declaración separada.

Solo para confirmar aún más que eso es lo que está sucediendo, si elimino el primer " y hago clic en el botón me sale el siguiente error en la consola:

SyntaxError: unterminated string literal

window.location.href = foo;bar;"

(con una flecha que indica el final ", que en realidad es un ", es el problema).

¿Qué me estoy perdiendo? ¿El carácter codificado está siendo decodificado por el motor javascript antes de ejecutarlo? ¿Qué pasa si esto involucra la entrada del usuario y la aplicación intenta codificar los caracteres de comillas como " para evitar secuencias de comandos en sitios cruzados, ¿un atacante aún podrá escapar porque su " seguirá siendo honrado como una cita real?

respuesta

Parece que estás invirtiendo tu orden de análisis.

El analizador HTML convierte el valor del atributo en texto (así &quot;se convierte en "). Luego , ese texto se pasa al motor de JavaScript.

Así que lo que tienes está bien y funciona como debería.


Is the encoded character being decoded by the javascript engine before executing it?

No, el analizador de HTML lo decodifica antes de que el motor de JavaScript llegue a verlo.

What if this involves user input, and the application tries encoding quote characters as " to prevent cross-site scripting, will an attacker still be able to break out because his " will still be honoured as a real quote?

Suponiendo que quiere decir que el servidor toma la entrada del usuario, ejecute una rutina de codificación HTML estándar para que sea seguro para insertar en HTML y luego inserte en el HTML:

Si el usuario escribe &quot;, la aplicación del lado del servidor lo codificará como &amp;quot;, y el analizador HTML lo decodificará de nuevo &quot;y no ".

Por supuesto, si está insertando la entrada del usuario en JavaScript (incluso si ese JavaScript también está dentro de un atributo HTML), entonces deberá escapar para JS antes de escapar para HTML.

Por ejemplo, usando PHP como es común:

<?php
$unsafe_input = $_GET['data'];
$js_safe_input = json_encode($unsafe_input);
$html_safe_input = htmlspecialchars($js_safe_input);
?>
<input type="button" onclick="alert(<?php echo $html_safe_input; ?>)" value="click">

Debe usar comillas escapadas en su lugar

<input type="button" value="test" onclick="window.location.href = "\"foo;bar\"">

o use comillas simples también

<input type="button" value="test" onclick="window.location.href = 'foo;bar;'">