De hecho, soy un ingeniero en VIP que revisa mucho el código :) Marco muchos escapes que faltan.
pero no escapa a la salida
No del todo, no se escapa en la salida, lo que es sorprendente para la mayoría de las personas. Esto se debe a que si eres un súper administrador tienes la unfiltered_html
capacidad, por lo que no puede escapar en la salida. En cambio, lo ejecuta wp_kses_post
en la entrada. Sin embargo, lo ideal sería eliminar esa capacidad.
Aquí está la implementación en el momento actual:
function the_content( $more_link_text = null, $strip_teaser = false ) {
$content = get_the_content( $more_link_text, $strip_teaser );
/**
* Filters the post content.
*
* @since 0.71
*
* @param string $content Content of the current post.
*/
$content = apply_filters( 'the_content', $content );
$content = str_replace( ']]>', ']]>', $content );
echo $content;
}
Por the_content
otro lado, el mecanismo ideal para escapar de todo lo que pasa por el filtro es:
echo apply_filters( 'the_content', wp_kses_post( $content ) );
De esta manera, hacemos que el contenido sea seguro, luego lo ejecutamos a través del filtro, evitando que se eliminen las incrustaciones, etc.
Entonces, ¿por qué escapar?
El punto de escapar es generar HTML válido, la seguridad adicional que proporciona es solo un buen efecto secundario.
Para evitar que los usuarios rompan accidentalmente el marcado
Hay muchas razones para escapar, pero fundamentalmente, estás haciendo cumplir las expectativas. Toma el siguiente código:
<a href="<?=$url?>">
Esperamos $url
contener una URL adecuada para un href
atributo, pero ¿y si no lo es? Bueno, ¿por qué dejarlo al azar?
<a href="<?=esc_url( $url )?>">
Ahora siempre será una URL. No importa si un pirata informático coloca una imagen $url
, o si un usuario escribe en el campo incorrecto, o si hay un script malicioso. Siempre será una URL válida porque dijimos que será una URL. Claro que puede ser una URL muy extraña, pero siempre cumplirá con las expectativas de que haya una URL allí. Esto es muy útil, ya sea para la validación de marcado, por seguridad, etc.
Habiendo dicho eso, escapar no es validación, escapar no es desinfección. Esos son pasos separados que suceden en diferentes puntos del ciclo de vida. Escapar obliga a que las cosas cumplan con las expectativas, incluso si eso las destruye.
A veces me gusta pensar en escapar como uno de esos juegos japoneses con la pared de espuma gigante con el corte. Los concursantes tienen que adaptarse a la forma del perro o se descartan, solo para nuestros propósitos hay láseres y cuchillos alrededor del agujero. Lo que quede al final tendrá forma de perro, y será implacable y estricto si aún no tiene forma de perro.
Recuerda:
- desinfectar temprano
- validar temprano
- escapar tarde
- escapar a menudo
La seguridad es un paso múltiple, una cebolla de defensa de múltiples capas, el escape es una de las capas externas de defensa en la salida. Puede destrozar el código de ataque en un sitio comprometido haciéndolo inútil, frustrar exploits abiertos y asegurarse de que su cliente no rompa un sitio colocando etiquetas en un campo que no debería. No es un sustituto de las otras cosas, y es, con mucho, la herramienta de seguridad más infrautilizada en un manual para desarrolladores.
¿En cuanto a por qué escapar si the_content
no es así? Si viene una inundación y 5 agujeros en una pared, pero solo es tiempo de arreglar 3, ¿se encoge de hombros y no arregla ninguno? ¿O mitiga el riesgo y reduce el área de ataque?
Quizás pueda ayudar a arreglar esos 2 agujeros finales con este fragmento:
add_filter( 'the_content' function( $content ) {
return wp_kses_post( $content );
}, PHP_INT_MAX + 1 );
Aquí establecemos la prioridad al número más alto posible en PHP, luego agregamos 1 para que se desborde al número más bajo posible que se pueda representar. De esta forma, todas las llamadas a the_content
escaparán del valor antes que cualquier otro filtro. De esta manera, las incrustaciones, etc. todavía funcionan, pero los usuarios no pueden colarse en HTML peligroso a través de la base de datos. Además, busca eliminar la unfiltered_html
capacidad de todos los roles
wp_kses_post