admin管理员组文章数量:1122846
I have upgraded my WordPress to 4.7.1
, and after that I've tried to enumerate users through REST API, which should be fixed, but I was able to retrieve users.
Output:
[{"id":1,"name":"admin","url":"","description":"","link":"https:\/\/mywebsite\/author\/admin\/","slug":"admin","avatar_urls":{"24": ...
Changelog from latest version:
The REST API exposed user data for all users who had authored a post of a public post type. WordPress 4.7.1 limits this to only post types which have specified that they should be shown within the REST API. Reported by Krogsgard and Chris Jean.
After installing plugin Disable REST API
, it seems that everything is working fine, but I don't like to use for every little thing plugin.
The output after using plugin is:
{"code":"rest_cannot_access","message":"Only authenticated users can access the REST API.","data":{"status":401}}
How can I fix this issue without using plugin, or why even after upgrading this stil exist?
EDIT 30.9.2017
I realized that there is a conflict between contact 7
plugin and Disable REST API
and that will give you 401 unauthorized
error.
When you try to send a message through contact 7
form, it will make a request
wp-json/contact-form-7/v1/contact-forms/258/feedback
and disabling that is not a good idea.
I have upgraded my WordPress to 4.7.1
, and after that I've tried to enumerate users through REST API, which should be fixed, but I was able to retrieve users.
https://mywebsite.com/wp-json/wp/v2/users
Output:
[{"id":1,"name":"admin","url":"","description":"","link":"https:\/\/mywebsite\/author\/admin\/","slug":"admin","avatar_urls":{"24": ...
Changelog from latest version:
The REST API exposed user data for all users who had authored a post of a public post type. WordPress 4.7.1 limits this to only post types which have specified that they should be shown within the REST API. Reported by Krogsgard and Chris Jean.
After installing plugin Disable REST API
, it seems that everything is working fine, but I don't like to use for every little thing plugin.
The output after using plugin is:
{"code":"rest_cannot_access","message":"Only authenticated users can access the REST API.","data":{"status":401}}
How can I fix this issue without using plugin, or why even after upgrading this stil exist?
EDIT 30.9.2017
I realized that there is a conflict between contact 7
plugin and Disable REST API
and that will give you 401 unauthorized
error.
When you try to send a message through contact 7
form, it will make a request
wp-json/contact-form-7/v1/contact-forms/258/feedback
and disabling that is not a good idea.
Share Improve this question edited Sep 30, 2017 at 1:49 mirsad asked Jan 13, 2017 at 0:45 mirsadmirsad 5571 gold badge4 silver badges8 bronze badges 4- 10 As of my understanding, the changelog doesn't say that users don't get exposed anymore. i think it should be read as "Exposure gets limited to users who have authored post types which are set to be exposed via REST API." So as soon as a users authors a post for a post type which gets exposed (in contrast to just being public), the author will also be exposed. – JHoffmann Commented Jan 13, 2017 at 8:04
- Maybe this link could be help you: wordpress.stackexchange.com/questions/228585/… – Pablo Commented Jul 25, 2017 at 2:23
- 1 Users are not considered secret/private data in WP, what you've requested will break a lot of plugins that use the REST API, as well as the block editor. E.g. it won't be possible to display the author of a post or any other information than its ID – Tom J Nowell ♦ Commented Jan 5, 2021 at 10:42
- Exactly. I just received an Open Bug Bounty about this on my WP site on 5.x. Even the script kiddies (openbugbounty.org/researchers/Cyber_World) misunderstand the CVE for this (cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5487). This was patched for anyone concerned. Don't copy and paste all of these without understanding what really is using it and if you need it. – Tony-Caffe Commented Nov 19, 2021 at 19:58
12 Answers
Reset to default 30This code snippet will hide the users, posts, and comments endpoint results and give 404 as the result, while the rest of the API calls keep running as they were.
::UPDATE::
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;
});
::UPDATE::
This snippet will remove all the default endpoints.
<?php remove_action('rest_api_init', 'create_initial_rest_routes', 99); ?>
/**
* Wrap an existing default callback passed in parameter and create
* a new permission callback introducing preliminary checks and
* falling-back on the default callback in case of success.
*/
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',
__( 'Sorry, you are not allowed to access users.' ),
[ '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');
- The endpoint(s) is not blocked for administrators (Gutenberg keeps working)
- The endpoint rejects anonymous users in a proper way.
- It's generic enough to support further endpoints.
- The
current_user_can
could be further enhanced, made more generic. - Assume that the
GET
method is the first for a registered route (which so far has always been true)
Remove the API link from the HTML head if you like.
// https://wordpress.stackexchange.com/a/211469/77054
// https://wordpress.stackexchange.com/a/212472
remove_action( 'wp_head', 'rest_output_link_wp_head', 10 );
Then require authentication for all requests.
// You can require authentication for all REST API requests by adding an is_user_logged_in check to the rest_authentication_errors filter.
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', 'Only authenticated users can access the REST API.', array( 'status' => 401 ) );
}
return $result;
});
This will leave you with the desired message.
Now to stop enumeration you could use something like this.
// https://perishablepress.com/stop-user-enumeration-wordpress/
// block WP enum scans
// https://m0n.co/enum
if (!is_admin()) {
// default URL format
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) {
// permalink URL format
if (preg_match('/\?author=([0-9]*)(\/*)/i', $request)) die();
else return $redirect;
}
Check out the whole post for further techniques.
just another answer:
add_filter( 'rest_user_query', '__return_null' );
add_filter( 'rest_prepare_user', '__return_null' );
You can fix it through nginx/apache config:
location ~* /wp-json/wp/v2/users {
allow ip_address;
deny all;
}
.htaccess code to block all author scans
# BEGIN block author scans
RewriteEngine On
RewriteBase /
RewriteCond %{QUERY_STRING} (author=\d+) [NC]
RewriteRule .* - [F]
# END block author scans
You can remove it by function as the accepted answer suggested
I used this little code in function.php :
/**
* API REST access only for administrators
*
* @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('Sorry you are not allowed to access this data','API REST Forbidden',403);
}
}
add_filter( 'rest_api_init', 'api_rest_only_for_admin_users', 99 );
To complete 2017 BlueSuiter's answer, here is a solution to filter users by role which makes its solution compatible with the Gutenberg editor.
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;
});
The Gutenberg editor needs to query the REST API to get the author. It is therefore necessary to let pass at least all the user roles of your site that have access to a Gutenberg editor, don't forget the custom posts.
On the public REST API endpoint, a 404 error is returned because is_user_logged_in will always return false.
If you are using a firewall to protect your wordpress website then best option is to block the api endpoint which exposes user details from firewall.
Detect the url https://example.com/wp-json/wp/v2/users
and simply block it from firewall.
Edit: only block the user details specific endpoint and not the whole REST api.
I created a full plugin that works for this inside GITHUB.
https://github.com/MRKWP/mrkwp-rest-permissions/
What I did was made sure to use INIT for the start of the action, this makes sure pluggable functions work as expected.
I also use the WordPress 'Edit_posts' capability for the API. This ensure the admin and block editor works as expected.
Take a look at that plugin to solve any CVE-2017-5487 issues raised by security auditors.
It also uses PHP CS so it will work with a VIP install or something that needs standards implemented.
Hope that helps someone out. Took me a fair while to get this working well on my own sites and servers.
// User WP Json API block
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' );
To be able to fix this you first need to know the source of the problem.
- Do you use SEO plugins like: All in one SEO pack or Yoast? Try to disable this and check again.
- Do you use the Jetpack plugin? Try to disable this and check again.
Please let me know if this pointed you into the right direction.
A dirty way to solve this is to just block the url underneath in your .htacces. https://mywebsite.com/wp-json/wp/v2/users
本文标签: securityWordPress 471 REST API still exposing users
版权声明:本文标题:security - WordPress 4.7.1 REST API still exposing users 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736311490a1934753.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论