¿Por qué escapar si el_contenido no lo es?

8

La función integrada se the_contentejecuta a través de varios filtros, pero no escapa a la salida. Sería difícil hacerlo, ya que se debe permitir el acceso a HTML e incluso algunos scripts.

Al generar, el_contenido parece ejecutarse a través de estos filtros (a partir de 5.0):

add_filter( 'the_content', 'do_blocks', 9 );
add_filter( 'the_content', 'wptexturize' );
add_filter( 'the_content', 'convert_smilies', 20 );
add_filter( 'the_content', 'wpautop' );
add_filter( 'the_content', 'shortcode_unautop' );
add_filter( 'the_content', 'prepend_attachment' );
add_filter( 'the_content', 'wp_make_content_images_responsive' );

(and)

add_filter( 'the_content', 'capital_P_dangit' );
add_filter( 'the_content', 'do_shortcode' );

También reemplaza una cadena simple:

$content = str_replace( ']]>', ']]>', $content );

Y luego get_the_content realiza un pequeño procesamiento relacionado con el enlace "más" y un error con idiomas extranjeros.

Ninguno de ellos impide la inyección de script XSS, ¿verdad?

Al guardar, los datos se desinfectan a través de wp_kses_post. Pero como este es un proceso costoso, entiendo por qué no se usa en la salida.

La regla general para el escape de WordPress es que todo debe escaparse, independientemente del saneamiento de entrada, y lo más recientemente posible. He leído varios artículos que dicen esto, porque la base de datos no debe considerarse una fuente confiable.

Pero por las razones anteriores, the_content no sigue eso. Tampoco los temas centrales (es decir, TwentyNineteen) agregan escapes adicionales en la salida.

Entonces ... ¿por qué está ayudando a algo a escapar a otra parte? Si fuera un hacker con acceso a la base de datos, ¿no agregaría mi código al contenido de una publicación?

tmdesigned
fuente
Olvidastewp_kses_post
Tom J Nowell
Se ejecuta a través de wp_kses_post en la salida? ¿Dónde?
tmdesigned

Respuestas:

10

Si fuera un hacker con acceso a la base de datos, ¿no agregaría mi código al contenido de una publicación?

Si tiene acceso a la base de datos, es probable que tenga suficiente acceso para que escapar no lo detenga. Escapar no te ayudará si has sido pirateado. No se supone que lo haga. Hay otras razones para escapar. Los dos principales que se me ocurren son:

Para lidiar con entradas no higienizadas

El contenido de las publicaciones de WordPress se desinfecta cuando se guarda, pero no todo lo demás lo es. El contenido pasado a través de una cadena de consulta en la URL no se desinfecta, por ejemplo. Tampoco el contenido está en los archivos de traducción, necesariamente. Ambas son fuentes de contenido que no tienen nada que ver con el sitio comprometido. Por lo tanto, el texto traducible y el contenido extraído de la URL deben escaparse.

Para evitar que los usuarios rompan accidentalmente el marcado

Escapar no es solo por seguridad. También lo necesita para evitar que los usuarios rompan accidentalmente el marcado de su sitio. Por ejemplo, si el usuario que coloca comillas o >símbolos en algún contenido de su complemento rompería el marcado, entonces debería escapar de esa salida. No desea ser demasiado agresivo al desinfectar la entrada, porque hay razones perfectamente válidas para que un usuario quiera usar esos caracteres.


“Escapar no se trata solo de protegerse de los malos. Solo hace que nuestro software sea duradero. Contra la mala entrada aleatoria, contra la entrada maliciosa o contra el mal tiempo ".

Eso es de las pautas VIP de WordPress para escapar . Tiene mucho más que decir sobre este asunto, y debería leerlo.

Jacob Peattie
fuente
Gracias, eso es útil. Había leído una publicación en VIP sobre el escape y el autor mencionó específicamente la idea de que alguien haya obtenido acceso a la base de datos pero no al servidor. Sin embargo, creo que su razonamiento sobre ese punto tiene más sentido. Y, supongo, a veces estás escapando contenido vulnerable de la base de datos incluso sin que alguien haya tenido acceso completo a la base de datos, es decir, a través de un complemento o incluso solo un comentario.
tmdesigned
9

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_htmlcapacidad, por lo que no puede escapar en la salida. En cambio, lo ejecuta wp_kses_posten 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_contentotro 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 $urlcontener una URL adecuada para un hrefatributo, 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_contentno 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_contentescapará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_htmlcapacidad de todos los roles

Tom J Nowell
fuente
1
Gracias por la perspectiva adicional. En realidad, había leído tu publicación sobre este tema en tu sitio y me preguntaba si tendrías algo que agregar.
tmdesigned
4

El punto de escapar es generar HTML válido, la seguridad adicional que proporciona es solo un buen efecto secundario.

Los filtros aplicados en el contenido generan un HTML válido a partir de algo que es una mezcla de HTML y algún otro texto que tiene otra sintaxis como códigos cortos. El hecho de que parte del contenido ya sea HTML válido impide la aplicación de escape en todo el contenido.

En cuanto a kseslas funciones relacionadas, no puede aplicarlas principalmente porque no tiene suficiente contexto para saber cuál usar. Por ejemplo, puede haber algún proceso que use el the_contentfiltro para agregar JS al contenido de la publicación, por lo que el núcleo no puede adivinar en función de cosas como el autor de la publicación si el JS es legítimo o no.

Entonces ... ¿por qué está ayudando a algo a escapar a otra parte? Si fuera un hacker con acceso a la base de datos, ¿no agregaría mi código al contenido de una publicación?

Nuevamente, escapar es para generar HTML válido. Desde un punto de vista de seguridad, no es que escapar brinde seguridad, sino que un código que tiene suerte de escapar debería ser sospechoso, ya que podría ser más fácil de explotar. Por ejemplo, la forma en que Core usa _ey '__' para las traducciones significa que cualquiera que pueda convencerlo de que instale una traducción no oficial podría agregar JS difícil de detectar en el archivo de traducción y piratear su sitio. Este es un buen ejemplo de "haz lo que digo y no lo que hago".

Mark Kaplun
fuente
Gracias, Mark, por la perspectiva adicional.
tmdesigned
2

Si fuera un hacker con acceso a la base de datos, ¿no agregaría mi código al contenido de una publicación?

Creo que tu pregunta se responde sola. Si eras un hacker con acceso a la base de datos, entonces ya has obtenido el acceso que necesitas. La salida de escape no cambia eso en absoluto.

La razón para escapar de la salida es evaluar los datos no confiables para evitar que el hacker obtenga ese acceso en primer lugar.

butlerblog
fuente
Gracias por tu respuesta. Creo que me concentré demasiado en la idea de evitar que un pirata informático echara de menos el bosque por los árboles.
tmdesigned