php - remove - ¿Strip_tags() es vulnerable a los ataques de scripting?
strip_tags php ejemplo (4)
Como su nombre puede sugerir, strip_tags
debería eliminar todas las etiquetas HTML. La única forma en que podemos probarlo es analizando el código fuente. El siguiente análisis se aplica a una strip_tags(''...'')
, sin un segundo argumento para las etiquetas incluidas en la lista blanca.
En primer lugar, alguna teoría sobre etiquetas HTML: una etiqueta comienza con un <
seguido de caracteres que no sean de espacios en blanco. Si esta cadena comienza con a ?
, no debe ser analizado . Si esta cadena comienza con un !--
, se considera un comentario y el siguiente texto tampoco debe analizarse. Un comentario termina con un -->
, dentro de dicho comentario, los caracteres como <
y >
están permitidos. Los atributos pueden aparecer en etiquetas, sus valores pueden estar rodeados opcionalmente por un carácter de comillas ( ''
o "
). Si existe dicha cita, debe cerrarse; de lo contrario, si a >
se encuentra, la etiqueta no está cerrada.
El código <a href="example>xxx</a><a href="second">text</a>
se interpreta en Firefox como:
<a href="http://example.com%3Exxx%3C/a%3E%3Ca%20href=" second"="">text</a>
La función PHP strip_tags
se referencia en la línea 4036 de ext / standard / string.c . Esa función llama a la función interna php_strip_tags_ex .
Existen dos almacenamientos intermedios, uno para la salida y el otro para "dentro de etiquetas HTML". Una depth
llamada contador contiene la cantidad de corchetes angulares abiertos ( <
).
La variable in_q
contiene el carácter de cita ( ''
o ''
"
) si lo hay, y 0
caso contrario. El último carácter se almacena en la variable lc
.
Las funciones tienen cinco estados, tres se mencionan en la descripción anterior de la función. Con base en esta información y el cuerpo de la función, se pueden derivar los siguientes estados:
- El estado 0 es el estado de salida (no en ninguna etiqueta)
- El estado 1 significa que estamos dentro de una etiqueta html normal (el buffer de etiqueta contiene
<
) - State 2 significa que estamos dentro de una etiqueta php
- Estado 3: venimos del estado de salida y encontramos el
<
y!
caracteres (el buffer de etiqueta contiene<!
) - Estado 4: comentario HTML interno
Solo debemos tener cuidado de que no se pueda insertar ninguna etiqueta. Es decir, <
seguido de un personaje que no es de espacio en blanco. La línea 4326 comprueba un caso con el <
carácter que se describe a continuación:
- Si hay comillas internas (por ejemplo,
<a href="inside quotes">
), se ignora el<
carácter (eliminado de la salida). - Si el siguiente carácter es un carácter de espacio en blanco,
<
se agrega al búfer de salida . - si está fuera de una etiqueta HTML, el estado pasa a ser
1
("dentro de la etiqueta HTML") y el último carácterlc
se establece en<
- De lo contrario, si está dentro de una etiqueta HTML, la
depth
del contador se incrementa y el personaje se ignora.
Si >
se cumple mientras la etiqueta está abierta ( state == 1
), in_q
convierte en 0
("no en una cita") y el state
convierte en 0
("no en una etiqueta"). El buffer de etiquetas se descarta.
Las comprobaciones de atributos (para caracteres como ''
y ''
"
) se realizan en el buffer de etiqueta que se descarta. Por lo tanto, la conclusión es:
strip_tags sin una etiqueta whitelist es seguro para su inclusión fuera de las etiquetas, no se permitirá ninguna etiqueta.
Por "etiquetas externas", me refiero a no <a href="in tag">outside tag</a>
etiquetas como en <a href="in tag">outside tag</a>
. El texto puede contener <
y >
, como en >< a>>
. Sin embargo, el resultado no es válido en HTML, <
, >
y &
aún deben escaparse, especialmente el &
. Eso se puede hacer con htmlspecialchars()
.
La descripción de strip_tags
sin un argumento de lista blanca sería:
Se asegura de que no exista etiqueta HTML en la cadena devuelta.
¿Hay un XSS conocido u otro ataque que lo haga pasar por un
$content = "some HTML code";
$content = strip_tags($content);
echo $content;
?
El manual tiene una advertencia:
Esta función no modifica ningún atributo en las etiquetas que permite usar allowable_tags, incluidos los atributos de estilo y onmouseover que un usuario travieso puede abusar al publicar texto que se mostrará a otros usuarios.
pero eso está relacionado con el uso del parámetro allowable_tags
solamente.
Sin etiquetas permitidas , ¿ strip_tags()
vulnerable a cualquier ataque?
Chris Shiflett parece decir que es seguro:
Usa soluciones maduras
Cuando sea posible, use soluciones maduras existentes en lugar de tratar de crear la suya propia. Las funciones como strip_tags () y htmlentities () son buenas opciones.
¿es esto correcto? Por favor, si es posible, cita las fuentes.
Sé sobre HTML purifier, htmlspecialchars () etc.- No estoy buscando el mejor método para desinfectar HTML. Solo quiero saber acerca de este problema específico. Esta es una pregunta teórica que surgió here .
Referencia: implementación de strip_tags()
en el código fuente de PHP
De acuerdo con esta herramienta en línea , esta cadena será "perfectamente" escapada, ¡pero el resultado es otro malicioso!
<<a>script>alert(''ciao'');<</a>/script>
En la cadena, las etiquetas "reales" son <a>
y </a>
, ya que <
y script>
solo no son etiquetas.
Espero estar equivocado o que sea solo por una versión anterior de PHP, pero es mejor verificar en su entorno.
No puedo predecir exploits futuros, especialmente porque no he buscado el código fuente de PHP para esto. Sin embargo, ha habido exploits en el pasado debido a que los navegadores aceptan etiquetas aparentemente inválidas (como <s/0cript>
). Entonces, es posible que en el futuro alguien pueda explotar el comportamiento extraño del navegador.
Aparte de eso, enviar la salida directamente al navegador como un bloque completo de HTML nunca debería ser inseguro:
echo ''<div>''.strip_tags($foo).''</div>''
Sin embargo, esto no es seguro:
echo ''<input value="''.strip_tags($foo).''" />'';
porque uno podría terminar fácilmente la cita a través de "
e insertar un controlador de scripts".
Creo que es mucho más seguro convertir siempre a los extraviados <
en <
(y lo mismo con las comillas).
Strip tags es perfectamente seguro, si todo lo que estás haciendo es enviar el texto al cuerpo html.
No es necesariamente seguro ponerlo en los atributos de mysql o url.