最近の技術トレンドとしてはJAMstackが熱いらしいという情報をキャッチしまして。静的コンテンツジェネレータ自体はjekyllやOctopressが流行った辺りから導入していましたがコンパイルする手間が面倒に思えてしまってWordPressを使う機会がちょこちょことあります。やっぱりブラウザで完結するのは楽なんですよね。
JAMstackのメリットである「静的コンテンツを公開しているからセキュリティが高い」というのは理解が出来るのですが、農家が田んぼに農作業に向かうためにスーパーカー乗る必要はないのと一緒で、ある程度はセキュリティに寛容になって楽した方がいいよね派ではあります。全部が静的コンテンツにすべきってのは乱暴かなと。
かといってセキュリティを意識しないのは違うので、サーバー内で動的コンテンツを出力するメリットを得つつ可能な限りのセキュリティを高める方法ってどんな事出来るの? ってのを具体的にするために、私が管理しているWordPressサイトのセキュリティチェックと対応方法をまとめていこうと思います。お決まりの対応方法が存在するWordPressの知見はアプリケーション開発の現場で活用できるかと思います。
使用するツールはWPScan。Rubyのgemとして公開されているコマンドラインツール、WordPressのコアやプラグインの脆弱性を確認してくれます。こちらのツールは他人のサイトに実行してしまうのは厳禁です、悪意あるアクセスと思われてしまいます。
そのため、対象のサイトは私が管理しているこちらのサイト
自己紹介のために作成したサイトです。
2020年11月16日 時点で最新のWordPress version 5.5.3
公式テーマを使用しつつ子テーマを作成して微調整、プラグインも公式のみ使用しています。
自動更新はONにしたままなので全て最新の状態になっています。
セキュリティ系のプラグインとしてSiteGuardの導入を行っています。ログインページのアクセス制限や画像認証、ログインページURLの変更などができるため、各種レンタルサーバーで導入が推奨されています。
設置しているサーバーはレンタルサーバーのxserver、VPSに置いてもいいんですがOSのアップデートとか面倒なのでレンサバです。共用サーバーだけどSSH可、無料SSL対応、CPU 40個にメモリ188Gのサーバーを月1000円でアプリ置き放題でMySQLのDB無制限のメール送受信可のcrontab弄れるのは個人的に熱いです。
WPScanの実行結果
$ wpscan --url https://soramugi.net
_______________________________________________________________
__ _______ _____
\ \ / / __ \ / ____|
\ \ /\ / /| |__) | (___ ___ __ _ _ __ ®
\ \/ \/ / | ___/ \___ \ / __|/ _` | '_ \
\ /\ / | | ____) | (__| (_| | | | |
\/ \/ |_| |_____/ \___|\__,_|_| |_|
WordPress Security Scanner by the WPScan Team
Version 3.8.7
Sponsored by Automattic - https://automattic.com/
@_WPScan_, @ethicalhack3r, @erwan_lr, @firefart
_______________________________________________________________
[+] URL: https://soramugi.net/ [183.90.238.7]
[+] Started: Mon Nov 16 17:17:59 2020
Interesting Finding(s):
[+] Headers
| Interesting Entries:
| - server: nginx
| - x-mod-pagespeed: Powered By mod_pagespeed
| Found By: Headers (Passive Detection)
| Confidence: 100%
[+] robots.txt found: https://soramugi.net/robots.txt
| Interesting Entries:
| - /wp-admin/
| - /wp-admin/admin-ajax.php
| Found By: Robots Txt (Aggressive Detection)
| Confidence: 100%
[+] XML-RPC seems to be enabled: https://soramugi.net/xmlrpc.php
| Found By: Direct Access (Aggressive Detection)
| Confidence: 100%
| References:
| - http://codex.wordpress.org/XML-RPC_Pingback_API
| - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_ghost_scanner
| - https://www.rapid7.com/db/modules/auxiliary/dos/http/wordpress_xmlrpc_dos
| - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_xmlrpc_login
| - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_pingback_access
[+] WordPress readme found: https://soramugi.net/readme.html
| Found By: Direct Access (Aggressive Detection)
| Confidence: 100%
[+] This site has 'Must Use Plugins': https://soramugi.net/wp-content/mu-plugins/
| Found By: Direct Access (Aggressive Detection)
| Confidence: 80%
| Reference: http://codex.wordpress.org/Must_Use_Plugins
[+] The external WP-Cron seems to be enabled: https://soramugi.net/wp-cron.php
| Found By: Direct Access (Aggressive Detection)
| Confidence: 60%
| References:
| - https://www.iplocation.net/defend-wordpress-from-ddos
| - https://github.com/wpscanteam/wpscan/issues/1299
[+] WordPress version 5.5.3 identified (Latest, released on 2020-10-30).
| Found By: Rss Generator (Passive Detection)
| - https://soramugi.net/feed/, <generator>https://wordpress.org/?v=5.5.3</generator>
| - https://soramugi.net/comments/feed/, <generator>https://wordpress.org/?v=5.5.3</generator>
| - https://soramugi.net/feed/podcast, <generator>https://wordpress.org/?v=5.5.3</generator>
[i] The main theme could not be detected.
[i] Plugin(s) Identified:
[+] contact-form-7
| Location: https://soramugi.net/wp-content/plugins/contact-form-7/
| Latest Version: 5.3 (up to date)
| Last Updated: 2020-10-21T10:25:00.000Z
|
| Found By: Hidden Input (Passive Detection)
|
| Version: 5.3 (100% confidence)
| Found By: Hidden Input (Passive Detection)
| - https://soramugi.net/, Match: '5.3'
| Confirmed By:
| Readme - Stable Tag (Aggressive Detection)
| - https://soramugi.net/wp-content/plugins/contact-form-7/readme.txt
| Readme - ChangeLog Section (Aggressive Detection)
| - https://soramugi.net/wp-content/plugins/contact-form-7/readme.txt
[+] seriously-simple-podcasting
| Location: https://soramugi.net/wp-content/plugins/seriously-simple-podcasting/
| Latest Version: 2.4 (up to date)
| Last Updated: 2020-11-09T15:30:00.000Z
|
| Found By: Meta Tag (Passive Detection)
|
| Version: 2.4 (100% confidence)
| Found By: Meta Tag (Passive Detection)
| - https://soramugi.net/, Match: 'Seriously Simple Podcasting 2.4'
| Confirmed By:
| Readme - Stable Tag (Aggressive Detection)
| - https://soramugi.net/wp-content/plugins/seriously-simple-podcasting/readme.txt
| Readme - ChangeLog Section (Aggressive Detection)
| - https://soramugi.net/wp-content/plugins/seriously-simple-podcasting/readme.txt
[+] wordpress-seo
| Location: https://soramugi.net/wp-content/plugins/wordpress-seo/
| Latest Version: 15.2.1 (up to date)
| Last Updated: 2020-11-02T14:14:00.000Z
|
| Found By: Comment (Passive Detection)
|
| Version: 15.2.1 (100% confidence)
| Found By: Comment (Passive Detection)
| - https://soramugi.net/, Match: 'optimized with the Yoast SEO plugin v15.2.1 -'
| Confirmed By:
| Readme - Stable Tag (Aggressive Detection)
| - https://soramugi.net/wp-content/plugins/wordpress-seo/readme.txt
| Readme - ChangeLog Section (Aggressive Detection)
| - https://soramugi.net/wp-content/plugins/wordpress-seo/readme.txt
[i] No Config Backups Found.
[!] No WPVulnDB API Token given, as a result vulnerability data has not been output.
[!] You can get a free API token with 50 daily requests by registering at https://wpvulndb.com/users/sign_up
[+] Finished: Mon Nov 16 17:18:03 2020
[+] Requests Done: 23
[+] Cached Requests: 36
[+] Data Sent: 8.208 KB
[+] Data Received: 70.311 KB
[+] Memory used: 245.828 MB
[+] Elapsed time: 00:00:03
基本的には 「[!]」で表示された内容に対応すれば問題なく、上記のログをみた限りでは全く問題がないサイトになります。
(APIトークンを使えと言われてますが自分の場合は同じ出力結果になったため今回は使用してません、回数制限があるのであまり使いたく無い…)
WordPressは自動更新と公式テーマと公式プラグインを使って必要かどうかを精査しておけばセキュリティ的には問題ないものになっています。
問題は無いのですが、出力された内容は「こういう情報が取得できましたよ」というものになるため、せっかくなので非表示にする対応や情報表示される理由を確認して悪用される種を摘んでおこうと思います。(この記事の本題)
ヘッダーの値削除
[+] Headers
| Interesting Entries:
| - server: nginx
| - x-mod-pagespeed: Powered By mod_pagespeed
| Found By: Headers (Passive Detection)
| Confidence: 100%
リクエストヘッダーの値が確認できます。実行アプリケーションが確認できれば攻撃方法も特定しやすくなるため非表示にしてみます。
xserverはnginxが起動していますが、.htaccess が使用できます
.htaccess に以下を追加
Header unset x-mod-pagespeed
Serverの記述削除は効かない?ようなので未対応
DoS攻撃対策
本格的なDoS攻撃をされた場合にはアプリケーションレベルでの対応ではどうしようもないので基本的には不要ですが、高負荷になりやすい箇所の理解のためにも使用できる対処を施します。
xmlrpcの無効化
[+] XML-RPC seems to be enabled: https://soramugi.net/xmlrpc.php
| Found By: Direct Access (Aggressive Detection)
| Confidence: 100%
| References:
| - http://codex.wordpress.org/XML-RPC_Pingback_API
| - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_ghost_scanner
| - https://www.rapid7.com/db/modules/auxiliary/dos/http/wordpress_xmlrpc_dos
| - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_xmlrpc_login
| - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_pingback_access
モバイルアプリからの更新のためにxmlrpcを使用するため存在しているファイルですが、DoS攻撃に悪用されてしまう可能性がある機能です。モバイルアプリからの更新は行わないので無効にします。
.htaccessに以下を追加
<Files xmlrpc.php>
order deny,allow
deny from all
#allow from xxx.xxx.xxx.xxx # アクセスする必要が出たらIP指定
</Files>
wp-cron.php 無効化
[+] The external WP-Cron seems to be enabled: https://soramugi.net/wp-cron.php
| Found By: Direct Access (Aggressive Detection)
| Confidence: 60%
| References:
| - https://www.iplocation.net/defend-wordpress-from-ddos
| - https://github.com/wpscanteam/wpscan/issues/1299
WordPressでの予約投稿をした場合、指定時間での公開をチェックするためにユーザーアクセス時に wp-cron.php が実行されます。これもDoSに悪用される危険があるため無効化、予約投稿やバックアップの処理、自動更新もwp-cronで実行されるのでサーバー内のcronで実行するように変更します。
wp-config.php
<?php
define('DISABLE_WP_CRON', 'true'); # 先頭に記載しないと無効にできない
crontab
* * * * * /usr/bin/php7.4 /path/to/wordpress/wp-cron.php > /dev/null 2>&1
.htaccess
<Files wp-cron.php>
order deny,allow
deny from all
#allow from xxx.xxx.xxx.xxx
</Files>
バージョン情報の削除
[+] WordPress readme found: https://soramugi.net/readme.html
| Found By: Direct Access (Aggressive Detection)
| Confidence: 100%
[+] WordPress version 5.5.3 identified (Latest, released on 2020-10-30).
| Found By: Rss Generator (Passive Detection)
| - https://soramugi.net/feed/, <generator>https://wordpress.org/?v=5.5.3</generator>
| - https://soramugi.net/comments/feed/, <generator>https://wordpress.org/?v=5.5.3</generator>
| - https://soramugi.net/feed/podcast, <generator>https://wordpress.org/?v=5.5.3</generator>
自動更新を有効化して常に最新にしていれば問題ありませんが、古いバージョンの脆弱性を突くための確認をさせないためにバージョン情報を表示させないようにします。(意味あるのか?)
バージョン情報を削除しすぎてしまうと更新時のキャッシュ廃棄がうまくいかずに、表示崩れやバグの原因になる可能性もあるのでほどほどに。
.htaccess
<Files readme.html>
Require all denied
</Files>
<Files license.txt>
Require all denied
</Files>
functions.php (子テーマの作成、もしくはプラグイン化を推奨)
// rssのURLに出力されるversionの無効化
add_filter('the_generator', '__return_empty_string');
プラグインのバージョン表示もありましたが、プラグイン毎にバージョン非表示用のメソッドは用意されていないため、こちらは対応見送り
contentのディレクトリ変更
プラグインディレクトリへの直アクセスが可能になっています。脆弱性が発見されているプラグインへの直アクセスを狙われる可能性もあるためcontentディレクトリを変更します。
wp-config.php
define('WP_CONTENT_DIR', dirname(__FILE__) . '/contents');
define('WP_CONTENT_URL', 'https://' . $_SERVER['SERVER_NAME'] . '/contents');
define('WP_PLUGIN_DIR', WP_CONTENT_DIR . '/plugins');
define('WPMU_PLUGIN_DIR', WP_CONTENT_DIR . '/plugins');
define('WP_PLUGIN_URL', WP_CONTENT_URL . '/plugins');
define('WPMU_PLUGIN_URL', WP_CONTENT_URL . '/plugins');
define('PLUGINDIR', WP_CONTENT_URL . '/plugins');
robots.txt
あとはrobots.txtに記載があるというこのメッセージ
[+] robots.txt found: https://soramugi.net/robots.txt
| Interesting Entries:
| - /wp-admin/
| - /wp-admin/admin-ajax.php
| Found By: Robots Txt (Aggressive Detection)
| Confidence: 100%
はおそらく対象パスにファイルがあることを記しているということになりますが、この記述を消したところで意味はなく、ajaxの機能を除外するのはコストが高すぎるためスルーです。
終わりに
以上です。
セキュリティチェックは一度対処して終わりでは無いため、自動更新の有効化をしたり最新の情報を定期的に収集することをお勧めします。WordPressは特定バージョンへのセキュリティパッチは存在しないため、常に最新に保つようにしましょう。
WordPress.orgニュース
https://wordpress.org/news/
脆弱性一覧
https://wpscan.com/wordpresses