Cómo validar correctamente datos de $_GET o $_REQUEST usando funciones de WordPress

12 sept 2012, 19:17:16
Vistas: 18.7K
Votos: 8

Estoy trabajando en un plugin que requiere manipulación dinámica del contenido mostrado. Esto depende completamente de la variable actual $_GET o $_REQUEST.

Dependiendo de qué valor tenga la variable, llamará a un método específico de una clase para manejar la solicitud del usuario y mostrar el contenido adecuado.

Estoy completamente consciente de la página de Validación de Datos en el Codex de WordPress, sin embargo, no estoy seguro de cuál es el mejor enfoque para mi escenario, o cualquier escenario de sanitización de variables $_GET o $_REQUEST.

¿Cómo puedo sanitizar usando funciones de WordPress para variables $_GET o $_REQUEST cuando se trata de un string que será comparado para llamar a un método específico de una clase?

¿Podría esto ser explotado o fallar con el siguiente código?:

public function display_admin_page(){
    if(is_admin() && isset($_GET['page'])){
        global $content;
        $page = sanitize_title($_GET['page']);
        $method_name = 'page_'.str_replace('-', '_', $page);
        if(method_exists('content', $method_name)){
            // Mostrar la página solicitada desde la clase content
            $thePage = $content->$method_name();
        } else{
            $thePage = $content->error(404);    
        }
        echo $thePage;
    }
}
0
Todas las respuestas a la pregunta 4
1

WordPress no proporciona funciones específicas de validación de datos para las variables SUPERGLOBALES.

Yo uso la función PHP filter_input y luego la escapo como lo haría con cualquier variable no confiable.

$url = filter_input( INPUT_GET, 'some_query_string', FILTER_VALIDATE_URL );

echo '<a href="'. esc_url( $url ). '">Click Me</a>';

El filtro de entrada de PHP acepta:

12 sept 2012 19:33:57
Comentarios

@Chris_0, ¿qué hay acerca de las solicitudes $_GET? Por ejemplo, filter_var( $_GET[ $item['name'] ], FILTER_SANITIZE_FULL_SPECIAL_CHARS ). ¿Debería implementarse esto de una manera diferente?

Motivated Motivated
30 oct 2022 10:12:17
2

Para tu ejemplo específico:

Has sanitizado los datos $_GET apropiadamente (aunque yo usaría sanitize_key en lugar de sanitize_title -- no hay mucha diferencia, pero sanitize_title está diseñado para usarse en URLs).

La función method_exists devolverá verdadero para métodos privados y protegidos, por lo que si un usuario intenta llamar a un método privado o protegido, fallará sin llegar al error 404. (A menos que el método display_admin_page esté en la misma clase).

Esto nos lleva a la principal vulnerabilidad potencial: que absolutamente cualquier persona puede forzar la ejecución de cualquier método público en tu clase. Si es posible, siempre es mejor crear una lista blanca específica de lo que se puede aceptar. De esa manera podrías validar con algo como:

if ( !in_array( $_GET['page'], array( 'metodo_aceptado', 'otro_metodo_aceptado' ) ) )
     $content->error(404);
12 sept 2012 22:22:47
Comentarios

¿Podrías ampliar más sobre la teoría del posible exploit?

Michael Ecklund Michael Ecklund
13 sept 2012 17:15:11

Claro, me refiero a que es algo que debes analizar. Cada método público en tu clase puede ser forzado a ejecutarse por cualquier persona en cualquier momento. Eso no es automáticamente un exploit, pero es una consideración. ¿Hay algún método en tu clase que elimine de tu base de datos? ¿Hay algún método que muestre las contraseñas de tus usuarios? ¿Agregarás en el futuro otros métodos que puedan ser preocupantes? Etc.

SeventhSteel SeventhSteel
14 sept 2012 16:23:01
2

Recomiendo usar mysql_real_escape_string($_GET) en cualquier solicitud GET. Es una función de PHP muy potente.

Luego puedes usar str_replace() para reemplazar cualquier carácter no deseado.

ACTUALIZACIÓN 2023:

esc_sql() es la solución perfecta.

12 sept 2012 19:26:06
Comentarios

¿No es la función de WordPress esc_sql() una mejor opción?

gillespieza gillespieza
10 feb 2023 12:55:04

@gillespieza por supuesto que lo es, pero en 2012 esa función es mejor. Es una respuesta de hace 11 años :)

Ciprian Ciprian
10 feb 2023 15:17:58
0

Sanitizar $_GET es bastante específico al contexto. Depende de qué valor quieras y cómo quieras que sea validado.

No hay una respuesta única que sirva para todos los casos. Es muy específico al contexto. Por ejemplo, podrías escribir una función que elimine todas las etiquetas y barras de la entrada, eso es muy seguro, pero ¿qué pasa si quisieras guardar una etiqueta p? No hay ningún daño ahí. La familia de funciones wp_kses() es un caso interesante, pero no es una gran solución, ya que toma en cuenta el contexto, el nivel de usuario y más. Por ejemplo, como usuario administrador puedes guardar JavaScript en el título y contenido de una entrada, pero con un rol inferior, no puedes.

Si su valor es una cantidad conocida, también puedes verificar si in_array( $array_valid_strings ) y estar completamente seguro de esos valores.

Dicho esto, hay diferentes grados de saneamiento, por lo que es importante mantener tu objetivo final en mente. Consultaría esta lista y encontraría la función o combinación de funciones que se ajuste a tus necesidades. Específicamente son las funciones sanitize_ las que deberían usarse aquí, no las esc_. El saneamiento y el escape continúan siendo confundidos...

En mi caso voy a usar sanitize_text_field() porque sanitiza una cadena de entrada del usuario o de la base de datos.

  • Verifica UTF-8 inválido,
  • Convierte caracteres individuales < en entidades
  • Elimina todas las etiquetas
  • Remueve saltos de línea, tabulaciones y espacios extra
  • Elimina octetos

Buena suerte :).

P.D. Esta respuesta cita las perspectivas de tres desarrolladores diferentes (Josh, Michal, Kevin).

11 oct 2016 21:19:29