Pasando el código PHP directamente a JavaScript en HTML5

5

Quiero pasar una cadena de PHP directamente a una variable de JavaScript y mantener la carga en el servidor al mínimo. Tengo el siguiente JavaScript en un archivo PHP para hacer esto:

<!DOCTYPE html>
<html>
...
<body>

<section id="section1"></section>

<script>
var example = <?php json_encode($string_var, JSON_HEX_TAG);?>;
example.replace(/[<>]/g, (m) => {return m == "<"? "&lt;" : "&gt;";});
document.getElementById('section1').innerHTML = example;
</script>

...
</body>
</html>

La variable $string_var que viene de PHP es una entrada del usuario que no fue saneada de ninguna manera (es decir, ni siquiera ejecuté htmlspecialchars() en ella).

¿Es seguro mi ejemplo? ¿O necesito usar todos estos indicadores para json_encode , es decir, JSON_HEX_QUOT | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS ? Sé que este ejemplo no sigue las mejores prácticas, pero ¿existe algún riesgo concreto o vulnerabilidad en él?

Referencias:

  1. ¿Por qué usar JSON_HEX_TAG ?
  2. Respuestas recomendando indicadores JSON_HEX_QUOT | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS para PHP json_encode :
pregunta flen 16.12.2017 - 23:52
fuente

1 respuesta

4

JSON_HEX_TAG

Si está haciendo eco en JS dentro de un documento HTML (como lo está en su ejemplo), es necesario o corre el riesgo de abrir una gran vulnerabilidad de XSS. Sin este, un atacante puede publicar algo como esto:

</script>alert("XSS");</script>

Desde PHP 5.4, esto se ha solucionado y las barras diagonales se escapan de forma predeterminada, pero aún así, nunca se sabe en qué versión de PHP se ejecutará su código. Mejor prevenir que lamentar.

Como señala OP, incluso en las versiones nunca de PHP puede insertar un <!-- para desordenar toda la página, lo que posiblemente cause un comportamiento inesperado. Así que la bandera es realmente necesaria en todas las versiones de PHP.

JSON_HEX_QUOT y JSON_HEX_APOS

Para entender lo que esto hace, eche un vistazo al siguiente ejemplo:

$array = array(
    "a" => "'",
    "b" => '"',
);

// This will output {"a":"'","b":"\""}
echo json_encode($array);

// This will output {"a":"\u0027","b":"\u0022"}
echo json_encode($array, JSON_HEX_QUOT | JSON_HEX_APOS);

Por lo tanto, las comillas alrededor de los literales de cadena nunca se codifican. Las citas dentro de los literales de cadena serán escapadas sin las banderas, y codificadas con ellas.

De acuerdo con sus referencias, esto se usa para hacer que la salida sea segura para usar dentro de los controladores de eventos (es decir, los atributos HTML). Es cierto que no son estrictamente necesarios dentro de las etiquetas de script, pero no es del todo correcto que estén a salvo en los controladores de eventos.

Eche un vistazo a este ejemplo, por ejemplo:

<?php $data = array(" onmouseenter=alert(1) " => "foo"); ?>
<a onclick="x = <?= json_encode($data, JSON_HEX_QUOT | JSON_HEX_APOS); ?>">test</a>

Resultando en:

<a onclick="x = {" onmouseenter=alert(1) ": "foo"}">test</a>

Creo que estás seguro si siempre encierras los valores de tus atributos entre comillas simples, pero aún así parece un poco arriesgado.

JSON_HEX_AMP

Cotizando su referencia aquí:

  

Para compatibilidad con bloques de script XHTML no CDATA, haga & también.

Entonces, como estás haciendo HTML5, esto no se aplica a ti, y no creo que haya una vulnerabilidad de seguridad aquí de todos modos. Sin embargo, no hace daño codificar.

Conclusión

  • Para su uso, dentro de una etiqueta de script en HTML5, solo usar JSON_HEX_TAG es suficiente.
  • Hacer esto dentro de los atributos (controladores de eventos) es peligroso, al menos a menos que esté entre comillas simples.
  • Si fuera usted, crearía una pequeña función de ayuda llamada safe_json_encode que usa las cuatro marcas, y luego la usaría solo en las etiquetas de secuencia de comandos. Codificar más de lo necesario no te hace daño.

Notas adicionales

  • Asegúrese de servir la página con un tipo de contenido y codificación de caracteres correctos. Desordenar esto puede llevar a maneras de evitar la codificación.
  • Si luego envía los valores de las variables a HTML, debe pensar en XSS nuevamente. Usando los valores de su JSON en, por ejemplo. innerHTML o document.write no serán seguros. (Veo que lidias con esto en tu segunda línea de guión).

Descargo de responsabilidad: > Esto se basa en la investigación que realicé hoy. No soy un gurú de PHP. Si confías en esto para algo crítico, probablemente quieras investigar más por tu cuenta para asegurarte de que no me esté perdiendo algo aquí.

    
respondido por el Anders 17.12.2017 - 00:30
fuente

Lea otras preguntas en las etiquetas