WordPress 4.7.1 REST API всё ещё раскрывает данные пользователей

13 янв. 2017 г., 02:45:03
Просмотры: 41.4K
Голосов: 37

Я обновил WordPress до версии 4.7.1, и после этого попробовал получить список пользователей через REST API, что должно было быть исправлено, но мне всё равно удалось получить данные пользователей.

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

Вывод:

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

Список изменений из последней версии:

REST API раскрывал данные пользователей для всех, кто был автором публичного типа записи. WordPress 4.7.1 ограничивает это только теми типами записей, которые специально отмечены для отображения в REST API. Сообщено Krogsgard и Chris Jean.

После установки плагина Disable REST API кажется, что всё работает нормально, но мне не нравится использовать плагин для каждой мелочи.

Вывод после использования плагина:

{"code":"rest_cannot_access","message":"Только аутентифицированные пользователи могут получить доступ к REST API.","data":{"status":401}}

Как можно исправить эту проблему без использования плагина, или почему даже после обновления это всё ещё существует?

РЕДАКТИРОВАНО 30.9.2017

Я обнаружил, что существует конфликт между плагинами Contact Form 7 и Disable REST API, который приводит к ошибке 401 unauthorized.

Когда вы пытаетесь отправить сообщение через форму Contact Form 7, она делает запрос

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

и отключение этого - не лучшая идея.

4
Комментарии

Насколько я понимаю, в журнале изменений не сказано, что пользователи больше не раскрываются. Я думаю, это следует понимать как "Доступ ограничивается пользователями, которые являются авторами типов записей, настроенных на раскрытие через REST API." Таким образом, как только пользователь создает запись для типа записи, который раскрывается (в отличие от просто публичного), автор также будет раскрыт.

JHoffmann JHoffmann
13 янв. 2017 г. 10:04:36

Возможно, эта ссылка вам поможет: https://wordpress.stackexchange.com/questions/228585/hiding-wordpress-rest-api-v2-endpoints-from-public-viewing

Pablo Pablo
25 июл. 2017 г. 05:23:36

Пользователи не считаются секретными/приватными данными в WP. Ваш запрос сломает множество плагинов, использующих REST API, а также редактор блоков. Например, станет невозможным отображение автора записи или любой другой информации, кроме его ID

Tom J Nowell Tom J Nowell
5 янв. 2021 г. 12:42:36

Именно так. Я только что получил уведомление Open Bug Bounty об этой уязвимости на своем сайте на WordPress 5.x. Даже скрипт-кидди (https://www.openbugbounty.org/researchers/Cyber_World/) неправильно понимают CVE для этой проблемы (https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5487). Патч уже выпущен для всех, кого это касается. Не копируйте и не вставляйте все эти данные, не разобравшись в том, что именно использует ваш сайт и нужно ли это вам.

Tony-Caffe Tony-Caffe
19 нояб. 2021 г. 21:58:33
Все ответы на вопрос 12
7
30

Этот фрагмент кода скроет конечные точки пользователей, записей и комментариев, возвращая ошибку 404, в то время как остальные вызовы API будут работать как обычно.

::ОБНОВЛЕНИЕ::

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;
});

::ОБНОВЛЕНИЕ::

Этот фрагмент кода удалит все стандартные конечные точки API.

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

27 янв. 2017 г. 20:38:15
Комментарии

Как указано в приведенной ссылке, вы также можете отфильтровать конечные точки...

BlueSuiter BlueSuiter
27 янв. 2017 г. 20:46:12

Это лучшее решение на данный момент.

mirsad mirsad
30 сент. 2017 г. 05:02:40

Куда вставлять этот пользовательский код? Вы не указали, где его нужно сохранить.

wruckie wruckie
5 дек. 2017 г. 22:31:12

Вы можете оставить это в файле functions.php вашей темы.

BlueSuiter BlueSuiter
6 дек. 2017 г. 08:15:47

Это решение отключает все CRUD-операции с пользователями, смотрите эту реализацию только для GET-запросов: https://github.com/szepeviktor/wordpress-fail2ban/commit/98eb4f292a5a6bdae637f9410eb7bb9d6dffd81c

Szépe Viktor Szépe Viktor
28 февр. 2019 г. 11:25:41

Как отключить вывод всех этих JSON-данных по адресу mydomain.com/wp-json/?

Solomon Closson Solomon Closson
20 сент. 2019 г. 20:27:16

Это решение несовместимо с Gutenberg, который выдает:

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 }

Принудительная аутентификация на этих конечных точках была бы лучше.

drzraf drzraf
13 нояб. 2020 г. 20:50:31
Показать остальные 2 комментариев
0
/**
 * Обернуть существующий стандартный callback, переданный в параметре, и создать
 * новый permission callback с предварительными проверками, 
 * возвращающий стандартный callback в случае успеха.
 */
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',
                __( 'Извините, у вас нет прав для доступа к пользователям.' ),
                [ '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');
  • Эндпоинт(ы) не блокируется для администраторов (Gutenberg продолжает работать)
  • Эндпоинт корректно отклоняет анонимных пользователей.
  • Достаточно универсален для поддержки дополнительных эндпоинтов.
  • current_user_can может быть дополнительно улучшен, сделан более универсальным.
  • Предполагается, что метод GET является первым для зарегистрированного маршрута (что пока всегда было верно)
13 нояб. 2020 г. 21:53:00
0

Удалите ссылку на API из HTML head, если хотите.

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

Затем потребуйте аутентификацию для всех запросов.

// Вы можете потребовать аутентификацию для всех запросов REST API, добавив проверку is_user_logged_in к фильтру 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', 'Только аутентифицированные пользователи могут получить доступ к REST API.', array( 'status' => 401 ) );
    }
    return $result;
});

Это оставит вам желаемое сообщение.

Теперь, чтобы остановить перебор, вы можете использовать что-то вроде этого.

// https://perishablepress.com/stop-user-enumeration-wordpress/
// блокировка сканирования перебора пользователей в WP
    // https://m0n.co/enum
    if (!is_admin()) {
        // стандартный формат URL
        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) {
        // формат URL с постоянными ссылками
        if (preg_match('/\?author=([0-9]*)(\/*)/i', $request)) die();
        else return $redirect;
    }

Ознакомьтесь с полной статьей для дополнительных методов.

18 июн. 2017 г. 16:38:22
1

ещё один ответ:

add_filter( 'rest_user_query', '__return_null' );
add_filter( 'rest_prepare_user', '__return_null' );
14 июл. 2020 г. 15:58:30
Комментарии

Вероятно, самое чистое решение из всех, спасибо.

MitchellK MitchellK
2 мая 2021 г. 08:49:16
1

Вы можете исправить это через конфигурацию nginx/apache:

location ~* /wp-json/wp-v2/users {
        allow ip_address;
        deny all;
}
12 дек. 2018 г. 15:37:09
Комментарии

это сломает wp-admin (Gutenberg)

ViliusL ViliusL
18 нояб. 2021 г. 10:02:57
0

Код .htaccess для блокировки всех сканирований авторов

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

Вы можете удалить его с помощью функции, как предложено в принятом ответе

11 дек. 2020 г. 16:24:56
0

Я использовал этот небольшой код в файле function.php:

/**
 * Доступ к REST API только для администраторов
 *
 * @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('Извините, у вас нет прав для доступа к этим данным','Доступ к REST API запрещен',403);
  }
}
add_filter( 'rest_api_init', 'api_rest_only_for_admin_users', 99 );
5 янв. 2021 г. 12:24:30
0

Чтобы дополнить ответ BlueSuiter за 2017 год, вот решение для фильтрации пользователей по роли, которое делает его решение совместимым с редактором 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;
    
});

Редактору Gutenberg необходимо делать запросы к REST API для получения информации об авторе. Поэтому необходимо пропустить как минимум все роли пользователей вашего сайта, которые имеют доступ к редактору Gutenberg, не забывая о пользовательских типах записей.

На публичной конечной точке REST API будет возвращаться ошибка 404, потому что is_user_logged_in всегда будет возвращать false.

30 нояб. 2021 г. 00:02:35
0

Если вы используете брандмауэр для защиты вашего сайта на WordPress, то лучшим вариантом будет заблокировать через брандмауэр конечную точку API, которая раскрывает данные пользователей.

Определите URL https://example.com/wp-json/wp/v2/users и просто заблокируйте его в брандмауэре.

Примечание: блокируйте только конечную точку, связанную с данными пользователей, а не весь REST API целиком.

23 мар. 2021 г. 11:03:25
0
// Блокировка пользовательских конечных точек WP Json API
function disable_custom_rest_endpoints( $endpoints ) {
    $routes = array( '/wp/v2/users', '/wp/v2/users/(?P<id>[\d]+)' );

    foreach ( $routes as $route ) {
        if ( empty( $endpoints[ $route ] ) ) {
            continue;
        }

        foreach ( $endpoints[ $route ] as $i => $handlers ) {
            if ( is_array( $handlers ) && isset( $handlers['methods'] ) &&
                'GET' === $handlers['methods'] ) {
                unset( $endpoints[ $route ][ $i ] );
            }
        }
    }

    return $endpoints;
}
add_filter( 'rest_endpoints', 'disable_custom_rest_endpoints' );
24 окт. 2023 г. 11:14:12
1

Я создал полноценный плагин, который решает эту задачу и разместил его на GITHUB.

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

Я убедился, что использовал INIT для запуска действия, это гарантирует правильную работу подключаемых функций.

Также я использовал стандартную возможность WordPress 'Edit_posts' для API. Это обеспечивает корректную работу админки и редактора блоков.

Ознакомьтесь с этим плагином, чтобы решить любые проблемы, связанные с уязвимостью CVE-2017-5487, которые могут быть выявлены аудиторами безопасности.

Плагин также использует PHP CS, поэтому он будет работать с установкой VIP или в средах, где требуются соблюдение стандартов.

Надеюсь, это кому-то поможет. У меня ушло немало времени, чтобы заставить это хорошо работать на моих собственных сайтах и серверах.

3 апр. 2024 г. 07:11:33
Комментарии

Просматривая код, название "hardener" немного вводит в заблуждение, так как оно не укрепляет конечные точки, а заставляет их всегда отклонять запросы - вы просто устанавливаете его условно. Также вы вызываете функции активации и деактивации, которые не существуют. Но да, похоже, что это сработает.

Rup Rup
4 апр. 2024 г. 19:36:22
1
-1

Чтобы исправить эту проблему, сначала необходимо определить её источник.

  1. Используете ли вы SEO-плагины, такие как: All in One SEO Pack или Yoast? Попробуйте отключить их и проверьте снова.
  2. Используете ли вы плагин Jetpack? Попробуйте отключить его и проверьте снова.

Пожалуйста, сообщите мне, помогло ли это вам найти верное направление для решения.

Грубым способом решить эту проблему является простое блокирование URL в вашем файле .htaccess. https://mywebsite.com/wp-json/wp/v2/users

24 июн. 2017 г. 21:30:56
Комментарии

Первые два ваших утверждения — это чушь, но «грязный» метод блокировки доступа действительно быстрее, чем использование WordPress, так как блокировка происходит на уровне Apache ещё до загрузки WordPress.

Alexander Holsgrove Alexander Holsgrove
18 февр. 2020 г. 12:54:56