LoginSignup
25
18

More than 5 years have passed since last update.

[WordPress] /?author=xx をちゃんと阻止した話

Last updated at Posted at 2017-05-28

2019.04.16補足
実際に実装してみたところ、[2017.05.29補足]のようにhtaccessに1行を追加すると、

/?author=1 => /author/hoge => 302 redirect

となり、/author/hoge を経由してしまうため本文同様(ログインIDが明示される)の状態になります。

RewriteRule ^\?author=(.*)? / [R=302,L]

も併せて設定されることをおすすめします。


2017.05.29補足
PHP(Wordpress)上でリダイレクトを行わなくても、htaccessに一行足せば簡単に問題が解決しました...。

RewriteRule ^author/(.*)? / [R=302,L]

mikkame 様からご指摘を受けました。ありがとうございます。


事の発端

とある管理サイトでの話。
/?author=xxでユーザーのログインIDが漏れるのは知っていたので

author.php
<?php header('Location: ' . get_bloginfo('url') . '/403.php'); exit; ?>

と403ページへ転送していました。
これに加えてAudit Trailというプラグインでログイン失敗だけ記録

これでひとまず安心...。しかしレンタルサーバーのエラーログを見ていたら

Error.log
WordPress Login Failure: adminID from xxx.xxx.xxx.xxx

と、ログインIDがバレていた!!

どうしてだろうか...

前後のエラーログやアクセスログを見ても/?author=xxxmlrpc.phpへのアクセスばかりでさっぱりわからず。

xmlrpc.phpも念のためアクセス制限をかけていました。使わないので。

<Files "xmlrpc.php">
order deny,allow
deny from all
</Files>

curl

ダメ元でcurlコマンドで叩いてみました。

# オプションなし
$ curl http://example.com/?author=xx

リダイレクト処理を行っているので応答なし。

そこでもしや、と思い -v をつけてHeaderを表示。

# リクエストヘッダーとレスポンスヘッダーの両方を見ることができます。
$ curl http://example.com/?author=xx -v
*   Trying xxx.xxx.xxx.xxx...
* TCP_NODELAY set
* Connected to example.com (xxx.xxx.xxx.xxx) port 80 (#0)
> GET /?author=xx HTTP/1.1
> Host: example.com
> User-Agent: curl/7.51.0
> Accept: */*
> 
< HTTP/1.1 301 Moved Permanently
< Date: Sun, 28 May 2017 19:07:33 GMT
< Server: Apache/2.2.31
< X-Powered-By: PHP/5.6.30
< Location: http://example.com/author/adminID/
< Content-Length: 0
< Content-Type: text/html; charset=UTF-8
< 
* Curl_http_done: called premature == 0
* Connection #0 to host example.com left intact

なんと、ヘッダーに隠したはずのログインIDが書かれているではないですか!!

対応策

大急ぎで対応を検討しました。
しかし、Headerの出力をWordPressで制御するのは大変。
そこで以下のようにリライトを制御。author.phpを経由することなくTOPページへリダイレクトするようにしました。

functions.php
function author_custom_redirection() {
    global $wp_rewrite;
    $wp_rewrite->flush_rules();
    $wp_rewrite->author_base = '';
    $wp_rewrite->author_structure = '/';
    if (isset($_REQUEST['author']) && !empty($_REQUEST['author'])) {
        wp_redirect(home_url());
        exit;
    }
}
add_action('init', 'author_custom_redirection');

補足
のちの参考リンク先ではif分岐が一段多いですが、これはログイン済みユーザーと非ログイン者とで処理を分けているからです。今回はログイン済みユーザーもauthor.phpを見ることができない仕様にしました。

# リクエストヘッダーとレスポンスヘッダーの両方を見ることができます。
$ curl http://example.com/?author=xx -v
*   Trying xxx.xxx.xxx.xxx...

# ### 中略 ###

< HTTP/1.1 301 Moved Permanently
< Date: Sun, 28 May 2017 19:07:33 GMT
< Server: Apache/2.2.31
< X-Powered-By: PHP/5.6.30
< Location: http://example.com
< Content-Length: 0
< Content-Type: text/html; charset=UTF-8
< 
* Curl_http_done: called premature == 0
* Connection #0 to host example.com left intact

無事にHeaderからもログインIDが消えました!!

まとめ

/?author=xxを非表示にする方法としてよく挙がる「author.phpからのリダイレクト」では抜け穴があることを学べました。ありがとうございました。

参考リンク

authorクエリを利用したWordPressのユーザー名漏洩を防ぐ方法

25
18
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
25
18