WordPress のユーザー・一覧表示対策
WordPress の場合、「サイトのURL/?author=1」などでアクセスするとユーザー名(ログインID)が閲覧者に見えてしまったり、WP REST API がデフォルトで有効になっているので、認証無しでもユーザー情報などのデータを外部から取得する事ができるようになっているので、そのための対策につて。
更新日:2023年03月11日
作成日:2019年01月18日
ユーザーの一覧表示対策
WordPress のいくつかの機能により、ユーザーのログイン ID などを外部から取得することができるようになっています。そのため、ブルートフォースアタックなどが懸念されますが、ユーザー名を適切に設定し、複雑なパスワードを使い定期的に変更していれば問題はないとされているようです。また、以下の対策で完全に問題を回避できるかは、定かではありません。
WP REST API を無効にする
WordPress 4.7 から「WP REST API」がデフォルトで有効になっています。そのため認証無しでも投稿記事やユーザー情報などのデータを外部から取得する事ができるようになっています。
例えば、以下のアドレスにアクセスしてみると、json 形式のユーザーのデータが表示されます。
「サイトのURL/wp-json/wp/v2/users」や「サイトのURL/?rest_route=/wp/v2/users」
REST API を使用しない場合は、以下のような方法で REST API を無効にすることができます。
※ WordPress の REST API Handbook によると、管理画面の機能が REST API に依存しているため無効にするのは推奨されていません。無効にする場合は、以下のように rest_authentication_errors フィルタを使ってログインしていない場合にのみ無効にする方法が推奨されてます。(以下を functions.php に記述)
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', 'You are not currently logged in.', array( 'status' => 401 ) ); } return $result; });
但し、上記の方法だと、ユーザーがログインしていないと Contact Form7 などの REST API を使用しているプラグインが機能しなくなってしまいます。
以下の方法で、特定のプラグインなどを除外して REST API を無効にすることができますが、今後 REST API を使ったプラグインや機能が増えていくことを考えるとこの方法が妥当かどうか自分のサイトに合わせて判断する必要があります。
以下では、REST API を使用している Embed(oEmbed)や編集エディタの機能、 Contact Form 7、 Akismet のプラグイン以外で REST API を無効にしています。
「rest_pre_dispatch」というフックを使っています。「WordPress4.7 の WP REST API を無効にする(ねんでぶろぐ)」を参考にさせていただきました。
function deny_rest_api_except_permitted( $result, $wp_rest_server, $request ){ //permit oembed, Contact Form 7, Akismet $permitted_routes = [ 'oembed', 'contact-form-7', 'akismet']; $route = $request->get_route(); foreach ( $permitted_routes as $r ) { if ( strpos( $route, "/$r/" ) === 0 ) return $result; } //permit Gutenberg(ユーザーが投稿やページの編集が可能な場合) if ( current_user_can( 'edit_posts' ) || current_user_can( 'edit_pages' )) { return $result; } return new WP_Error( 'rest_disabled', __( 'The REST API on this site has been disabled.' ), array( 'status' => rest_authorization_required_code() ) ); } add_filter( 'rest_pre_dispatch', 'deny_rest_api_except_permitted', 10, 3 );
除外したいプラグインが増えた場合は、その文字列を配列 $permitted_routes = [ ]; に追加します。「サイトのURL/wp-json/」で namespaces や routes を確認できます。
/oembed/1.0 /oembed/1.0/embed /oembed/1.0/proxy /akismet/v1 /akismet/v1/key /akismet/v1/settings /akismet/v1/stats /akismet/v1/stats/(?P<interval>[\w+]) /contact-form-7/v1 /contact-form-7/v1/contact-forms /contact-form-7/v1/contact-forms/(?P<id>\d+) /contact-form-7/v1/contact-forms/(?P<id>\d+)/feedback /contact-form-7/v1/contact-forms/(?P<id>\d+)/refill /wp/v2 /wp/v2/posts /wp/v2/posts/(?P<id>[\d]+) /wp/v2/posts/(?P<parent>[\d]+)/revisions /wp/v2/posts/(?P<parent>[\d]+)/revisions/(?P<id>[\d]+) /wp/v2/pages /wp/v2/pages/(?P<id>[\d]+) /wp/v2/pages/(?P<parent>[\d]+)/revisions /wp/v2/pages/(?P<parent>[\d]+)/revisions/(?P<id>[\d]+) /wp/v2/media /wp/v2/media/(?P<id>[\d]+) /wp/v2/types /wp/v2/types/(?P<type>[\w-]+) /wp/v2/statuses /wp/v2/statuses/(?P<status>[\w-]+) /wp/v2/taxonomies /wp/v2/taxonomies/(?P<taxonomy>[\w-]+) /wp/v2/categories /wp/v2/categories/(?P<id>[\d]+) /wp/v2/tags /wp/v2/tags/(?P<id>[\d]+) /wp/v2/users /wp/v2/users/(?P<id>[\d]+) /wp/v2/users/me /wp/v2/comments /wp/v2/comments/(?P<id>[\d]+) /wp/v2/settings
前述の方法で WP REST API を無効にすると、「サイトのURL/?rest_route=/wp/v2/users」などでアクセスすると以下のように「"code":"rest_disabled","message":"The REST API on this site has been disabled.","data":{"status":401}」と表示されます。
/wp/v2/users をリダイレクト
単純に、/wp/v2/users にアクセスできないようにするだけであれば、以下を functions.php に記述すると言う方法もあるかと思いますが、これが妥当な方法かは定かではありません。以下の場合だと、URL や クエリに /wp/v2/users が含まれている場合、ホームにリダイレクトします。
function disable_users_query() { if( preg_match('/wp\/v2\/users/i', $_SERVER['REQUEST_URI']) || preg_match('/wp\/v2\/users/i', $_SERVER['QUERY_STRING']) ){ wp_safe_redirect( home_url() ); exit; } } add_action('init', 'disable_users_query');