¿La forma correcta de protegerse contra XSS, cuando la salida está directamente en JS no en HTML?

8

Veo muchos ejemplos cuando la salida va directamente a HTML, pero veo más información conflictiva cuando la salida va directamente a JS.

Por ejemplo, si el código era:

var thisIsATest = '<?php echo $_GET['a']; ?>';

Y el vector de ataque de URL fue:

?a=';alert(1);'

La salida se procesa como:

var thisIsATest = '';alert(1);'';

He visto un montón de documentos que recomiendan qué evitar (como las barras de adición), y referencias a htmlspecialchars () (pero no por sí mismo) ...

¿Cuál es el enfoque más correcto?

    
pregunta Jason Vendryes 09.01.2016 - 00:41
fuente

1 respuesta

12

La forma correcta es usar las herramientas de su marco (y su motor de plantilla, si está disponible). Si estás jugando con PHP en cadenas JS, probablemente harás la vida más difícil y más peligrosa de lo necesario.

Con PHP simple, un enfoque común y seguro es utilizar json_encode() como se explica aquí . Por ejemplo:

var foo = <?php echo json_encode($foo, JSON_HEX_QUOT|JSON_HEX_TAG|JSON_HEX_AMP|JSON_HEX_APOS); ?>

json_encode() devuelve la representación JSON de un valor, por lo tanto, se garantiza que se evaluará a un objeto válido en su código JS y puede asignarlo a una variable como se muestra. Pero no omita las marcas adicionales. Dependiendo del contexto, un atacante podría usar cargas útiles como </script> para romper la etiqueta de secuencia de comandos completa.

Las funciones htmlentities() y htmlspecialchars() a las que hizo referencia se usan para salida HTML directa y no deben emplearse en JS. También permitirían que su cadena contenga saltos de línea, lo que resultaría en un error de sintaxis que podría tener consecuencias de seguridad.

Hablando de marcos, Wordpress te da el envoltorio wp_json_encode() , como se recomienda en esta guía . Puede haber funciones equivalentes para su propio marco.

También tenga en cuenta que con json_encode() el objeto está preparado de manera segura para un contexto JS, pero cualquier cadena que pase puede contener etiquetas HTML que no sería seguro insertar a través de, por ejemplo, document.write() o innerHTML . (Evita estos dos en total.)

Esto es una tontería, pero es seguro para XSS:

Hello, <span id="display"></span>!
<?php $name = $_GET['name']; ?>
<script>
    var name = <?php echo json_encode($name, JSON_HEX_QUOT|JSON_HEX_TAG|JSON_HEX_AMP|JSON_HEX_APOS); ?>;
    display.textContent = name;
</script>
    
respondido por el Arminius 09.01.2016 - 02:26
fuente

Lea otras preguntas en las etiquetas