WordPressサイトのセキュリティ強化:初心者でもできる堅牢な設定方法
はじめに
最近、私のWordPressサイト(Cocoonテーマを使用、ConoHa上で運用中)でセキュリティ診断を実施したところ、いくつかの警告が表示されました。専門用語が多くて最初は「何これ?」と思いましたが、ひとつずつ対応していったプロセスを記録しておきます。技術に詳しくない方でも同じように設定できるよう、なるべく簡潔に説明します。
【重要なお知らせ】 このシリーズは私がWordPressのセキュリティ強化に取り組んだ「体験記」として時系列で公開しています。
- 第1部(本記事):【Cocoon】CSP/クリックジャッキング対策|中級者ならできるセキュリティ強化
- 第2部:【Cocoon】.htaccessをいじったせいでAnalyticsとAdSenseが反映されなくなった話
- 第3部:【Cocoon】テザリングの落とし穴!AIOSでブルートフォース攻撃設定をしたら127.0.0.1 でログインできなくなった話
時系列での学びを追体験したい方はぜひ順番に読んでください。ただし、実際の実装には第3部の内容をベースにしてください。なぜなら第1部・第2部の設定だけでは特定の環境(モバイルテザリングなど)で問題が発生する可能性があるためです。第3部ではそれらの問題を含めた包括的な対策を解説しています。
セキュリティ診断で指摘された問題
診断結果で最初に目についたのは、「HTTP Strict Transport Security(HSTS)」が未設定という警告でした。これだけでなく、他にもいくつかのセキュリティヘッダーが設定されていないことがわかりました。
1. HSTS(HTTP Strict Transport Security)の設定
HSTSとは?
HSTSは、常に安全な接続(HTTPS)を利用するようブラウザに指示するヘッダです。このヘッダを設定することで、サーバのTLS証明書が信頼されない場合、ブラウザは接続自体を拒否します。さらに、ユーザーがhttp://で始まるURLにアクセスした際には、自動的にhttps://に変更されます。
簡単に言うと、HSTSはウェブサイトを常に暗号化通信(HTTPS)で表示するようブラウザに指示する仕組みです。これにより、「中間者攻撃」と呼ばれる、通信を途中で盗み見られる危険から守ることができます。
なぜHSTSが必要なのか?
最初私は「HTTPS接続するだけでいいんじゃないの?」と思いました。しかし、HTTPS接続時にHTTPSへのリダイレクトが設定されていても、中間者攻撃によって、HTTPSへのアップグレード前に悪意あるサイトへ誘導される恐れがあります。つまり、単にHTTPSを使っているだけでは不十分で、HSTSを設定することで追加のセキュリティ層が得られるのです。
HSTSの設定方法
.htaccessファイルに以下のコードを追加します:
# BEGIN HSTS
<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
</IfModule>
# END HSTS
この設定を.htaccessファイルの中の「# BEGIN WordPress」という行の前に追加します。
実際には、私のサイトでは「All In One WP Security」プラグインを使っていたので、「# END All In One WP Security」の行の直後に追加しました。
設定の期間について
HSTSの設定で悩んだのが「max-age」パラメータです。これは”ブラウザがそのサイトに対してHTTPSのみを使用する期間を秒単位で指定”するものです。
- テスト用: 300秒 (5分) – 設定のテストに適している
- 本番環境: 31536000秒 (1年) または 63072000秒 (2年) – 実運用に推奨される期間
「本番環境で1年とか設定したら、1年後にどうなるの?」と心配になるかもしれませんが、安心してください。この設定は自動的に更新されます。ユーザーがサイトを再訪問するたびに、サーバーは再びHSTSヘッダーを送信し、ブラウザの記憶期間がリセットされるのです。つまり、一度設定してしまえば、あなたが意識して更新する必要はありません。
preloadオプションについての注意点
HSTSヘッダーに「preload」パラメータを含めることで、主要ブラウザのプリロードリストへの登録が可能になります。これにより、ユーザーが初めてサイトを訪問する前からHTTPSのみを使用するよう強制できます。ただし、この設定を有効にするには、hstspreload.org でサイトを登録する必要があります。
重要な注意点: preloadリストへの登録は、簡単には取り消せません。将来HTTPSを無効にしたい場合や、サブドメインのいずれかがHTTPSをサポートできなくなった場合、ユーザーはサイトにアクセスできなくなる可能性があります。小規模サイトや実験的なプロジェクトでは、まずpreloadなしでHSTSを使用することを検討してください。
2. クリックジャッキング対策の設定
クリックジャッキングは、悪意のあるサイトがあなたのサイトを透明なフレーム内に埋め込み、ユーザーに気づかれないようにクリックさせる攻撃手法です。これに対する防御策として、以下の2つのヘッダーを併用するのが現在のベストプラクティスです。
X-Frame-Options設定
X-Frame-Optionsはレガシーブラウザもサポートする広く採用されたヘッダーで、サイトのフレーム内表示を制限します。
# BEGIN X-Frame-Options
<IfModule mod_headers.c>
Header always set X-Frame-Options "SAMEORIGIN"
</IfModule>
# END X-Frame-Options
「SAMEORIGIN」は、同じオリジン(ドメイン)からのフレーム内表示のみを許可するオプションです。
Content-Security-Policy frame-ancestors設定
X-Frame-Optionsは将来的には Content-Security-Policy (CSP) の frame-ancestors
ディレクティブに置き換えられる見込みです。最新のブラウザとの互換性を維持するために、両方を設定することが推奨されています。
# BEGIN Content-Security-Policy (Frame Protection)
<IfModule mod_headers.c>
Header always set Content-Security-Policy "frame-ancestors 'self';"
</IfModule>
# END Content-Security-Policy (Frame Protection)
frame-ancestors 'self'
は X-Frame-Options の “SAMEORIGIN” と同じ効果があり、同一オリジンからのフレーム内表示のみを許可します。
ただし、CSPの完全な設定は次のセクションで説明する通り、より包括的なものになります。
3. Content-Security-Policy(CSP)の設定
CSPとは?
コンテンツセキュリティポリシーは、XSS攻撃からサイトを保護するための非常に効果的な対策です。このポリシーを設定することで、承認されたコンテンツのソースのみをホワイトリストに登録し、ブラウザが悪意のあるアセットを読み込むのを完全に防ぐことができます。サイトの防御層として非常に重要な役割を果たします。
XSS(クロスサイトスクリプティング)とは、攻撃者があなたのサイトに悪意のあるスクリプトを挿入し、ユーザーのブラウザで実行させる攻撃です。CSPを設定することで、どのようなコンテンツ(スクリプト、スタイルシート、画像など)をどこから読み込むことを許可するかを指定できます。
CSPの包括的な設定
CSPには多数のディレクティブがあり、前述の frame-ancestors
だけでなく、あらゆる種類のリソースの読み込み元を制御できます。以下は基本的な設定例です:
# BEGIN Content-Security-Policy
<IfModule mod_headers.c>
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; frame-ancestors 'self';"
</IfModule>
# END Content-Security-Policy
この設定では:
default-src 'self'
: 基本的に同一オリジンからのリソース読み込みのみを許可script-src
: JavaScriptの読み込み元を制御style-src
: スタイルシートの読み込み元を制御img-src
: 画像の読み込み元を制御frame-ancestors 'self'
: 同一オリジンからのフレーム内表示のみを許可(X-Frame-Optionsの代替)
‘unsafe-inline’と’unsafe-eval’のリスクと代替策
上記の設定には’unsafe-inline’と’unsafe-eval’という値が含まれていますが、これらはセキュリティリスクを伴います:
- ‘unsafe-inline’: インラインのスクリプトやスタイルを許可しますが、XSS攻撃の可能性を残します
- ‘unsafe-eval’: eval()などの動的コード評価を許可しますが、悪意あるコードが実行される可能性があります
可能であれば、より安全な代替策を検討することをお勧めします:
# より安全なCSP設定(テーマやプラグインによっては動作しない場合があります)
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' https://trusted-cdn.example.com 'nonce-{RANDOM_NONCE}'; style-src 'self' https://trusted-cdn.example.com; img-src 'self' data:; frame-ancestors 'self';"
ただし、WordPressのテーマやプラグインは多くの場合インラインスクリプトやスタイルに依存しているため、’unsafe-inline’や’unsafe-eval’を完全に排除するのは難しいかもしれません。サイトの機能が損なわれる場合は、元の設定に戻すか、問題のあるリソースを特定して個別に許可することを検討してください。
なお、第2部では、Google AnalyticsやGoogle AdSenseなどの外部サービスをCSPで使用する方法について詳しく説明します。
4. Permissions-Policyの設定
Permissions-Policyとは?
権限ポリシーは、サイトがブラウザで使用できる機能とAPIを厳密に制御するための重要なヘッダーです。このヘッダーを適切に設定することで、サイトのセキュリティレベルを大幅に向上させることができます。
これはブラウザの特定の機能(カメラ、マイク、位置情報など)へのアクセスを制限するためのヘッダーです。ブログサイトなど、こうした機能を使用しないサイトでは、セキュリティ向上のためにアクセスを制限するのが賢明です。
Permissions-Policyの設定方法
Content-Security-Policyの設定の後に以下のコードを追加します:
# BEGIN Permissions-Policy
<IfModule mod_headers.c>
Header always set Permissions-Policy "camera=(), geolocation=(), microphone=(), payment=(), accelerometer=(), gyroscope=(), magnetometer=(), xr-spatial-tracking=()"
</IfModule>
# END Permissions-Policy
この設定により、カメラ、位置情報、マイク、支払い情報などへのアクセスを制限します。最新のブラウザでサポートされている他のセンサーAPIへのアクセスも制限することで、より完全な保護を提供します。
5. X-Content-Type-Optionsの設定
このヘッダーは、ブラウザがファイルの種類(MIMEタイプ)を自動判別せず、サーバーが指定した種類として扱うよう指示します。これにより、MIMEタイプのスニッフィングを利用した攻撃を防ぐことができます。
# BEGIN X-Content-Type-Options
<IfModule mod_headers.c>
Header always set X-Content-Type-Options "nosniff"
</IfModule>
# END X-Content-Type-Options
6. FTPからSFTPへの移行
セキュリティヘッダーを設定した後、もう一つ重要な課題がありました。FTPの平文通信の問題です。
FTPの問題点
FTP(File Transfer Protocol)は、暗号化なしの標準的なファイル転送プロトコルです。これを使用すると、ユーザー名、パスワード、データがすべて平文で送信されるため、深刻なセキュリティ上のリスクを抱えることになります。
私自身も最初は「公共Wi-Fiとか絶対に使わず、ブログやるとき、WordPressのログインは自分のスマホのテザリングを自宅でしかやらない」ので安全だと思っていました。しかし、FTP通信はサーバーとの間の経路全体で平文なのです。スマホのテザリングを使用しても、その後のインターネット上の経路(ISPのネットワーク、バックボーン回線など)では理論的に盗聴可能であり、絶対に安全とは言えません。この事実を理解することがセキュリティ強化の第一歩です。
特にECショップを作成予定であれば、SFTPへの移行はより重要です。
SFTPへの移行方法
SFTPはSSHプロトコルを使用してファイル転送を行う方式で、通信全体が暗号化されるので非常に安全です。セキュリティを重視するなら、FTPではなく常にSFTPを使用するべきでしょう。
ConoHaサーバーでは、FTP/FTPS/SFTP/SCPがすべて利用可能です(FTPSはexplicitモードのみ対応しています)。こうした多くのレンタルサーバーでSFTPが利用できるため、今すぐ移行することをお勧めします。
FTPクライアント(FileZillaなど)の設定を変更するだけでSFTPに移行できますが、ConoHaのファイルマネージャーを使う場合は特に設定変更は不要な場合が多いです。詳細はサーバー管理者に確認してみるとよいでしょう。
7. 追加のセキュリティ対策
ここまで説明した.htaccessファイルの設定に加えて、WordPressのセキュリティをさらに強化するための重要な対策をいくつか紹介します。
強力なパスワードと二要素認証の設定
- 強力なパスワード: 最低でも12文字以上の長さで、大文字、小文字、数字、特殊文字を含むパスワードを使用しましょう。管理者アカウントとデータベースには特に強力なパスワードを設定してください。
- 二要素認証: WordPressの二要素認証プラグイン(Google Authenticator、Wordfenceなど)を使用すると、パスワードが漏洩しても不正アクセスからアカウントを守ることができます。
WordPressと全プラグインの定期的な更新
WordPress本体、テーマ、プラグインは常に最新の状態に保つことが重要です。多くのセキュリティ脆弱性は更新で修正されるため、少なくとも月に1回はダッシュボードをチェックし、利用可能な更新をすべて適用しましょう。
自動更新を有効にすることも検討してください。wp-config.phpファイルに以下のコードを追加することで、WordPress本体の自動更新を有効にできます:
define('WP_AUTO_UPDATE_CORE', true);
不要なプラグインの削除
使用していないプラグインはセキュリティリスクとなります。定期的にインストール済みプラグインを確認し、必要ないものは削除しましょう。また、プラグインを選ぶ際は、以下の点を確認することをお勧めします:
- 定期的に更新されているか
- 多数のユーザーがインストールしているか
- 良いレビューを受けているか
- サポートフォーラムで質問に迅速に対応しているか
定期的なバックアップの取得
サイトが侵害された場合に備えて、定期的にバックアップを取得しておくことが重要です。以下のプラグインがバックアップに役立ちます:
- UpdraftPlus: 無料版でも定期的な自動バックアップが可能
- BackWPup: データベースとファイルのバックアップを別々に取得できる
- VaultPress (Jetpack): 自動バックアップとセキュリティスキャンを提供
バックアップは、サーバーとは別の場所(Dropbox、Google Drive、Amazonなど)に保存することをお勧めします。
8. WordPressセキュリティプラグインの比較
記事内で触れた「All In One WP Security」以外にも、WordPressセキュリティを強化するための優れたプラグインがあります。それぞれの特徴を簡単に紹介します:
All In One WP Security & Firewall
- 特徴: 使いやすいインターフェース、セキュリティスコアメーター、基本的なファイアウォール機能
- 料金: 無料
- 向いているユーザー: 初心者〜中級者
【補足:セキュリティプラグインのIPベース機能に関する注意】
All In One WP SecurityなどのプラグインでIPアドレスに基づくブロック機能を設定する場合、特にモバイルテザリングを使用している方は注意が必要です。IPアドレスが頻繁に変わる環境では、これらの機能が自分自身を「攻撃者」と誤認識してサイトからロックアウトする可能性があります。
セキュリティを高めることは重要ですが、自分がアクセスできなくなるほど厳しい設定は避け、IPに依存しない認証方法(二段階認証など)と組み合わせて使用することをお勧めします。
Wordfence Security
- 特徴: リアルタイムのファイアウォール保護、マルウェアスキャン、二要素認証、ライブトラフィックモニタリング
- 料金: 基本機能は無料、プレミアム版は年間$99〜
- 向いているユーザー: 中級者〜上級者、eコマースサイト
Sucuri Security
- 特徴: ファイアウォール(WAF)、マルウェア除去、改ざん検知、サイト修復
- 料金: 基本プラグインは無料、プレミアムサービスは年間$199〜
- 向いているユーザー: 中規模〜大規模サイト、高いセキュリティが必要なビジネスサイト
iThemes Security (旧Better WP Security)
- 特徴: 40以上のセキュリティ機能、ブルートフォース攻撃対策、マルウェアスキャン
- 料金: 基本版は無料、Pro版は年間$80〜
- 向いているユーザー: 小〜中規模のビジネスサイト
選び方のポイントは、サイトの規模、必要な保護レベル、予算、技術的な知識によって異なります。初心者の方は、All In One WP SecurityやiThemes Securityの無料版から始めるのがおすすめです。
設定後の効果
(自分にとって必要な)すべての設定を行った後、再度セキュリティ診断を実行しました。
Security Report Summary
A
Site: https://true-bank.love/
IP Address: 192.168.1.1(ここでは架空のIPアドレスや時間に変更して表示しています)
Report Time: 01 April 2100 12:34:56 UTC
Headers:Strict-Transport-Security
X-Frame-Options
Content-Security-Policy
X-Content-Type-Options
Referrer-Policy
Permissions-Policy
Warning capped at A, please see warnings below.
また、SSL Labsのレポートでは「A+」評価を獲得しました!これは全ての重要なセキュリティヘッダーが正しく設定されていることを示しています。
自分のサイトも診断してみたい方は、以下のツールをお試しください:
- セキュリティヘッダー診断: Security Headers
- SSL/TLS設定診断: SSL Labs
これらのツールは無料で使用でき、サイトのセキュリティレベルを簡単に確認できます。定期的に(少なくとも3ヶ月に1回程度)チェックして、セキュリティ設定が最新の基準を満たしているか確認することをお勧めします。
あなたのサイトを今すぐ守るための対策
WordPressサイトのセキュリティを強化するために、下記の対策を重要度順に実施してください:
優先度高(今すぐ対応すべき)
- HTTPS化とHSTSの設定: あらゆるサイトの絶対的な基本です。これなしでは他の対策も意味がありません。
- 強力なパスワードと二要素認証: サイトへの侵入を防ぐ最前線の防衛策です。今すぐ実施してください。
- WordPress、テーマ、プラグインの更新: 既知の脆弱性はすぐに修正し、攻撃者に付け入る隙を与えないようにしましょう。
- 定期的なバックアップ: 攻撃を受けた場合の保険です。これがないと復旧できない可能性があります。
優先度中(1週間以内に対応)
- セキュリティヘッダーの設定 (X-Frame-Options, CSP, Permissions-Policy): 多層防御の重要な一部です。
- FTPからSFTPへの移行: 特にECサイトでは絶対に必要です。平文通信は情報漏洩のリスクが非常に高いです。
- 不要なプラグインの削除: 攻撃対象となる面積を減らし、脆弱性リスクを低減します。
優先度低(今月中に対応)
- セキュリティプラグインの導入: 総合的な保護を提供し、セキュリティ管理を簡素化します。
- ログイン試行制限の設定: ブルートフォース攻撃を効果的に防止します。
これらの設定はすべて.htaccessファイルを編集するだけ、またはプラグインを使用するだけで簡単に実装できます。特にECサイトを運営している、または計画している場合は、今日中にこれらのセキュリティ対策を開始してください。遅延は危険を招きます。
まとめの実装例: すべてのセキュリティヘッダーの設定
以下のコードをWordPressの.htaccessファイルの「# BEGIN WordPress」行の前に追加してください:
# BEGIN Security Headers
<IfModule mod_headers.c>
# HSTS設定
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
# X-Frame-Options設定(クリックジャッキング対策の基本)
Header always set X-Frame-Options "SAMEORIGIN"
# Content-Security-Policy設定
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; frame-ancestors 'self';"
# Permissions-Policy設定
Header always set Permissions-Policy "camera=(), geolocation=(), microphone=(), payment=(), accelerometer=(), gyroscope=()"
# X-Content-Type-Options設定
Header always set X-Content-Type-Options "nosniff"
# Referrer-Policy設定
Header always set Referrer-Policy "strict-origin-when-cross-origin"
</IfModule>
# END Security Headers
このコードを追加することで、すべてのセキュリティヘッダーが一度に設定され、サイトのセキュリティが大幅に向上します。設定後、セキュリティ診断ツールで再度チェックして、すべてのヘッダーが正しく機能していることを確認してください。
よくありそうな質問(FAQ)
Q: これらの設定はサイトのパフォーマンスに影響しますか?
A: セキュリティヘッダーの追加による性能への影響は最小限です。ほとんどの場合、ユーザーが体感できるほどの遅延は発生しません。
Q: 設定後にサイトが表示されなくなった場合はどうすればよいですか?
A: バックアップから元の.htaccessファイルを復元するか、FTPアクセスで問題のある設定を削除してください。特にCSPは適用すると機能が損なわれることがあるため、段階的に導入することをお勧めします。
Q: これらの設定は定期的に更新する必要がありますか?
A: セキュリティ標準は時間とともに進化するため、少なくとも半年に一度は設定を見直し、最新のベストプラクティスに従って更新することをお勧めします。
最後に
専門用語に圧倒されないでください。この記事で説明したように、一つずつ対応していけば、技術的な知識が少なくても堅牢なセキュリティを構築できます。
対策を一つ実施するごとに、あなたのサイトはより安全になります。完璧なセキュリティは存在しませんが、これらの基本的な対策を実施することで、ほとんどの一般的な攻撃からサイトを効果的に守ることができます。サイトの安全は、あなたとあなたのユーザーの両方にとって非常に重要です。今すぐ行動しましょう。