2012-05-01 29 views
7

¿Cuál es la forma correcta de codificar datos no confiables para el contexto de atributos HTML? Por ejemplo:PHP: HTML Codificación de atributo/JavaScript Decodificación

<input type="hidden" value="<?php echo $data; ?>" /> 

lo general el uso htmlentities() o htmlspecialchars() Para ello:

<input type="hidden" value="<?php echo htmlentities($data); ?>" /> 

Sin embargo, hace poco encontré con un problema por el que se trataba de romper mi solicitud cuando los datos que necesitaba para pasar era una URL que debía ser entregado fuera de JavaScript para cambiar la ubicación de esta página:

<input id="foo" type="hidden" value="foo?bar=1&amp;baz=2" /> 
<script> 
    // ... 
    window.location = document.getElementById('foo').value; 
    // ... 
</script> 

En este caso, foo es un programa C, y no comprende los caracteres codificados en la URL y segfaults.

Simplemente puedo tomar el valor en JavaScript y hacer algo como value.replace('&amp;', '&'), pero parece kludgy, y solo funciona para ampersands.

Entonces, mi pregunta es: ¿hay una mejor manera de ir sobre la codificación o decodificación de datos que se inyecta en los atributos de HTML?

He leído todo OWASP's XSS Prevention Cheatsheet, y me parece que siempre que tenga cuidado de citar mis atributos, entonces el único carácter que necesito codificar es la propia cita (") - en cuyo caso, yo podría usar algo como str_replace('"', '&quot;', ...) - pero no estoy seguro si lo estoy entendiendo correctamente.

+2

No urlencode cuidar de que en PHP? Hay pocos ejemplos de código en los comentarios que muestran cómo protegerse contra XSS también en el manual de php. http://php.net/manual/en/function.urlencode.php – GillesC

+0

@gillesc: 'urlencode()' es para codificar URL * parámetros *, no direcciones URL enteras, y no codifica para el contexto de atributo HTML. Hay una sección en el manual que incluso habla de esto: * "Déjalo como &, pero simplemente codifica tus URL usando htmlentities() o htmlspecialchars()." * – FtDRbwLXw6

+0

¿estás seguro de 'window.location = document.getElementById ('foo'); '? debería ser así, creo-> 'window.location = document.getElementById ('foo'). value;' y redirige a la página de la derecha (foo? bar = 1 & baz = 2) – ocanal

Respuesta

11

Su método actual de utilizar htmlentities() o htmlspecialchars() es el enfoque correcto.

El ejemplo que ya ha proporcionado es correcta HTML:

<input id="foo" type="hidden" value="foo?bar=1&amp;baz=2" /> 

El signo en el valor del atributo en efecto necesitan ser codificados en HTML, de lo contrario el código HTML es válido. La mayoría de los navegadores lo analizarían correctamente con un & allí, pero eso no cambia el hecho de que no es válido y es correcto codificarlo.

Su problema no radica en la codificación del valor, que es bueno, sino en el hecho de que está utilizando un código JavaScript que no lo decodifica correctamente.

De hecho, estoy sorprendido de esto, porque su código JS está accediendo al DOM, y el DOM debería devolver los valores descodificados.

me escribió una jsFiddle para probar esto a mí mismo: http://jsfiddle.net/qRd4Z/

La ejecución de este, me da un cuadro de alerta con el valor decodificado como lo esperaba. Cambiarlo a console.log también da el resultado que espero. ¿Entonces no estoy seguro de por qué está obteniendo resultados diferentes? ¿Tal vez estás usando un navegador diferente? Vale la pena especificar con cuál estás probando. ¿O tal vez has codificado por duplicado las entidades por error? ¿Puedes confirmar que ese no es el caso?

0

Puede utilizar el DOM para decodificar el valor:

function decodeHTMLSpecialChars(input){ 
    var div = document.createElement('div'); 
    div.innerHTML = input; 
    return div.childNodes.length === 0 ? "" : div.childNodes[0].nodeValue; 
} 

Esto hará que la siguiente cadena:

'http://someurl.com/foo?bar=1&amp;baz=2' 

a esto:

decodeHTMLSpecialChars('http://someurl.com/foo?bar=1&amp;baz=2'); 
// => 'http://someurl.com/foo?bar=1&baz=2 

Y no, para HTML codificación y decodificación, el htmlspecialchars y html escaping es el método estándar y está haciendo el trabajo jus Está bien para ti.

5

¿Cuál es la forma correcta de codificar datos no confiables para el contexto de atributos HTML?

Si agrega comillas dobles alrededor del valor del atributo, htmlspecialchars() es suficiente.

<input id="foo" type="hidden" value="foo?bar=1&amp;baz=2" /> 

Esto es correcto, y el navegador enviará foo?bar=1&baz=2 (decodificado &amp;) al servidor. Si el servidor no está viendo foo?bar=1&baz=2, debe haber codificado el valor dos veces.

Obtener el valor en javascript también debe devolver foo?bar=1&baz=2 (por ejemplo, document.getElementById('foo').value debe devolver).

Vea la fuente de la página usando su navegador y vea la fuente real del campo de entrada.

Si está modificando el valor del campo de entrada utilizando Javascript, entonces la secuencia de comandos debe tener una codificación doble.

Por cierto que su programa no debe segfault a causa de la entrada del usuario mal;)

0

Tenga en cuenta que el uso de htmlentities ya que es doesn no ayuda

Por defecto sólo se codifica " < > &

No escapa ' que puede crear un problema!

Asegúrese de que utiliza Banderas de las funciones, se encuentra el uso y ejemplos here

+0

Gracias, pero esto solo importaría si no delimita adecuadamente los valores de sus atributos con los caracteres '" ', y lo hago. Es una mala práctica dejar los delimitadores o delimitarlos con' ''. – FtDRbwLXw6

Cuestiones relacionadas