¿Por qué este vector:
<svg><script>alert(/1/.source)</script>
funciona en enlace y este
<script>alert(/1/.source)</script>
no lo hace. ¿Cómo hace <svg>
para que funcione?
HTML <script>
tiene poderes especiales que otros elementos no tienen: es un "elemento CDATA". Eso significa que cualquier carácter de <
o &
hasta el final del elemento se considera que significa literalmente esos caracteres. Entonces, lo que se pasa al intérprete de JS es:
alert(/1/.source)
que obviamente no es una sintaxis JS válida.
El concepto de "elemento CDATA" proviene del mundo SGML a partir del cual se desarrolló HTML. Pero SVG proviene del mundo XML donde las cosas se simplifican y no hay elementos CDATA. En consecuencia, el elemento SVG <script>
no tiene poderes especiales: dentro de un script SVG, <
introduce una etiqueta y &
introduce una entidad o referencia de carácter.
En consecuencia, (
se analiza a (
y la cadena resultante que se pasa al intérprete de JS es:
alert(/1/.source)
En términos XML, el elemento <script>
está en el espacio de nombres HTML y el elemento <svg><script>
está en el espacio de nombres SVG, por lo que son elementos diferentes. HTML5 hace que todo esto sea menos claro al ocultar los prefijos de espacio de nombres y al aplicar un analizador no XML al SVG (por eso (
funciona a pesar de que no está bien formado; debería ser (
).
El #
(hash, sharp, pound) rompe tu Javascript. Dentro de un par de etiquetas <svg>
(no se proporciona su etiqueta de cierre), el número de la entidad se traduce a su referencia de caracteres adecuada, ya que se procesa como html, luego el motor ejecuta el script ECMA (que está permitido hacer para dibujar) .
OWASP.org documenta esto como codificación hexadecimal sin punto y coma .