Configuración típica de $allowed en wp_kses para sanitizar contenido

7 mar 2012, 17:55:51
Vistas: 16.4K
Votos: 15

Tengo un cuadro de texto personalizado para posts que quiero sanitizar usando wp_kses antes de actualizar mi meta post.

Estaba buscando ejemplos de configuraciones comunes para $allowed, pero solo he encontrado este ejemplo:

$allowed = array(  
        'a' => array( // permite solo etiquetas a  
            'href' => array() // y esos anchors solo pueden tener atributo href  
        )  
    );  

¿Cuál es una configuración típica para $allowed en wp_kses? ¿Alguien puede proporcionar un ejemplo de lo que normalmente filtran?

3
Comentarios

Esta pregunta está fuera del alcance del sitio ya que hay más de una respuesta correcta. Si reduces el alcance de la pregunta, presenta un caso de uso y pide que alguien te indique qué cosas deberías incluir, sería mucho mejor.

mor7ifer mor7ifer
7 mar 2012 18:35:12

Quiero tener un cuadro de texto enriquecido donde el usuario pueda ingresar texto normal, negritas, enlaces, cursivas...

redconservatory redconservatory
7 mar 2012 19:31:53

El problema era lo que estaba buscando.

Frank Frank
2 jul 2021 12:31:27
Todas las respuestas a la pregunta 6
3
10

Discrepo con la solución publicada por @JaredCobb, wp_kses() es mucho más flexible que el método que presentó. Puede eliminar atributos no deseados de las etiquetas sin destruir las etiquetas mismas. Por ejemplo, si el usuario ingresara <strong class='foo'>, wp_kses() devolvería <strong> si no permites el atributo class, mientras que strip_tags() eliminaría completamente <strong>.

@redconservatory: Los atributos que querrás usar son los siguientes:

$args = array(
    //formato
    'strong' => array(),
    'em'     => array(),
    'b'      => array(),
    'i'      => array(),

    //enlaces
    'a'     => array(
        'href' => array()
    )
);

Esto permitirá negritas y cursivas sin atributos, así como etiquetas de ancla con atributo href...y nada más. Utiliza el principio de listas blancas, que como @jaredcobb señaló correctamente, es el mejor enfoque aquí.

7 mar 2012 20:01:06
Comentarios

¿No puedes indicarle a strip_tags qué etiquetas están permitidas? http://php.net/manual/en/function.strip-tags.php

redconservatory redconservatory
7 mar 2012 20:30:25

Aunque, ahora puedo ver mejor por qué wp_kses es superior, ya que veo cómo elimina las clases no deseadas...

redconservatory redconservatory
7 mar 2012 20:31:00

Probablemente no me expliqué claramente... Pero sí, wp_kses permite más control que las opciones nativas de PHP. Creo que mencioné eso. También usé la palabra "atributos". Lo que decía es que depende de tu caso de uso. Alguien que intente proteger sus datos de todas las etiquetas estaría mejor usando strip_tags en mi opinión, pero es más una preferencia personal que otra cosa. Saludos.

Jared Cobb Jared Cobb
8 mar 2012 00:59:28
1

Comenzaría con el mismo array $allowedtags que WordPress utiliza para sus comentarios. Puedes encontrar este array en el archivo [directorio de wordpress]/wp-includes/kses.php. Me parecen valores por defecto sensatos y un buen punto de partida. Aquí está su array...

$allowedtags = array(
    'a' => array(
        'href' => true,
        'title' => true,
    ),
    'abbr' => array(
        'title' => true,
    ),
    'acronym' => array(
        'title' => true,
    ),
    'b' => array(),
    'blockquote' => array(
        'cite' => true,
    ),
    'cite' => array(),
    'code' => array(),
    'del' => array(
        'datetime' => true,
    ),
    'em' => array(),
    'i' => array(),
    'q' => array(
        'cite' => true,
    ),
    'strike' => array(),
    'strong' => array(),
);

NO recomendaría usar la función strip_tags de PHP como reemplazo de wp_kses.

¡Nunca deberías usar strip_tags para filtrar contenido de usuarios desconocidos!

He creado un video rápido explicando Por qué wp_kses() de WordPress es mejor que strip_tags() de PHP para seguridad.

4 abr 2013 16:29:56
Comentarios

Hola, ¿qué tal &nbps

User User
25 may 2019 14:44:13
7

Aquí lo tienes. Esto funciona tanto en WordPress como fuera de WordPress.

<?php

$str = '     I am <strong>stronger</strong> and cooler every single day <aaaaa>.    ';
echo orbisius_html_util::strip_tags($str);

/**
 * Clase de utilidades HTML
 * @author Svetoslav Marinov (SLAVI) | http://orbisius.com
 */
class orbisius_html_util {
    /**
     * Utiliza wp_kses de WP para limpiar algunas etiquetas HTML pero permite algunos atributos
     * uso: orbisius_html_util::strip_tags($str);
     * utiliza wp_kses() de WordPress
     * @param str $buffer cadena de texto
     * @return str texto limpio
     */
    public static function strip_tags($buffer) {
        static $default_attribs = array(
            'id' => array(),
            'class' => array(),
            'title' => array(),
            'style' => array(),
            'data' => array(),
            'data-mce-id' => array(),
            'data-mce-style' => array(),
            'data-mce-bogus' => array(),
        );

        $allowed_tags = array(
            'div'           => $default_attribs,
            'span'          => $default_attribs,
            'p'             => $default_attribs,
            'a'             => array_merge( $default_attribs, array(
                'href' => array(),
                'target' => array('_blank', '_top'),
            ) ),
            'u'             =>  $default_attribs,
            'i'             =>  $default_attribs,
            'q'             =>  $default_attribs,
            'b'             =>  $default_attribs,
            'ul'            => $default_attribs,
            'ol'            => $default_attribs,
            'li'            => $default_attribs,
            'br'            => $default_attribs,
            'hr'            => $default_attribs,
            'strong'        => $default_attribs,
            'blockquote'    => $default_attribs,
            'del'           => $default_attribs,
            'strike'        => $default_attribs,
            'em'            => $default_attribs,
            'code'          => $default_attribs,
        );

        if (function_exists('wp_kses')) { // WP está presente
            $buffer = wp_kses($buffer, $allowed_tags);
        } else {
            $tags = array();

            foreach (array_keys($allowed_tags) as $tag) {
                $tags[] = "<$tag>";
            }

            $buffer = strip_tags($buffer, join('', $tags));
        }

        $buffer = trim($buffer);

        return $buffer;
    }
}
16 mar 2015 15:28:43
Comentarios

Hola, señor Svetoslav, ¿esto sigue siendo seguro hoy en día? He estado buscando una forma simple pero segura de sanitizar la entrada de usuarios en mi backoffice (no es Wordpress). Solo quiero permitir el uso de formato HTML básico como el presente en tu código, <b>, <I>, <u>. ¿Crees que puedo usar esto como strip_tags($_POST['myDoc']) o crees que debería hacer algo más para estar seguro? ¡Gracias por tu ayuda!

Pluda Pluda
31 oct 2018 14:42:29

Hola, usa mi código. Verifica si se ejecuta dentro del contexto de WordPress y usará la función de WP, de lo contrario recurrirá a strip_tags de php. Además, es mejor usar $_REQUEST en lugar de $_POST porque en algún momento podrías pasar datos como parámetro GET.

Svetoslav Marinov Svetoslav Marinov
8 nov 2018 12:07:19

Gracias por tu respuesta :-). Ahora estoy lidiando con un problema... si pego HTML formateado o por ejemplo algún código de Sublime Text 3, la mayor parte del texto falta, debe haber algún código oculto con formato que está rompiendo el script.

Pluda Pluda
8 nov 2018 14:37:57

podría ser un problema de codificación utf8

Svetoslav Marinov Svetoslav Marinov
8 nov 2018 22:21:54

Puede ser, estoy limpiando el html como he publicado en la respuesta anterior, buscando \n, \r y demás pero el problema sigue ahí :-(. Limpiar datos pegados puede ser un gran problema, hace algunos años usaba copiar y pegar en textedit para limpiar las cadenas copiadas, pero no puedo esperar que mis usuarios hagan lo mismo.

Pluda Pluda
8 nov 2018 23:17:16

¿Cuál es exactamente el problema? ¿Qué saltos de línea?

Svetoslav Marinov Svetoslav Marinov
12 nov 2018 15:40:48

Hola, ¿qué tal &nbps

User User
25 may 2019 14:45:00
Mostrar los 2 comentarios restantes
1

Solo he usado wp_kses cuando necesitaba específicamente permitir/filtrar atributos de etiquetas HTML (por ejemplo, quiero permitir que tengan una etiqueta <image> con un atributo src="", pero no quiero que puedan agregar href="" o style="" o cualquier otro atributo en la etiqueta de imagen. En ese caso, wp_kses es útil porque (como se puede ver en el ejemplo que creaste) puedes filtrar de manera muy específica. Sin embargo, rara vez uso wp_kses porque encuentro que un par de funciones nativas de PHP (que verás a continuación) hacen el trabajo y son más fáciles de entender cuando reviso el código varios meses después.

Si quieres eliminar completamente las etiquetas HTML (excepto quizás permitir algunas), siempre uso strip_tags. Puedes pasar una cadena de etiquetas permitidas (como <p> <br> <strong>) o cualquier otra etiqueta inofensiva que prefieras. Esto permite al usuario tener algo de control sobre el formato, si es aplicable en tu caso de uso. Me gusta strip_tags porque sigue un enfoque de lista blanca para sanitizar tus datos. (Lo que significa que todo se elimina excepto lo que explícitamente permites).

Si tu objetivo es permitir que ingresen cualquier HTML en el contenido, pero solo quieres mostrar su texto tal como lo ingresaron (como ejemplos de código), entonces usa htmlspecialchars. Esto convertirá los caracteres HTML en sus equivalentes codificados para que puedas mostrarlos de manera segura en la página.

Puede que encuentres código que use str_replace para "buscar" etiquetas malas como <script> o <style> o lo que sea. Realmente no recomiendo ese enfoque porque sigue una estrategia de lista negra para sanitizar datos y tienes que asegurarte constantemente de que tu lista negra esté actualizada.

En resumen, depende del uso que tengan tus metaboxes. Si estás protegiendo contra entradas de usuarios (que podrían ser maliciosos), recomendaría strip_tags y solo permitir algunas etiquetas inofensivas. Si tienes un buen caso de negocio para controlar minuciosamente las etiquetas y atributos específicos del contenido del usuario, usa wp_kses.

7 mar 2012 18:48:25
Comentarios

¿No hace wp_kses() todo lo que hace strip_tags() y más? Estoy a favor de mantener las cosas simples, pero también creo que hay un argumento para no "sorprender" a nadie. wp_kses() es "la forma de Wordpress", y dado que estamos escribiendo código de Wordpress, hay un argumento de que probablemente sea la mejor opción. Además, si en algún momento en el futuro queremos permitir ciertas combinaciones de etiquetas/atributos, usar wp_kses() desde el principio no requerirá una refactorización.

rinogo rinogo
15 ago 2018 21:44:09
0

También podrías usar la función wp_kses_post que se utiliza en el contenido de las publicaciones y solo requiere los datos como parámetro.

Más información aquí: http://codex.wordpress.org/Function_Reference/wp_kses_post

1 may 2013 14:49:04
0

@Svetoslav Marinov

He agregado este código justo después de $buffer = trim($buffer);

    $string_limpa = array(
                '<div><p><\/div>' => '<br>',
                '<div><br><\/div>'=> '<br>',
                '<div align="left"><br><\/div>' => '<br>',
                '<div align="center"><br><\/div>' => '<br>',
                '<div align="right"><br><\/div>' => '<br>',
                '<div style="text-align: left;"><br><\/div>' => '<br>',
                '<div style="text-align: center;"><br><\/div>' => '<br>',
                '<div style="text-align: right;"><br><\/div>' => '<br>',
                '<div style="text-align: justify;"><br><\/div>' => '<br>',
                'class="Apple-style-span"' => '<br>',
                '<p><br></p>' => '<br>',
                '<p><b></p>' => '<br>',
                '<p><i></p>' => '<br>',
                '<p><u></p>' => '<br>',
                '\r' => '<br>',
                '\n' => '<br>',
                '\t' => ' ',
                '\0' => ' ',
                '\x0B' => '<br>',
                '<p style="text-align: center;"><br></p>' => '<br>'
            );
    return strtr($buffer, $string_limpa);

para intentar limpiar el html y evitar que los caracteres ocultos pegados rompan el código, pero no funciona, limpia el html, pero los caracteres ocultos aún permanecen.

8 nov 2018 14:44:29