WordPress 4.7.1 REST API sigue exponiendo usuarios

13 ene 2017, 02:45:03
Vistas: 41.4K
Votos: 37

He actualizado mi WordPress a 4.7.1, y después de eso intenté enumerar usuarios a través de la REST API, que debería estar corregido, pero pude recuperar los usuarios.

https://mywebsite.com/wp-json/wp/v2/users

Salida:

[{"id":1,"name":"admin","url":"","description":"","link":"https:\/\/mywebsite\/author\/admin\/","slug":"admin","avatar_urls":{"24": ...

Registro de cambios de la última versión:

La REST API exponía datos de usuario para todos los usuarios que habían escrito una entrada de un tipo de publicación pública. WordPress 4.7.1 limita esto solo a los tipos de publicación que han especificado que deberían mostrarse dentro de la REST API. Reportado por Krogsgard y Chris Jean.

Después de instalar el plugin Disable REST API, parece que todo funciona bien, pero no me gusta usar un plugin para cada pequeña cosa.

La salida después de usar el plugin es:

{"code":"rest_cannot_access","message":"Solo los usuarios autenticados pueden acceder a la REST API.","data":{"status":401}}

¿Cómo puedo arreglar este problema sin usar plugin, o por qué incluso después de actualizar esto sigue existiendo?

EDICIÓN 30.9.2017

Me di cuenta de que hay un conflicto entre el plugin Contact Form 7 y Disable REST API que te dará un error 401 no autorizado.

Cuando intentas enviar un mensaje a través del formulario de Contact Form 7, realizará una petición

wp-json/contact-form-7/v1/contact-forms/258/feedback

y deshabilitar eso no es una buena idea.

4
Comentarios

Según mi entendimiento, el registro de cambios no indica que los usuarios ya no estén expuestos. Creo que debería interpretarse como "La exposición se limita a los usuarios que han creado tipos de contenido que están configurados para exponerse a través de la API REST". Así que tan pronto como un usuario crea una publicación para un tipo de contenido que se expone (a diferencia de simplemente ser público), el autor también quedará expuesto.

JHoffmann JHoffmann
13 ene 2017 10:04:36

Los usuarios no se consideran datos secretos/privados en WP, lo que has solicitado rompería muchos plugins que usan la API REST, así como el editor de bloques. Por ejemplo, no sería posible mostrar el autor de una publicación o cualquier otra información que no sea su ID

Tom J Nowell Tom J Nowell
5 ene 2021 12:42:36

Exactamente. Acabo de recibir un reporte de Open Bug Bounty sobre esto en mi sitio WP en la versión 5.x. Incluso los script kiddies (https://www.openbugbounty.org/researchers/Cyber_World/) malinterpretan el CVE para esto (https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5487). Esto fue parcheado para quienes estén preocupados. No copies y pegues todo esto sin entender qué lo está usando realmente y si lo necesitas.

Tony-Caffe Tony-Caffe
19 nov 2021 21:58:33
Todas las respuestas a la pregunta 12
7
30

Este fragmento de código ocultará los resultados de los endpoints de usuarios, publicaciones y comentarios, devolviendo un error 404 como resultado, mientras que el resto de llamadas a la API seguirán funcionando como antes.

::ACTUALIZACIÓN::

add_filter('rest_endpoints', function(){
    $toRemove = ['users', 'posts', 'comments'];
    foreach($toRemove as $val)
    {
        if (isset($endpoints['/wp/v2/'.$val])) {
            unset($endpoints['/wp/v2/'.$val]);
        }

        if(isset($endpoints['/wp/v2/'.$val.'/(?P<id>[\d]+)'])) {
            unset($endpoints['/wp/v2/'.$val.'/(?P<id>[\d]+)']);
        }
    }        
    return $endpoints;
});

::ACTUALIZACIÓN::

Este fragmento eliminará todos los endpoints predeterminados.

<?php remove_action('rest_api_init', 'create_initial_rest_routes', 99); ?>

27 ene 2017 20:38:15
Comentarios

según el enlace referido también puedes filtrar los endpoints...

BlueSuiter BlueSuiter
27 ene 2017 20:46:12

Esta es la mejor solución hasta ahora.

mirsad mirsad
30 sept 2017 05:02:40

¿Dónde va este código personalizado? No mencionas dónde se debe guardar esto.

wruckie wruckie
5 dic 2017 22:31:12

Puedes mantener esto en el archivo functions.php de tu tema.

BlueSuiter BlueSuiter
6 dic 2017 08:15:47

Esta solución deshabilita todas las operaciones CRUD en usuarios, mira esta implementación solo para solicitudes GET: https://github.com/szepeviktor/wordpress-fail2ban/commit/98eb4f292a5a6bdae637f9410eb7bb9d6dffd81c

Szépe Viktor Szépe Viktor
28 feb 2019 11:25:41

¿Cómo deshabilitar mydomain.com/wp-json/ para que no muestre todos estos datos en formato json?

Solomon Closson Solomon Closson
20 sept 2019 20:27:16

Esta solución es incompatible con Gutenberg que muestra:

Uncaught (in promise) Response { type: "basic", url: "/wp-json/wp/v2/users/?who=authors&per_page=100&_locale=user", redirected: false, status: 404, ok: false, statusText: "Not Found", headers: Headers, body: ReadableStream, bodyUsed: false }

Sería mejor forzar la autenticación en estos endpoints.

drzraf drzraf
13 nov 2020 20:50:31
Mostrar los 2 comentarios restantes
0
/**
 * Envuelve un callback existente pasado como parámetro y crea
 * un nuevo callback de permisos que realiza verificaciones preliminares
 * y recurre al callback original en caso de éxito.
 */
function permission_callback_hardener ($existing_callback) {
    return function ($request) use($existing_callback) {
        if (! current_user_can('list_users')) {
            return new WP_Error(
                'rest_user_cannot_view',
                __( 'Lo sentimos, no tienes permiso para acceder a los usuarios.' ),
                [ 'status' => rest_authorization_required_code() ]
            );
        }

        return $existing_callback($request);
    };
}

function api_users_endpoint_force_auth($endpoints)
{
    $users_get_route = &$endpoints['/wp/v2/users'][0];
    $users_get_route['permission_callback'] = permission_callback_hardener($users_get_route['permission_callback']);

    $user_get_route = &$endpoints['/wp/v2/users/(?P<id>[\d]+)'][0];
    $user_get_route['permission_callback'] = permission_callback_hardener($user_get_route['permission_callback']);

    return $endpoints;
}

add_filter('rest_endpoints', 'api_users_endpoint_force_auth');
  • El/los endpoint(s) no están bloqueados para administradores (Gutenberg sigue funcionando)
  • El endpoint rechaza usuarios anónimos de forma adecuada.
  • Es lo suficientemente genérico para soportar más endpoints.
  • El current_user_can podría mejorarse, haciéndolo más genérico.
  • Se asume que el método GET es el primero para una ruta registrada (lo cual hasta ahora siempre ha sido cierto)
13 nov 2020 21:53:00
0

Elimina el enlace de la API del encabezado HTML si lo deseas.

// https://wordpress.stackexchange.com/a/211469/77054
// https://wordpress.stackexchange.com/a/212472
remove_action( 'wp_head', 'rest_output_link_wp_head', 10 );

Luego, requiere autenticación para todas las solicitudes.

// Puedes requerir autenticación para todas las solicitudes de la API REST agregando una verificación is_user_logged_in al filtro rest_authentication_errors.
add_filter( 'rest_authentication_errors', function( $result ) {
    if ( ! empty( $result ) ) {
        return $result;
    }
    if ( ! is_user_logged_in() ) {
        return new WP_Error( 'rest_not_logged_in', 'Solo los usuarios autenticados pueden acceder a la API REST.', array( 'status' => 401 ) );
    }
    return $result;
});

Esto te dejará con el mensaje deseado.

Ahora, para detener la enumeración, podrías usar algo como esto.

// https://perishablepress.com/stop-user-enumeration-wordpress/
// bloquear escaneos de enumeración en WP
    // https://m0n.co/enum
    if (!is_admin()) {
        // formato de URL por defecto
        if (preg_match('/author=([0-9]*)/i', $_SERVER['QUERY_STRING'])) die();
        add_filter('redirect_canonical', 'shapeSpace_check_enum', 10, 2);
    }
    function shapeSpace_check_enum($redirect, $request) {
        // formato de URL de enlace permanente
        if (preg_match('/\?author=([0-9]*)(\/*)/i', $request)) die();
        else return $redirect;
    }

Consulta la publicación completa para más técnicas.

18 jun 2017 16:38:22
1

solo otra respuesta:

add_filter( 'rest_user_query', '__return_null' );
add_filter( 'rest_prepare_user', '__return_null' );
14 jul 2020 15:58:30
Comentarios

Probablemente la solución más limpia de todas, gracias.

MitchellK MitchellK
2 may 2021 08:49:16
1

Puedes solucionarlo mediante la configuración de nginx/apache:

location ~* /wp-json/wp-v2/users {
        allow dirección_ip;
        deny all;
}
12 dic 2018 15:37:09
Comentarios

romperá wp-admin (Gutenberg)

ViliusL ViliusL
18 nov 2021 10:02:57
0

Código .htaccess para bloquear todos los escaneos de autores

# BEGIN block author scans
RewriteEngine On
RewriteBase /
RewriteCond %{QUERY_STRING} (author=\d+) [NC]
RewriteRule .* - [F]
# END block author scans

Puedes eliminarlo mediante función como sugiere la respuesta aceptada

11 dic 2020 16:24:56
0

Usé este pequeño código en functions.php:

/**
 * Acceso a la API REST solo para administradores
 *
 * @return void
 */
 function api_rest_only_for_admin_users() {
  $current_user = wp_get_current_user();
  if ( in_array('administrator', $current_user->roles ) ) {
    return;
  } else {
    wp_die('Lo sentimos, no tienes permiso para acceder a estos datos','API REST Prohibido',403);
  }
}
add_filter( 'rest_api_init', 'api_rest_only_for_admin_users', 99 );
5 ene 2021 12:24:30
0

Para completar la respuesta de BlueSuiter en 2017, aquí hay una solución para filtrar usuarios por rol que hace que su solución sea compatible con el editor Gutenberg.

add_filter( 'rest_endpoints', function( $endpoints ) {
    
    if(is_user_logged_in()) {

        $user = wp_get_current_user();

        $roles = array('editor', 'administrator', 'author');

        if( array_intersect($roles, $user->roles ) ) return $endpoints; 

    } 

    if ( isset( $endpoints['/wp/v2/users'] ) ) unset( $endpoints['/wp/v2/users'] );

    if ( isset( $endpoints['/wp/v2/users/(?P<id>[\d]+)'] ) ) unset( $endpoints['/wp/v2/users/(?P<id>[\d]+)'] );

    return $endpoints;
    
});

El editor Gutenberg necesita consultar la API REST para obtener el autor. Por lo tanto, es necesario permitir al menos todos los roles de usuario de tu sitio que tienen acceso a un editor Gutenberg, no olvides las publicaciones personalizadas.

En el endpoint público de la API REST, se devuelve un error 404 porque is_user_logged_in siempre devolverá falso.

30 nov 2021 00:02:35
0

Si estás utilizando un firewall para proteger tu sitio web de WordPress, la mejor opción es bloquear el endpoint de la API que expone los detalles de los usuarios desde el firewall.

Detecta la URL https://ejemplo.com/wp-json/wp/v2/users y simplemente bloquéala desde el firewall.

Edición: solo bloquea el endpoint específico de detalles de usuarios y no toda la API REST.

23 mar 2021 11:03:25
0
// Bloqueo de la API JSON de usuarios de WordPress
function disable_custom_rest_endpoints( $endpoints ) {
    // Definir las rutas de la API que queremos deshabilitar
    $routes = array( '/wp/v2/users', '/wp/v2/users/(?P<id>[\d]+)' );

    // Recorrer cada ruta definida
    foreach ( $routes as $route ) {
        // Si la ruta no existe en los endpoints, continuar
        if ( empty( $endpoints[ $route ] ) ) {
            continue;
        }

        // Recorrer los manejadores de cada ruta
        foreach ( $endpoints[ $route ] as $i => $handlers ) {
            // Si es un manejador válido con método GET, eliminarlo
            if ( is_array( $handlers ) && isset( $handlers['methods'] ) &&
                'GET' === $handlers['methods'] ) {
                unset( $endpoints[ $route ][ $i ] );
            }
        }
    }

    // Devolver los endpoints modificados
    return $endpoints;
}
// Aplicar el filtro a los endpoints REST
add_filter( 'rest_endpoints', 'disable_custom_rest_endpoints' );
24 oct 2023 11:14:12
1

Creé un plugin completo que funciona para esto dentro de GITHUB.

https://github.com/MRKWP/mrkwp-rest-permissions/

Lo que hice fue asegurarme de usar INIT para el inicio de la acción, esto garantiza que las funciones pluggables funcionen como se espera.

También uso la capacidad 'Edit_posts' de WordPress para la API. Esto asegura que el administrador y el editor de bloques funcionen correctamente.

Echa un vistazo a ese plugin para resolver cualquier problema CVE-2017-5487 señalado por los auditores de seguridad.

También utiliza PHP CS, por lo que funcionará con una instalación VIP o algo que necesite estándares implementados.

Espero que esto ayude a alguien. Me tomó bastante tiempo hacer que esto funcionara bien en mis propios sitios y servidores.

3 abr 2024 07:11:33
Comentarios

Al revisar el código, el nombre "hardener" es un poco engañoso ya que no refuerza los endpoints, sino que hace que siempre rechacen las solicitudes. Simplemente lo instalas condicionalmente. Además, estás llamando funciones de activación y desactivación que no existen. Pero sí, parece que esto haría el trabajo.

Rup Rup
4 abr 2024 19:36:22
1
-1

Para poder solucionar esto, primero necesitas conocer la fuente del problema.

  1. ¿Utilizas plugins de SEO como: All in one SEO pack o Yoast? Intenta desactivarlos y verifica nuevamente.
  2. ¿Utilizas el plugin Jetpack? Intenta desactivarlo y verifica nuevamente.

Por favor, házme saber si esto te orientó en la dirección correcta.

Una forma rápida de solucionar esto es simplemente bloquear la URL en tu archivo .htaccess. https://miweb.com/wp-json/wp/v2/users

24 jun 2017 21:30:56
Comentarios

Los primeros dos puntos que mencionas no tienen sentido, pero el método "sucio" de bloquear el acceso en realidad es más rápido que usar WordPress, ya que se bloqueará a nivel de Apache antes de que WordPress ni siquiera se cargue.

Alexander Holsgrove Alexander Holsgrove
18 feb 2020 12:54:56