Mstudio

技術ブログ

技術ブログ詳細

技術ブログ

WordPressの ?author=1 でユーザー名がバレる問題を、プラグインなしで根本対策する方法

著者: マサシ読了時間: 15
WordPressの ?author=1 でユーザー名がバレる問題を、プラグインなしで根本対策する方法
avatar
今日は WordPress の地味だけど大事な話。`?author=1` って URL 知ってる?
avatar
えっ、それなに?こわい話?💦
avatar
URL の最後に `?author=1` を付けると、運用者のログインID が外からバレちゃうことがあるんだ。
avatar
ええっ、自分のサイトも危ないかも…どうしたらいい?
avatar
安心して。今日はプラグインに頼らずに、コードでちゃんと根本対策する方法を一緒に見ていこう。

こんにちは、マサシです。

WordPress のサイトを公開していると、外部のセキュリティ診断ツールやサーバー監査で

?author=1 でユーザー名が漏れています」

と指摘を受けることがあります。脆弱性スキャナの WPScan なども、まずここを見ます。
本記事では、プラグインを増やさずに functions.php と REST API 制御で根本対策する手順を、検証コマンド付きでやさしく解説します。

結論はシンプルです。次の 4 段階で塞げば十分です。

  1. ?author=N のリクエストを init フックで早期 404
  2. パーマリンクの author スラッグを変更(漏洩経路を狭める)
  3. REST API /wp-json/wp/v2/users を非ログイン時に無効化
  4. サイトマップ・投稿スラッグの author 露出を確認

「Edit Author Slug を入れて終わり」では塞ぎきれない経路があります。
1 つずつ見ていきましょう。

なぜ ?author=1 だけで「ログインID」がバレるのか

avatar
そもそも、なんで URL を 1 つ叩いただけでバレちゃうの?
avatar
これは WordPress の仕様で、`?author=N` を踏むと author アーカイブにリダイレクトされるんだ。
avatar
リダイレクト?
avatar
リダイレクト先の URL に「ログインID(user_nicename)」がそのまま含まれて返ってくる。だから外から特定できるんだよ。

WordPress には author アーカイブ という、特定の投稿者の記事一覧を表示する仕組みがあります。
そして、?author=N(N はユーザーID)を URL に付けると、サーバーが自動で次のような URL にリダイレクトします。

GET https://example.com/?author=1
↓ 302 Redirect
Location: https://example.com/author/admin/

この admin の部分が、そのユーザーの ログインID(user_login)に紐づく user_nicename です。
初期設定のままだと、user_loginuser_nicename は同じ値になっていることがほとんどなので、結果として ログインIDが外部にバレます

ID を 1, 2, 3 …と総当たりで叩けば、サイト運用者全員のログインIDがリスト化できてしまいます。

バレた後に何が起きるか(攻撃者の流れ)

ログインIDだけなら大した被害はない、と感じるかもしれません。
ですが、攻撃者の典型的な流れは次のとおりです。

  1. ?author=NログインIDを総当たり収集
  2. 収集したIDに対して パスワードを総当たり(ブルートフォース)
  3. ログインに成功したら、管理画面から不正コードを埋め込む
  4. SEO スパム・マルウェア配布・スパムメール送信に悪用される

つまり ?author=N の露出は、ブルートフォース攻撃の「IDの部分」を攻撃者にプレゼントしている状態です。
パスワードが弱いユーザーが 1 人でもいると、そこから一気に陥落します。

対策レベル 1:Edit Author Slug プラグイン(最低限ライン)

avatar
プラグインで簡単に塞げるって聞いたよ?
avatar
Edit Author Slug は author スラッグだけ変えるプラグイン。それも有効ではあるけど、`?author=N` の経路自体は残るから不十分なんだ。

有名な対策プラグインに Edit Author Slug があります。
これは、ユーザープロフィール画面で user_nicename を任意の文字列に変更できるようにするものです。

例:admineditor-team

これでリダイレクト先の URL に admin が出なくなるので、ログインIDの直接的な漏洩は防げます
しかし、次の 2 つの経路は残ります。

  • 投稿一覧の 投稿者リンク(テーマで投稿者名を表示している箇所)
  • REST API /wp-json/wp/v2/users で全ユーザー情報が返る

つまり、Edit Author Slug を入れただけでは、root 原因の ?author=N リダイレクトは生きたままです。
本気で塞ぐなら、次のレベル 2 以降の対策が必要です。

対策レベル 2:functions.php で ?author=N を init で 404 にする

avatar
ここからが本題!コードで根本から塞ぐ方法を見せるね。
avatar
お願いします〜!

WordPress には init フックという、リクエスト処理の 最も早い段階 で動くフックがあります。
ここで ?author=N のリクエストを検知して、author アーカイブが組み立てられる前に 404 を返してしまうのが根本対策です。

子テーマの functions.php に次のコードを追加します。

/**
 * ?author=N によるユーザー名漏洩を防ぐ
 * - クエリ文字列に author が含まれる場合、init で早期に 404 を返す
 * - 管理画面・ログイン中ユーザーは除外(編集機能を壊さない)
 */
add_action( 'init', function () {
	// 管理画面・REST・ログイン済みユーザーには影響を与えない
	if ( is_admin() || defined( 'REST_REQUEST' ) || is_user_logged_in() ) {
		return;
	}

	// クエリパラメータ ?author=... を検知
	if ( ! empty( $_GET['author'] ) ) {
		// CLI / wp-cron 等の文脈は除外
		if ( ( defined( 'WP_CLI' ) && WP_CLI ) || ( defined( 'DOING_CRON' ) && DOING_CRON ) ) {
			return;
		}

		status_header( 404 );
		nocache_headers();
		// テーマの 404 テンプレートを描画して終了
		require get_query_template( '404' );
		exit;
	}
}, 1 );

ポイントは次の 3 つです。

  • init の優先度を 1(最速)にして、author アーカイブの組み立てよりも前に 404 を返す
  • 管理画面・REST・ログイン中ユーザーは除外(管理機能を壊さないため)
  • CLI / wp-cron も除外(バッチ処理で 404 がノイズにならない)

これで、https://example.com/?author=1 を踏まれても リダイレクトせず 404 になります。
ログインIDが URL から漏れる経路はここで遮断できます。

パーマリンクの author スラッグも変えておく

直接の漏洩経路は塞ぎましたが、テーマによっては投稿一覧で投稿者名のリンク(/author/admin/)が表示されています。
こちらも合わせて user_nicename を変更しておくのが定石です。

WordPress 管理画面 → ユーザー → 該当ユーザー → 「ニックネーム」「ブログ上の表示名」 を変更し、Edit Author Slug を入れているなら author スラッグも変更します。

プラグインを使いたくない場合は、wp-cliuser_nicename を直接書き換えても構いません。

wp user update 1 --user_nicename="editor-team"

対策レベル 3:REST API /wp-json/wp/v2/users を非ログイン時に無効化

avatar
あれ、`?author=1` を塞いだのに、まだバレるって聞いたよ?
avatar
鋭い!実は REST API 経由で全ユーザー名が一覧で返るんだよ。これも塞がないと意味がない。

WordPress は標準で REST API を提供しており、次の URL で 全ユーザーの公開情報が一覧取得できます。

GET https://example.com/wp-json/wp/v2/users

この API は ログインしていない第三者からも叩けます
返ってくる JSON の中には slug(user_nicename)や name(表示名)が含まれており、ここからもログインIDの推測が可能です。

子テーマの functions.php に次を追加して、非ログイン時の users エンドポイントを 401 で塞ぎます

/**
 * REST API /wp/v2/users を非ログイン時にブロック
 */
add_filter( 'rest_authentication_errors', function ( $result ) {
	// 既にエラーがある場合はそのまま返す
	if ( ! empty( $result ) ) {
		return $result;
	}

	// 現在のリクエスト URL を判定
	$path = isset( $GLOBALS['wp']->request ) ? $GLOBALS['wp']->request : '';
	$rest_prefix = rest_get_url_prefix(); // 通常は wp-json

	// /wp-json/wp/v2/users 系へのアクセスのみブロック
	if (
		strpos( $_SERVER['REQUEST_URI'] ?? '', '/' . $rest_prefix . '/wp/v2/users' ) !== false
		&& ! is_user_logged_in()
	) {
		return new WP_Error(
			'rest_forbidden',
			'このリソースには認証が必要です。',
			array( 'status' => 401 )
		);
	}

	return $result;
} );

これで、非ログイン状態で wp-json/wp/v2/users を叩いても 401 Unauthorized が返るようになり、ユーザー一覧の漏洩を防げます。

エディタ・著者・寄稿者などログインユーザーの操作には影響しません。

対策レベル 4:サイトマップ・投稿スラッグの確認

avatar
最後の仕上げ。実は XMLサイトマップにも author URL が出ていることがあるんだ。
avatar
えー、まだあるの〜!

WordPress 5.5 以降は、標準で /wp-sitemap.xml という XML サイトマップが生成されます。
そして、ここには author アーカイブのサブサイトマップが含まれることがあります。

実際にブラウザで叩いてみてください。

https://example.com/wp-sitemap.xml
https://example.com/wp-sitemap-users-1.xml

wp-sitemap-users-1.xml に author URL が並んでいれば、そこからも user_nicename が漏れます。
子テーマの functions.php に次を追加して、サイトマップの users セクションを完全に消します。

/**
 * 標準サイトマップから users(author アーカイブ)を除外
 */
add_filter( 'wp_sitemaps_add_provider', function ( $provider, $name ) {
	return ( 'users' === $name ) ? false : $provider;
}, 10, 2 );

これで /wp-sitemap-users-*.xml 自体が生成されなくなり、検索エンジン経由の漏洩経路もなくなります。

投稿スラッグ・テーマの投稿者リンク

最後に、テーマ側で投稿者名をリンク表示している箇所も確認します。
よくあるのは、投稿一覧・記事下部の「Posted by ◯◯」のような表示です。

  • 表示する必要がない → CSS や PHP で 非表示にする
  • 必須なら → 「ブログ上の表示名」を実名やID と無関係な値に変える

ここまで対応すれば、外部から user_login を特定する経路はほぼ塞げます。

確認方法(curl / ブラウザ)

avatar
対策したら、ちゃんと塞げてるか確認したいな。
avatar
そうだね!コマンドで一発確認できるよ。

対応後は、必ず次のコマンドで動作確認します。

# 1. ?author=1 が 404 になることを確認
curl -sI "https://example.com/?author=1" | head -1
# → HTTP/1.1 404 Not Found

# 2. /author/admin/ などが直接踏まれても 404 を確認
curl -sI "https://example.com/author/admin/" | head -1
# → HTTP/1.1 404 Not Found

# 3. REST users が 401 で塞がれていることを確認
curl -sI "https://example.com/wp-json/wp/v2/users" | head -1
# → HTTP/1.1 401 Unauthorized

# 4. サイトマップから users が消えていることを確認
curl -s "https://example.com/wp-sitemap.xml" | grep -i "users"
# → 何も返らなければOK

すべてクリアできていれば、?author=N 経由でのログインID漏洩はまず防げています。

まとめ:プラグインを増やさず、コードで根本から塞ぐ

WordPress の ?author=N 漏洩は、プラグインに頼ると入口だけ閉じて裏口が開きっぱなしになりがちな脆弱性です。
本記事の 4 段階を上から順に適用すれば、プラグインを増やさずに根本対策できます。

  • レベル 2:init フックで ?author=N を 404 にする
  • レベル 3:REST API /users を非ログイン時に 401 で塞ぐ
  • レベル 4:標準サイトマップから users を除外する
  • 最後に:curl で 4 経路をテストする

セキュリティ運用は 「対策の数」より「漏れている経路の数」 で評価するのが正解です。
入口を 1 つ塞いだから安心、ではなく、curl で全経路を確認してはじめて本当に塞いだことになります。

「自社サイトの author 漏洩、ちゃんと塞げているか不安」
「functions.php への追加が怖いので、専門家に見てほしい」
そんなときは、Mstudio で WordPress セキュリティの簡易監査もお請けしています。お気軽にご相談ください。

今のサイトに「あと少し」を。
あなたの想いを、いっしょに形にします。

  • 💬 まずは気軽に相談から
  • 🗓 最短1週間で初稿お届け
  • 🤝 公開後もずっとサポート
WordPressの ?author=1 でユーザー名がバレる問題を、プラグインなしで根本対策する方法 | Mstudio