メインコンテンツまでスキップ

Allgrow-labo Wordpress Site Security Guideline

はじめに

​ はじめに「Wordpressのセキュリティーリスクについて」記載する。

続いて、「WordPressサイト制作時のセキュリティー対策」と、「WordPressサイト運用上のセキュリティー対策」について記載する。

弊社が制作・運営するWordpressサイトは必ず本ドキュメントに記載されているセキュリティー対策の実施を厳守すること。

本ドキュメントにおけるセキュリティー対策の内容は、Wordpressについてのセキュリティー対策に限定されている。使用されるデバイス、接続されるネットワーク、Linux, PHP, Apache, MySQLなどのセキュリティーについては、本ドキュメントにおけるセキュリティー対策の範囲対象外とする。

本ドキュメントにおけるセキュリティー対策は、一般的な方法で制作・運用されているWordpressサイトを想定している。そのためカスタマイズされたWordpressサイトにはそのまま適用できない場合があるが、本ドキュメントはWordpressサイトのセキュリティーリスクの内容の共有とその対策を行う際の参考になることを目的としているため、カスタマイズされたWordpressサイトでも同様のセキュリティーリスクが存在するものとして必ず対応を行うこと。 ​ ​

Wordpressのセキュリティーリスクについて

​ WordPressは世界中で使用されているオープンソースCMSである。W3Techsの調査によると、2022年8月時点でのCMSにおけるWordPressシェアは64.2%となっている。

2位以降のCMSとのシェア率が大きく異なり、世界中で非常に多くの人が利用していることが分かる。

ハッカーの立場で考えると、利用者の多いシステムを狙ったほうがハッキングに成功する可能性が高くなる。WordPress内の脆弱性(システム上の弱いところ)を1つ発見できれば、WordPressを利用している多数のWebサイトを標的にでき効率よくハッキングが進められるのだ。

そのため、WordPressはハッカーの標的となりやすい背景がある。そのうえ、WordPressはオープンソースであり、世界中の開発者が応用できるようコードを公開している。

コードは開発者のみでなくハッカーも閲覧できるため、脆弱性の発見やセキュリティをかいくぐる施策を検討しやすい状況になっている。

👉 引用元:https://lucy.ne.jp/bazubu/wordpress-security-2-23873.html ​ ​

Wordpressサイト制作時のセキュリティー対策​

1. ログインURLへのアクセス可能なIPアドレスを制限する

​ 予め管理画面を利用するユーザーが利用するIPアドレスが分かっている場合、IPアドレスによるアクセス制限を行うことで、不正なアクセスを防ぐことができる。

apacheを利用する方法

デフォルトのWordpressのログインURLがあるディレクトリに以下のような.htaccessファイルを設置し、許可するIPアドレスを指定する。 ​

<Files "wp-login.php">
Order Deny,Allow
Deny from All
Allow from xxx.xxx.xxx.xxx
</Files>

PHPを利用する方法

composerなどのツールでWordpressの管理している場合は、htaccessをWordpressのコアファイル内に配置できないので、PHPでIP制限を設ける。 ​

add_action('login_form', function () {
if (!in_array($_SERVER["REMOTE_ADDR"], ['xxx.xxx.xxx.xxx'])) {
wp_safe_redirect(home_url());
exit;
}
}, 10);

2. ログインURLを変更する

プラグインを利用する方法

下記、2つのプラグインがよく利用されており、プロジェクトの更新頻度も高い。 ​

プラグインを利用しない方法

以下のログインURLに変更するケースを想定して、サンプルコードを記載する。 ​

https://some-wordpress-site.com/company-login-1234.php

company-login-1234.phpに以下のように記述する。
このファイルはwp-login.phpを読み込み、wp-login.phpからWordpressのコアファイルが読み込まれるので、LOGIN_CHANGEの定数が反映される。 ​

<?php
define('LOGIN_CHANGE', sha1( 'keyword' ));
require_once './wp-login.php';

​ 次に、Wordpressのテーマ開発の場合、functions.phpに以下の記述をする。
login_initへのadd_actionwp-login.phpからアクセスがあった場合、定数LOGIN_CHANGEが存在しないので、リダイレクトされることになる。 また、site_url, wp_redirectにフィルターをかけることで、wp-login.phpとしてWordpressが処理する内容を独自のログインページへ変更することができる。 ​

$login_page = 'company-login-1234.php';

add_action( 'login_init', function () {
if ( !defined('LOGIN_CHANGE') || sha1('keyword') !== LOGIN_CHANGE ) {
wp_safe_redirect( home_url() );
exit;
}
});

add_filter('site_url', function ($url, $path,) {
if ($path == 'wp-login.php' &&
(is_user_logged_in() || strpos( $_SERVER['REQUEST_URI'], $login_page ) !== false)
) {
$url = str_replace( 'wp-login.php', $login_page, $url );
return $url;
}
}
, 10, 2);

add_filter('wp_redirect', function login_change_wp_redirect( $location, $status ) {
if (strpos( $_SERVER['REQUEST_URI'], $login_page ) !== false) {
$location = str_replace( 'wp-login.php', $login_page, $location );
return $location;
}
}, 10, 2);

3. 推測されにくいパスワードとユーザー名を設定する

ユーザー名について

デフォルトで頻繁に使用される初期ユーザー名adminは容易に推測が可能なので、変更すること。

パスワードについて

WordPressのパスワードを破る手法としては、「Brute-force attack(ブルートフォースアタック)」が利用される。

英数字・大文字・小文字を含めた6桁のパスワードは、約5日で解除されてしまう。しかし、10桁に増やすと1千万年の時間を要する。 つまり、パスワードを英数字・大文字・小文字を含めた10桁以上に変更するだけでハッキング対策ができる。

そのため、パスワードは可能な限り10桁以上の英数字・大文字・小文字を含めたものにすることが望ましい。

また、強固なパスワードであっても、情報漏洩が発生した場合、ハッカーはパスワードを利用することができてしまう。そのため、パスワードは定期的に変更することが望ましい。 ​ ​

4. 適切なパーミッション設定・不要ファイルの削除

パーミッションについて

Wordpressは、基本的には以下のようにパーミッションを設定する。

ファイル名パーミッション
.htaccess644
wp-config.php600 or 400
ディレクトリ755 or 705
ファイル644 or 604

​ 以下は、コマンドラインでの一括操作の例 ​

$ find /var/www/html -type f -print | xargs chmod 664
$ find /var/www/html -type d -print | xargs chmod 775

ファイル削除について

その後、サイト表示に不要なファイルは削除する。 ​

  • readme.html (Wordpressのバージョン情報がある)
  • license.txt (Wordpressのバージョン情報がある)
  • wp-config-sample.php (接続するとエラーになる)
  • install.php (Wordpressのインストール後は不要なファイル) ​ ​

5. wp-config.phpファイルの適切な取り扱い

wp-config.phpへのアクセスを制限するように.htaccessに下記のコードを記述する。 また、パーミッションも適切に設定する。管理者ではないとアクセスできないよう400が望ましい。 ​

<Files wp-config.php>
Order Deny,Allow
Deny from All
</files>

​ また、roots.ioBedrockのようにwp-config.phpファイルをWebサイトの公開領域外に配置することも有効である。 ​ ​

6. プラグインの使用は必要最小限にする

​ Wordpress PluginはPHPの実装経験がなくても手軽に利用できるメリットがあるが、サイトパフォーマンスを下げたり、場合によってはセキュリティ惰弱性を引き起こす可能性がある。 Wordpressサイト制作でプラグインを利用する必要がある場合、以下の手順を踏み検討すること。 ​

  1. プラグインが本当に必要か検討する。(自分自身で実装できる内容は自身で実装した方が、実装者がリスクを把握できる。)
  2. プラグインを利用する場合、プラグインの公式サイトを確認し、アップデートが1年以上行われていないものは採用は見送る。
  3. 惰弱性対策情報データベースを使用して、利用したいプラグインにセキュリティ惰弱性が無いかを確認する。 ​ ​

7. Wordpressのバージョン情報を非表示にする

​ Wordpressのバージョンを非表示にすることで、ハッカーがWordpressのバージョンを特定することを防ぐことができる。以下のコードをfunctions.phpに記述する。 ​

remove_action('wp_head','wp_generator');

8. PHP XML パーサーの無効化

xmlrpc.phpへのアクセスを制限するように.htaccessに下記のコードを記述する。 ​

<Files xmlrpc.php>
Order Deny,Allow
Deny from All
</Files>

Wordpress公式サイトのセキュリティノートに、WordPress 3.9.2で解決されたと記載があるが、慣習として対応しておくことが望ましい。特に、Wordpressのバージョンが3.9.2よりも古い場合には、必ず対応すること。 ​ ​

9. ユーザー名が推測されることを防ぐ

​ 以下のURLにアクセスすると、Wordpressで使用されているユーザー名を確認することができる。(1~から順番に試せば、すべてのユーザーを確認可能) 管理画面に対して有効なセキュリティ対策を行えない状況であれば、ユーザー名が特定されるとパスワードのみ特定すればハッカーからの攻撃にさらされる危険性が高まる。 ​

https://some-wordpress-site.com?author=1

​ Wordpressでは自動的に投稿者アーカイブを作成してしまうため、 もし投稿者アーカイブページが不要であれば、function.phpに以下のように記載して、投稿者アーカイブページを非アクティブにする。 ​

add_filter( 'author_rewrite_rules', '__return_empty_array' );

​ 投稿者アーカイブページを使用している場合、?author=1のようなURLが入力された際に、Wordpressで使用されているユーザー名であると露呈しないように、404ステータスでリダイレクト処理を行うこと。 ​

add_action('init', function () {
if( preg_match('/author=([0-9]*)/i', $_SERVER['QUERY_STRING']) ){
wp_safe_redirect(home_url('/404.php'));
exit;
}
});

​ また、REST APIからもユーザー情報の取得が可能だ。(/wp-json/wp/v2/usersのURLからアクセス可能) このURLも不要であれば、使用できないように以下のように編集しておくこと。 ​

add_filter('rest_endpoints', function ($endpoints) {
if (isset($endpoints['/wp/v2/users'])) {
unset($endpoints['/wp/v2/users']);
}
if (isset($endpoints['/wp/v2/users/(?P[\d]+)'])) {
unset($endpoints['/wp/v2/users/(?P[\d]+)']);
}
return $endpoints;
}, 10, 1);

10. ユーザーロールを分けてユーザーを管理する

​ 投稿者アーカイブページが有効であり、複数のユーザーが存在する場合、 権限の強いadministratorやeditorユーザーの投稿者アーカイブページにもアクセスできてしまう。 この場合、投稿者アーカイブページで使用されるユーザーロールを限定的にして、権限の強いユーザーは表示させないようにすること。 ​

define('ROLES_THAT_CAN_DISPLAY_AUTHOR_ARCHIVES', [
'author',
]);

define('USER_NAMES_THAT_CAN_DISPLAY_AUTHOR_ARCHIVES', [
'user01',
]);

function can_display_user($user)
{
return in_array($user->user_login, USER_NAMES_THAT_CAN_DISPLAY_AUTHOR_ARCHIVES, true)
|| count(array_diff(ROLES_THAT_CAN_DISPLAY_AUTHOR_ARCHIVES, $user->roles)) < count(ROLES_THAT_CAN_DISPLAY_AUTHOR_ARCHIVES);
}

add_action('template_redirect', function () {
if (!is_author()) {
return;
}
$user = get_queried_object();
if (can_display_user($user)) {
return;
}
wp_safe_redirect(home_url('/404.php'));
exit;
});

Wordpressサイト運用上のセキュリティー対策​

1. データベースバックアップを定期的に行う

​ コマンドラインからの操作が可能な場合、コマンドでデータベースのバックアップを取得できる。 ​

$ mysqldump -u [user_name] -p [databese] > [backup_file_name.sql]

​ これをcronなどで定期的に実行することで、データベースのバックアップを行うことができる。 ​ コマンドラインからの操作が不可能な場合は、以下のプラグインを利用することで、管理画面からデータベースのバックアップを行うことができる。 https://wordpress.org/plugins/backwpup/ ​ いずれの場合でも、バックアップの保存先は、サイトが設置されているサーバー内ではなく、別のサーバーに保存することが望ましい。 ​ ​

2. ソースコードはバージョン管理して管理する

​ ソースコードはバージョン管理ツールを利用して管理することで、ソースコードの変更履歴を管理することができる。 不正なアクセスがあり、ソースコードが改変されている場合、変更履歴を確認することで、不正なアクセスの内容を特定することができる。 ​

git status

3. Wordpressを最新の状態に保つ

Wordpress公式サイトのセキュリティノートを確認すると、Wordpressのコア開発では、セキュリティー惰弱性の修正を目的としてマイナーアップデートと新規機能追加のためのメジャーアップデートが行われている事がわかる。 (セキュリティーアップデートが行われた場合、Wordpress公式サイトのセキュリティに関するニュースでアナウンスされる。) ​ ​

Wordpressの自動更新設定について

​ Wordpressの公式は、すべてのWordpressサイトで自動更新設定にしておくことを推奨しており、コアファイルの自動更新設定はデフォルト設定となっている。 ​ この自動更新設定による弊害として、テーマやプラグインで使用されている処理が自動で実行される更新後に、いつの間にか正常に処理されなくなってしまう可能性があることだ。テーマやプラグイン側で複雑な処理を行っており、自動更新により問題が発生するリスクを考慮する場合には以下のコードでWordpressの自動更新設定を無効化することもできる。 ​

define('WP_AUTO_UPDATE_CORE', false);

​ Wordpressのアップデートにより、テーマやプラグインの動作不良の発生リスクと、セキュリティーリスクへの対応を両立させなければならない状況では、マイナーアップデートのみを許可する設定にしておく選択もある。 ​

define('WP_AUTO_UPDATE_CORE', 'minor');

​ Wordpressのバージョンをcomposerで管理しているプロジェクトのの場合、Wordpressの自動更新設定を有効にしておくと、composerでの管理バージョンと実際のバージョンに差が出てしまい望ましい状況ではない。 そのため、github dependabotを利用してWordpressの更新情報を取得し、composer.jsonのバージョンを更新するように設定することが望ましい。 ​ プロジェクトの性質によって対応方法は異なるので、プロジェクトの性質を考慮した上で以下の優先度で対応する。 ​

  1. 自動更新設定を行う。(github dependabot, github-actionの組み合わせでも可)
  2. minorアップデートのみ自動更新設定を行い、majorアップデートは手動で行う。
  3. 自動更新設定を行わず、リリースノートを確認し手動でアップデートを行う。 ​ ​

4. Pluginは最新の状態に保つ・使用しないものは削除する

プラグインの削除について

プラグインを使用しない場合は、Wordpressの管理画面から削除することは、セキュリティ惰弱性のリスク減らすことになる。1ヶ月以上に渡って使用されていないプラグインは削除すること。 ​

Wordpress Pluginの自動更新設定について

​ プラグインは、Wordpressのコア開発とは別の開発者が開発しているため、Wordpressのコア開発とは別のタイミングでアップデートが行われる。 ​ Wordpressの公式は、プラグイン・テーマ・翻訳ファイルにおいても自動更新設定にしておくことを推奨しており、自動更新設定はデフォルト設定となっている。 ​ PluginやThemeは個別に自動更新を停止することを定義できないが、以下のコードで全ての自動更新を無効化することができる。(Wordpressのコアファイルの自動更新設定も含まれる。) ​

define( 'AUTOMATIC_UPDATER_DISABLED', true );

​ プラグイン更新に関する対応方針は、Wordpressコアファイルのアップデートと同様となる。 プラグイン・テーマに自動更新を適用しない場合、将来的なセキュリティーリスクが発生する可能性が有ることを念頭においてサイト運用を行うこと。 ​

  1. 自動更新設定を行う。(github dependabot, github-actionの組み合わせでも可)
  2. 自動更新設定を行わず、リリースノートを確認し手動でアップデートを行う。 ​ ​

参考資料

OWASP Wordpress Security Implementation Guideline

Security note (Wordpress official)

OWASP Top 10 2021:

wpscan.com

その他