実はやらなくてもいい6つのWordPressセキュリティ対策
セキュリティ対策は、やった方がいいことを全てやることではない。
誤解されがちなWordPressのセキュリティ対策について解説します。
- 「やらなくていい」設定
- 「やった方がいいけど、別にやらなくてもいい」設定
- 「やるべき」設定
この記事では下線の項目の解説をします。
なお「やるべき」設定については別な記事を用意しています。(記事の最後にあります)
バージョン情報を隠す
推奨レベル: ★☆☆☆☆
まずは「やらなくていい」設定から紹介します。
使用しているWordPressのバージョンに脆弱性があった場合に攻撃を受けないようにするものとして設定している方がいらっしゃいますが、効果はなく、設定によっては不具合が生じる可能性もあるのでやめましょう。
設定の効果
WordPressは定期的にアップデートが必要なCMSです。
世界中で使われているので、脆弱性があるとすぐに攻撃されてしまうからです。
すぐにアップデートしない場合、脆弱性があるバージョンのWordPressを放置することになります。
そこで、WordPressのページに出力されるバージョン情報を隠すことで攻撃を防ぐ効果を発揮します。
という認識を持っている方がよくいますが、実は効果がありません。
バージョン情報は隠せない
まずは上記のWordPress公式サイトのソースを見てください。
以下のようなタグが出力されているかと思います。
<meta name="generator" content="WordPress 5.9-alpha-51951" />
これがWordPressのバージョン情報です。
ja.wordpress.orgはWordPressの開発版を使用していることが分かりますね。
簡単にできるので、これを出力しないように設定する方は非常に多いです。
しかしそれだけでは不十分です。
別な箇所に以下のようなタグも出力されているかと思います。
<link rel='stylesheet' id='wp-block-library-css' href='https://ja.wordpress.org/wp-includes/css/dist/block-library/style.min.css?ver=5.9-alpha-51951' type='text/css' media='all' />
<style id='wp-block-library-inline-css' type='text/css'>
.has-text-align-justify{text-align:justify;}
</style>
<link rel='stylesheet' id='wporg-global-header-footer-css' href='https://ja.wordpress.org/wp-content/mu-plugins/pub-sync/blocks/global-header-footer/build/style.css?ver=1635463862' type='text/css' media='all' />
<link rel='stylesheet' id='mediaelement-css' href='https://ja.wordpress.org/wp-includes/js/mediaelement/mediaelementplayer-legacy.min.css?ver=4.2.16' type='text/css' media='all' />
<link rel='stylesheet' id='wp-mediaelement-css' href='https://ja.wordpress.org/wp-includes/js/mediaelement/wp-mediaelement.min.css?ver=5.9-alpha-51951' type='text/css' media='all' />
<link rel='stylesheet' id='dashicons-css' href='https://s.w.org/wp-includes/css/dashicons.min.css?ver=5.9-alpha-51951' type='text/css' media='all' />
上記の1,7,8行目をよく見てください。URLの後ろに「?ver=5.9-alpha-51951」という文字列があります。?ver=以降はバージョン情報と同じ文字列です。
上記に加えて、これを出力しないようにする設定を行っている方も見受けました。
しかし、それでも不十分です。
WordPressはオープンソースソフトウェアなので、バージョンアップした場合に更新されるファイルは分かります。まじまじとcssやjsファイルを見られた場合(※)、どのバージョンを使っているかは特定可能です。
※ハッシュ値で簡単に比較可能です
いたちごっこですね。WordPressのバージョン情報は隠せるものではないので当然です。
ちなみに「?ver=バージョン情報」の文字列を出力しないようにした場合、デメリットがあります。
「?ver=バージョン情報」は必要
通常、サイトを閲覧したブラウザは、通信量を削減するためにファイルをローカルにキャッシュします。
アクセスありがとう!
CSSは「style.min.css?ver=5.8.2」を使ってね!
「style.min.css?ver=5.8.2」のファイルをリクエストするよ!
あ、前回アクセスした時にキャッシュしてたから、やっぱりリクエストはやめてキャッシュしたファイルを使うよ!
しかしサイト側のファイルに更新があった場合は、新しいファイルを参照しなければなりません。
アクセスありがとう!
CSSは「style.min.css?ver=5.9」を使ってね!
キャッシュに「style.min.css?ver=5.8.2」のファイルがあるけど、文字列が違うから別物だね。
「style.min.css?ver=5.9」のファイルをリクエストするよ!
これはCache Bustingと言われている手法で、例えばWordPressのバージョンアップ時、新しいURLとして認識させることで常に最新状態のファイルを参照させることができます。
新しいファイルを参照させる手法は色々ありますが、確実性の高い手法であるため、よく使われます。
つまり、この文字列を隠すと何が起きるか?
WordPressのバージョンアップを行ったのにもかかわらず、サイトに訪問したユーザーに更新前の古いファイルを参照させてしまい、サイトの表示が崩れる可能性があるということです。
攻撃時はバージョン情報を見ない
多くのハッカー(クラッカー)は攻撃時にバージョン情報を見ていません。
以下は私がWordPressで使用しているセキュリティ系プラグインのアクセス履歴です。
何やら怪しげなアクセスがたくさんありますね。全て拒否されていますが、これらのアクセス元は世界中のサイトに対して同じリクエストを送り付けて無差別に攻撃しているので、そんなことはお構いなしです。
アクセスログの途中にある「/owa/auth/logon.aspx」に対するアクセスに関しては、WordPressは拡張子がphpであるのに対してログの拡張子がaspxであることから、WordPressへのアクセスですらない(※)ことが分かります。
自分がハッカー(クラッカー)だったら、という立場で考えてみれば簡単です。
身近なサイトとにらめっこしてあら探しするよりも、何百万のサイトに同じリクエストを送り付けるやり方の方が効率がいいからそのような行動を取っているのです。
「下手な鉄砲も数打ちゃ当たる」とはこのことですね。
※「/owa/auth/logon.aspx」に対する不審なアクセスはMicrosoft Exchange Serverの脆弱性(CVE-2018-16793)を狙った攻撃です。
もちろん無差別ではなく、標的を定めるタイプの攻撃者も存在します。あなたが有名人ならばなおさらで、そういった攻撃者はバージョンを確認してくる可能性があります。
抜本的な対策は最新に保つこと
抜本的な対策は、WordPressのバージョンを常に最新に保つことです。
そもそもの話は「WordPressに脆弱性があった場合の対策」だったはずです。
脆弱性なら修正されるので、バージョンアップを怠らないようにしましょう。
WordPressには自動アップデート機能もあります。
実際には、使用しているプラグインや社内フローなどの関係ですぐにアップデートできないかもしれません。限度はありますがそれは仕方ないと思います。
だからといって「バージョン情報を隠して誤魔化そう」という対策に意味はありません。
データベースの接頭辞の変更
推奨レベル: ★★☆☆☆
よく紹介される設定です。
効果がないとは言い切れませんが、脆弱性がある状況でのみ効果を発揮する上、それも抜本的な対策にならないため重要性は低いです。
設定の効果
WordPressのデータベーステーブルにはユーザー情報が格納される「wp_users」、投稿情報が格納される「wp_posts」などがあります。
この「wp_」の部分はデフォルトの接頭辞であり、変更が可能です。
WordPressはOSSなので、テーブル構造はよく知られています。
この接頭辞をデフォルトから変更することでテーブル名を隠し、不正なクエリを未然に防止できるというのがこの設定の効果です。
不正なクエリとは?
WordPressに使われているMySQL(MariaDB)に対して発行するSQL文(クエリ)を悪用したものです。
ここでいう不正なクエリは、大きく分けて2つのことが可能です。
- データの盗取
- データの改ざん
データベース内部に含まれるデータすべてが対象です。
つまり、データベース内部に登録されているパスワードのハッシュ値や固定ページや投稿記事などすべてが盗取・改ざん対象になるということです。
このような不正なクエリを発行されることは通常ありませんが、テーマやプラグインにSQLインジェクションという脆弱性があった場合は不正なクエリが発行されてしまい、被害を受けることになります。
つまりこの設定は「SQLインジェクション対策を目的とした設定」ということになります。
SQLインジェクションの対策にはならない
仮にSQLインジェクションの脆弱性があった場合、以下のSQLでテーブル名の取得が可能です。
SELECT DISTINCT SUBSTRING(TABLE_NAME FROM 1 FOR ( LENGTH(TABLE_NAME)-8 ) ) FROM information_schema.TABLES WHERE TABLE_NAME LIKE '%postmeta';
実行すると以下が返ってきます。
+------------------------------------------------------------+
| SUBSTRING(TABLE_NAME FROM 1 FOR ( LENGTH(TABLE_NAME)-8 ) ) |
+------------------------------------------------------------+
| wp_ |
+------------------------------------------------------------+
1 row in set (0.001 sec)
接頭辞を他の文字列にしていた場合でもその文字列が返ってきます。
実際にSQLインジェクションを狙う場合は一工夫必要ですが、これはトリッキーな手法でも何でもなく、MySQL(MariaDB)に存在するinformation_schemaテーブルを使ったごく普遍的なものです。
任意のSELECT句を発行できてしまう場合はこのように接頭辞の特定が可能です。
WordPressのテーマやプラグインの開発者の実装が誤っていた場合、SQLインジェクションは現実に起こり得ます。調べてみれば分かりますが、事実、プラグインの脆弱性の報告が時々上がっています。
2021年にも有名なプラグイン「All in One SEO」からSQLインジェクションの脆弱性が発見されました。
(考察)対策にならないというが、全く効果がないわけではない?
接頭辞を取得する必要がある都合上、実際にSQLインジェクションを悪用するにはリクエストを2回送る必要があるというところまで想像がついた方もいるのではないでしょうか。
- 1回目のリクエストで接頭辞(例:wp_)を取得
- 2回目のリクエストでwp_usersをSELECT(もしくはDELETE)
多くの攻撃者は無差別に被害を出したいでしょう。
適当にリストアップしたサーバーに対して1回だけリクエストを送って完結させるのが理想なので、「2回リクエストを送る必要がある」という時点でハードルになっています。
私は実際に送られたSQLインジェクションのリクエスト内容を見たことがないので何とも言えないのですが、無差別な攻撃者は「接頭辞はwp_である」という前提で攻撃を仕掛けてくるかもしれません。
そうであるとするなら、この設定は「100%効果がないわけではない」ということになります。
「★★☆☆☆」なのはそういう理由です。
ちなみに1回のリクエストで完結しそうなSQLも書いてみました。
SET @sql_injection_test = CONCAT('SELECT * FROM ', (SELECT DISTINCT SUBSTRING(TABLE_NAME FROM 1 FOR ( LENGTH(TABLE_NAME)-8 ) ) FROM information_schema.TABLES WHERE TABLE_NAME LIKE '%postmeta'), 'users');
PREPARE p_sql_injection_test FROM @sql_injection_test;
EXECUTE p_sql_injection_test;
「FROM句に他のテーブルから持ってきた動的な文字列を指定する」というところが難しいですね。
コンソール上からしか確認していないので、実際にプログラム上から使えるかどうかまでは確認してません。PHPからだとPDOの関係で実行できないかもしれませんが、仮に使えたとして、実際にこういうの使ってくるんでしょうかね?
ただいずれにしても、もしかすると2回リクエストを送ってくる律儀な攻撃者がいるかもしれませんし、無差別ではなく標的型攻撃の場合にアウトなのは変わりません。
過度な期待は禁物です。
SQLインジェクションを防ぐ方法
SQLインジェクションの対策は難しいですが、基本的には以下を守れば大丈夫です。
- テーマとプラグインのバージョンを常に最新に保つ
- 長期間(2年とか)更新が途絶えているテーマやプラグインは使用しない
SQLインジェクションはプログラムの実装が原因になる脆弱性です。
サーバーの設定などに関係なく発生します。
テーマやプラグインに依存した使い方をしている以上、「定期的にアップデートがある有名どころのテーマやプラグインなら大丈夫です」以上のことは言えません。
更新が止まっているようなものは脆弱性が発見されてもアップデートが来ないので論外です。
Web Application Firewall (WAF)
一応更なる対策はあって、WAFにはSQLインジェクションを防ぐ効果があります。
もしSQLインジェクションを本気で対策するならWAFを導入してください。
ただ、WAFは運用が難しく、誤検知による不具合が起きやすいので注意が必要です。
不具合が起きたからテーマやプラグインのバグだと思ったらレンタルサーバーで有効にしていたWAFが原因だった、という話も耳にします。
- 不具合という、脆弱性とは異なるリスクを抱えて運用できるだけの知識があるか?
- その時間を対象のサイトにかけられるか?
WAFの導入は上記を自問した上で検討するべきです。
接頭辞を変更できるのはなぜ?
WordPressには標準で接頭辞を変更できる機能が搭載されているため、このような設定が可能になっています。
なぜこの機能が存在するかというと、マルチサイト機能の利用や、1つのデータベースに複数のWordPressをインストールすることを想定しているからです。
つまりセキュリティ対策を意図した機能ではありません。
複数WordPressに関しては公式ドキュメントがあるので、詳細は以下でどうぞ。
複数 WordPress サイトのインストール | WordPress.org 日本語
結局のところ、設定すべき?
以下の理由から設定する意味は薄いです。
- 効果があるのはSQLインジェクションに対してのみ
- そのSQLインジェクションも防げない場合がある
- セキュリティ対策を意図した機能ではない
特にデメリットがないので設定してもいいですが、それよりも使用しているテーマ・プラグインのバージョンを最新に保つ方が効果があります。
前項と結論は変わらないですね。
とはいえ、バージョンアップをするまで危険な状態になってしまうのは事実です。
それが許容できない場合はWAFの利用を検討された方がいいと思います。(スキルがある前提ですが)
WAFはサーバーに導入するタイプが主流ですが、WordfenceのようなプラグインにもWAF機能はあります。
そういったWordPressに特化したWAFの方が不具合は少ないかもしれません。
ユーザー名を隠す
推奨レベル: ★★☆☆☆
こちらもよく紹介される設定です。
効果はあるといえばありますが、一般的なセキュリティ対策ではありません。
ユーザー名はどこに表示されるか
WordPressにおけるユーザー名は以下に表示されます。
- 固定ページや投稿記事の投稿者名
- RSSフィードのdc:creatorタグ
- REST APIである「ドメイン名/wp-json/v2/users」にアクセスした時のレスポンス内容
- XMLサイトマップ
2つ目と3つ目はそれぞれ「フィードの無効化」や「REST APIの制限」などの対策で隠します。
これらの情報を全て隠蔽することが、即ちユーザー名を隠すことです。
ユーザー名を隠すと何がいいのか
ユーザー名をパスワードと同等にできるので、不正ログインされる確率が減ります。
ご存じの通り、パスワードは「自分しか知らない文字列」です。
自分で作った文字列を誰にも教えないことで、その文字列は初めてパスワードになります。
ユーザー名を誰にも教えなければ、それはもうパスワードです。
WordPressは「ユーザー名」と「パスワード」の2つの文字列を入力しなければログインできないので、2つとも自分しか知らない文字列なら他人が当てることはより難しくなります。
「効果がある or ない」じゃない
効果があるか否かで話をするなら、効果はあります。
ただ原初に立ち返って話をしましょう。
WordPressは公式で「ユーザー名は公開情報である」と位置付けています。
The WordPress project doesn’t consider usernames or user ids to be private or secure information. A username is part of your online identity. It is meant to identify, not verify, who you are saying you are. Verification is the job of the password.
Why are disclosures of usernames or user IDs not a security issue?
Generally speaking, people do not consider usernames to be secret, often sharing them openly. Additionally, many major online establishments — such as Google and Facebook — have done away with usernames in favor of email addresses, which are shared around constantly and freely. WordPress has also moved this way, allowing users to log in with an email address or username since version 4.5.
Instead of attempting to hide a public identifier, WordPress attempts to encourage users to choose strong passwords instead, through both user interface as well as education.
上記について、私は以下のようなことを伝えようとしていると解釈しました。(めっちゃ意訳なので注意)
- ユーザー名は秘密にするものじゃなくて、みんなに公開するものだよ
- GoogleとかFacebookではメールアドレスとパスワードの組み合わせでログインしてるよね
- メールアドレスって公開情報だよね
- じゃあWordPressのユーザー名も公開情報で大丈夫だね
- 強力なパスワードを使えばユーザー名を隠す必要ないよ
「何のためにパスワードというものがあるのか?」を考えれば答えにたどり着けます。
ユーザー名は他人に自分を認識してもらうための文字列であり、他人から隠すものではありません。
強力なパスワードの定義
ユーザー名を隠す代わりに、強力なパスワードを使えばいいということが分かりました。
2021年時点の一般的な話をしますが、以下が強力なパスワードの基準です。
- 「アルファベットの大文字・小文字」「数字」「記号」をすべて含めている
- 最低でも8文字以上である
- 「12345678」のような当てずっぽうで特定できる文字列ではない
- 自分の名前や誕生日など、推測しやすい文字列ではない
「他で使っているパスワードではない」とかもありますが、割愛します。
ちなみに「8文字以上」というのは諸説あります。
8文字というのは割と一般的な認知で、IPA(経済産業省の管轄組織)でも以下のように記載しています。
安全なパスワードとは?
今、パスワードが危ない!
□最低でも8文字以上の文字数で構成されている。
□パスワードの中に数字や、「@」、「%」、「"」などの記号も混ぜている。
□パスワード内のアルファベットに大文字と小文字の両方を入れている。
対して、内閣サイバーセキュリティセンターの資料には以下の記載があります。
総当たり攻撃は、攻撃し続ければ理論上はいつかは成功するのですが「時間がかかり事実上不可能な状態」にして防ぎます。ログイン用パスワードであれば入力ごとに時間がかかるので、英大文字小文字+数字+記号混じりで 10 桁以上を安全圏として推奨します。しかし、より桁数を増やして安全性を高めるに超したことはありません。
[PDF] インターネットの安全・安心ハンドブック Ver 4.10 第1章 P30
8文字とか10文字のようなブレがあるのは、時代とともにコンピュータの性能が上がるに伴って、パスワードの適切な長さが変わるからです。
上記にも少し説明がありますが、パスワードを長くて複雑にする理由は総当たり攻撃を防ぐためなので、コンピュータの計算能力に左右されます。
2019年時点でも、1秒間に1000億個のパスワードを試せる環境が3000円以下で作れるみたいですね。
かといって、長すぎるパスワードを設定すると今度は覚えられなくなります。
ちょうどいい塩梅がいいです。
ユーザー名を隠すべき唯一のパターン
ここまで言っておいてなんですが、実はユーザー名を隠すべきパターンというのは存在します。
仮に以下の要件のサイトがあったとしましょう。
- 従業員を100人以上抱えた企業のポータルサイト
- ポータルサイトはWordPressで構築している
- ポータルサイトには全従業員がログイン可能である
- 社内連絡のほか、従業員同士で連絡を取ることができる
- 社外からも閲覧できるようにするため、インターネットからアクセス可能である
さらに、以下の運用を行っていたとします。
- ポータルサイトには全従業員に対する登録を義務付けている
- 他の従業員から分かるようにするため、ユーザー名は従業員の個人名とする
この条件で運用していた場合、対策しなければ全社員の個人名が流出します。
REST APIを使えば、WordPressに登録している全てのユーザーに関するデータを取得できます。
このデータにユーザー名も含まれているので、ユーザー名に個人名を使っているとアウトです。
客先常駐や派遣社員などの他社の人間も含まれていたらもう大惨事ですね。
従業員が10000人以上いる大企業とかだったらニュースになるんじゃないでしょうか。
同じ条件ではないので安全でしたが、私が新入社員として入社したIT企業でもこういうサイトはありました。
企業で使う場合は要注意ですね。
結局のところ、隠すべき?
個人で使う場合は、以下を守れば隠す必要はありません。
- ユーザー名に公開したくない情報(個人名など)を付けない
- パスワードを強力な文字列にする
聞き飽きるほど当たり前なことです。
隠さなくてもいいならやらなくていいのでは? というのが本記事での意見です。
以下の記事でも隠す方法を解説していますが、このサイトではユーザー名を公開情報として扱っています。
企業の場合は運用次第ですね。
それでも、ほとんどのケースで隠す必要はありません。
フィードの無効化
推奨レベル: ★☆☆☆☆
ユーザー名の流れで紹介しますが、これは「やらなくていい」設定です。
RSSフィードにユーザー名が載ることからフィードを無効化する方がいますが、別にフィードを無効化しなくてもユーザー名を隠すことはできます。
ユーザー名を隠すか否か以前の問題です。フィードは無効化すべきではありません。
REST APIの制限
推奨レベル: ★★☆☆☆
REST APIは、特定のURLにアクセスすることでWordPress内のデータをJSON形式で取得できる機能です。
前述の通りREST APIでユーザー名を取得できること、また危険という印象があることからよく制限や無効化する設定を紹介されます。
REST APIで取得可能な情報
以下のようなデータを取得可能です。
- 登録されているユーザーの情報
- 投稿された記事の情報
- 登録されているカテゴリやタグの情報
- アップロードした画像やファイルの情報
上記は一部です。
なお当たり前ですが、ユーザーのパスワードなど重要な情報は含まれません。
「投稿された記事はREST APIとか関係なく見れるじゃん?」という疑問ですが、REST APIはプログラムが理解しやすいJSON形式でデータを取得できるところが魅力の機能です。
一部のテーマやプラグインなんかもこれに依存した作りになっています。ユーザーのための機能ではなく、開発者のための機能ということです。
「REST APIは危険」という誤解
WordPress 4.7.0から4.7.1には、REST APIの脆弱性がありました。
REST APIは4.7.0で登場した新機能でした。
しかし深刻な脆弱性が存在し、少なくとも155万のサイトが改ざん被害に遭ってしまいました。
緊急リリースされた4.7.2で修正されましたが、とても大きな衝撃です。
これがきっかけで「REST APIは危険な機能である」という認知が世間一般に広まったのではないかと思います。
「WordPressそのものが危険である」と思われた方も中にはいるでしょうね。これは仕方ない
WordPressのメジャーなセキュリティ系プラグインもREST APIを制限できる機能を付けています。
それはこのような歴史的事情があるからです。
しかし、この事件は2017年の話です。
もしかするとまだ発見されていない脆弱性があるかもしれませんが、それは全ての機能に対して言えることです。
制限するデメリット
前述した通り、テーマやプラグインの中にはREST APIに依存した作りのものがあります。
(有名どころだとContact Form 7、Caldera Form、Yoast SEO、Jetpackなど)
むやみに制限すると知らず知らずのうちに不具合に悩まされるリスクがあります。
また、WordPressそのものにもREST APIに依存した機能があります。
具体的には以下です。
- アプリケーションパスワード
- WordPressのモバイルアプリ
アプリケーションパスワードは外部アプリケーションとWordPressを認証する仕組みで、WordPressのモバイルアプリはスマートフォンなどからWordPressを使うためのアプリです。
REST APIを制限すると、これらが使えなくなる恐れがあります。
この先、バージョンアップに伴って実装される新機能でもREST APIが必要になるかもしれません。
制限したい現実的なケース
ユーザー名に関しては既に説明済みなので省略します。
REST API絡みで他に考えられるとすれば、コピーサイト対策です。
REST APIを使えば記事のデータをプログラムが加工しやすい形で取得できるので、大企業のサイト・大手メディア・人気ブロガーなどの場合、悪用して大量にコピーサイトを作られてしまうかもしれません。
ただ、REST APIを制限したところでスクレイピングという手法を使えばこれまたコピー可能です。
いたちごっこなので、最初から対策をするのではなく「コピーサイトが量産されている」という被害に遭ってから対策を講じた方が現実的だと思います。
あとは未公開情報の制限です。
ログイン状態にかかわらず、REST API経由ならWordPressにアップロードした画像やファイルデータのURLが分かるので、URLを知っている人だけが閲覧できる記事やファイルを見られたくない場合は対策が必要です。
結局のところ、制限するべき?
ほとんどの場合は制限しなくてもいいです。
特に前述のユーザー名問題がクリアになるならなおさらです。
むしろ制限することにデメリットがある以上、明確な理由がなければ制限せずにそのまま使うべきです。
アクセスログが気持ち悪い件について
REST APIの中でも、/wp-json/wp/v2/users/に対する不審なアクセスはとても多いです。
REST API経由ならばログイン用のユーザー名を取得できる可能性が高いため、恐らくはこれを足掛かりにして不正ログインを試みようという魂胆なのでしょう。
何度も言いますが、ユーザー名が分かったところで問題はありません。
ただ「何となくアクセスされているのが気持ち悪い」と感じる方はいるでしょう。
そう感じる方は制限した方が精神衛生上いいかもしれません。
デメリットを理解した上で制限する分には問題ないからです。
ログインページを隠す
推奨レベル: ★★★☆☆
今まで紹介したものと違って効果があると断言できますが、必須と言えるほどの重要性はありません。
ログインページへのアクセス方法
WordPressのログインページは、サイトのURLの末尾に以下のいずれかを付けることでアクセスできます。
- /login/
- /admin/
- /wp-login.php
つまりログインページには誰でもアクセスできます。
あとはユーザー名とパスワードが分かれば不正ログインの条件は整います。
上記によるアクセスを無効(リダイレクトさせない設定)にし、任意の文字列でアクセスできるようにするという設定がログインページを隠すということです。
2つのメリット
不正ログインの未然防止
攻撃者がログインページにたどり着くことができなければ、不正ログインされることもありません。
パスワードと同じで、ページにアクセスするための文字列を複雑なものにすれば、より高い効果があります。
サーバー負荷の軽減
それほど大きなものではありませんが、サーバー負荷対策になります。
世界中にあるサーバーに無差別なアクセスを行い、初期設定のログインURLに対して機械的に総当たり攻撃を仕掛けてくる攻撃者は一定数存在します。
DoS攻撃ほどではないものの、それなりにサーバーへ負荷をかけるということと同義だからです。
1つのデメリット
ログインページを隠すことにはデメリットがあります。
それは、ログインページにアクセスするための文字列を忘れるとログインできなくなることです。
このことからログインページはブックマークして使うことを推奨します。
同様に、短くて思い出しやすい文字列にしている方も多いのではないかと思います。
複数人で管理するサイトである場合は全員が見れるところにURLを記載しているケースもあるでしょう。
そういったことを行うと当てずっぽうで文字列を当てられたり、URLが流出するリスクが大きくなります。
個人で管理することが当たり前で、忘れたとしても画面から再発行が可能なパスワードとは性質が違います。
ログインページにアクセスするための文字列を忘れても、復旧は可能です。
ただし正攻法の手段では不可で、サーバーにアクセスしてWordPress内部の特定のディレクトリ名を変更する作業が必要です。
隠すことが重要ではない理由
WordPress以外のサービスで考えてみてください。
これらのログインページは、隠されていますか?
- Google: https://www.google.com/accounts/Login
- Facebook: https://facebook.com/login/
- Twitter: https://twitter.com/login
答えは「いいえ」です。
ちなみにWordPressの開発元が運営しているWordPress.comも同様です。
https://wordpress.com/log-in/
上記を見て分かる通り、ログインページは隠さないのが普通です。
しかも大企業やWordPressの開発元までもが、です。
というよりも「公開しないと誰もログインできないので隠せない」が正解ですが
WordPressは世界一使われているCMSなのでアカウントが狙われるのは必然ですが、Googleなどのアカウントの方がはるかに重要で狙われやすいでしょう。
これらのサービスは、なぜログインページを隠さずとも高いセキュリティを保てるのでしょうか?
それでもセキュリティを担保できている理由
その理由は、名だたるWebサービスは以下のような仕組みを設けているからです。
- 「パスワードが8文字以上でなければアカウントを登録できない」などの制限がある
- 何度もログインに失敗するとアクセス制限がかかる
- 2要素認証を設定できる
総当たり攻撃を含めた対策を複数用意することで不正ログインの成功確率を減らしています。
「ログインページのURLを隠す」という対策は一般的なWebサービスでは取れない手段なので、その他の手段でセキュリティを担保しています。
パスワードは自衛できますし、WordPressでもログイン失敗によるアクセス制限や2要素認証の設定は可能です。
こういうものは小手先のテクニックよりも教科書通りの一般的なセオリーに従った方がいいです。
実は劣化Basic認証?
話は逸れますが、管理者用ページにベーシック認証を掛ければ別途ID/パスワードによる認証が可能になります。
ここでのID/パスワードは、WordPressに登録しているユーザー名/パスワードとは別です。
両者ともログインページへアクセスするには文字列が必要ですね。
ログインページを隠した場合は任意の文字列が必要で、
ベーシック認証をかけた場合は任意のID+任意のパスワードが必要です。
ベーシック認証の方が必要な情報量が多いので、実はこちらの方が優れています。
PHPのようなバックエンドに到達しない認証方法なのでサーバー負荷という点でも強いです。
結局のところ、隠すべき?
「やった方がいいけど、別にやらなくてもいい」設定ではありますが、どちらかと言えばやった方がいいです。
理由は、デメリットが比較的小さなものだからです。
URLを忘れないようにすればいいだけですし、ブックマークをすれば忘れにくいので運用負荷も低いでしょう。
特殊な作業が必要になるものの、もし忘れた場合でも復旧は可能です。
「サーバー負荷の軽減」というメリットもついでに得られますし、基本的には設定することをおすすめします。
ただし一般的なセオリーに基づいたセキュリティ対策ではなく、WordPress特有のセキュリティ対策であることは頭の片隅に入れておきましょう。万能な設定ではありません。
おさらい
「やらなくていい」設定
効果なしの設定です。
- ★☆☆☆☆ バージョンを隠す
- ★☆☆☆☆ フィードの無効化
「やった方がいいけど、別にやらなくてもいい」設定
万人に効果があるとまでは言い切れない設定です。
- ★★☆☆☆ データベースの接頭辞の変更
- ★★☆☆☆ ユーザー名を隠す
- ★★☆☆☆ REST APIの制限
- ★★★☆☆ ログインページを隠す
本当にやるべき設定
以下記事で解説します。