2026年9月10日
2026年9月10日
WordPressにセキュリティヘッダーを追加する方法・XSS・クリックジャッキング対策
はじめに
「セキュリティチェックツールでヘッダーが足りないと指摘された」「XSSやクリックジャッキング攻撃への対策をしたい」——HTTPセキュリティヘッダーを適切に設定することで、ブラウザレベルで多くの攻撃を防御できます。
症状・原因
WordPressはデフォルトでセキュリティヘッダーをほとんど送信しません。https://securityheaders.com/でサイトをチェックすると「F」評価になることが多く、XSS・クリックジャッキング・MIMEスニッフィングなどの攻撃に対して無防備な状態です。
解決手順
ステップ1:現在のヘッダーを確認する
# 現在のレスポンスヘッダーを確認
curl -I https://example.com/ | grep -i \
-e "x-frame" -e "x-content" -e "strict-transport" \
-e "content-security" -e "referrer" -e "permissions"
# セキュリティヘッダーのグレードチェック
# https://securityheaders.com/?q=https://example.com/
# SSLの設定もチェック
# https://www.ssllabs.com/ssltest/
ステップ2:Nginxでセキュリティヘッダーを追加する
# /etc/nginx/conf.d/security-headers.conf
server {
# ...
# クリックジャッキング防止
add_header X-Frame-Options "SAMEORIGIN" always;
# MIMEタイプスニッフィング防止
add_header X-Content-Type-Options "nosniff" always;
# XSS保護(古いブラウザ向け)
add_header X-XSS-Protection "1; mode=block" always;
# HTTPS強制(HSTS)- 1年間
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# リファラーポリシー
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Permissions Policy(カメラ・マイク等のAPI制限)
add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=()" always;
# Content Security Policy(CSP)- 基本設定
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://www.google-analytics.com https://www.googletagmanager.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https:; frame-ancestors 'self';" always;
}
sudo nginx -t && sudo systemctl reload nginx
ステップ3:WordPressのfunctions.phpでヘッダーを追加する
// セキュリティヘッダーをWordPress経由で送信
add_action( 'send_headers', function() {
// クリックジャッキング防止
header( 'X-Frame-Options: SAMEORIGIN' );
// MIMEタイプスニッフィング防止
header( 'X-Content-Type-Options: nosniff' );
// HSTS(HSTSはHTTPS環境のみ)
if ( is_ssl() ) {
header( 'Strict-Transport-Security: max-age=31536000; includeSubDomains' );
}
// リファラーポリシー
header( 'Referrer-Policy: strict-origin-when-cross-origin' );
// Permissions Policy
header( 'Permissions-Policy: camera=(), microphone=(), geolocation=()' );
} );
ステップ4:Content Security Policy(CSP)を設定する
CSPは最も強力ですが、設定が難しいヘッダーです。まずはレポートモードで始めましょう。
// CSPをレポートモードで開始(本番適用前の確認用)
add_action( 'send_headers', function() {
$csp_report_only = implode( '; ', [
"default-src 'self'",
"script-src 'self' 'unsafe-inline' 'unsafe-eval' https://www.google-analytics.com",
"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com",
"font-src 'self' https://fonts.gstatic.com",
"img-src 'self' data: https:",
"connect-src 'self' https://www.google-analytics.com",
"frame-ancestors 'self'",
"report-uri /wp-json/csp/v1/report", // 違反レポートの受信先
] );
// まずはReport-Onlyで違反を収集
header( 'Content-Security-Policy-Report-Only: ' . $csp_report_only );
} );
// CSP違反レポートを受信するエンドポイント
add_action( 'rest_api_init', function() {
register_rest_route( 'csp/v1', '/report', [
'methods' => 'POST',
'callback' => function( $request ) {
$body = $request->get_body();
error_log( 'CSP Violation: ' . $body );
return new WP_REST_Response( null, 204 );
},
'permission_callback' => '__return_true',
] );
} );
ステップ5:ヘッダー設定を確認・評価する
# ヘッダーが正しく設定されているか確認
curl -I https://example.com/ 2>/dev/null | \
grep -iE "x-frame|x-content|strict-transport|content-security|referrer|permissions"
# 期待される出力:
# strict-transport-security: max-age=31536000; includeSubDomains
# x-content-type-options: nosniff
# x-frame-options: SAMEORIGIN
# referrer-policy: strict-origin-when-cross-origin
# permissions-policy: camera=(), microphone=(), geolocation=()
# WordPress REST APIでヘッダーを確認
wp eval '
$response = wp_remote_head(home_url("/"));
$headers = wp_remote_retrieve_headers($response);
foreach (["x-frame-options", "x-content-type-options"] as $h) {
echo $h . ": " . ($headers[$h] ?? "NOT SET") . "\n";
}'
注意事項
Strict-Transport-Security(HSTS)を設定すると、一定期間はHTTPへのアクセスが強制的にHTTPSにリダイレクトされます。SSL証明書に問題が生じた場合にアクセス不能になるため、max-ageは最初は短く(例:3600秒)設定して徐々に延ばしてください。- CSPの
'unsafe-inline'と'unsafe-eval'は多くのWordPressプラグインで必要ですが、XSS対策の効果が薄れます。Nonce(ワンタイムトークン)を使った厳格なCSPへの段階的移行を検討してください。 X-XSS-Protectionは現代のブラウザでは非推奨ですが、古いIEのために残しておくと良いでしょう。
まとめ
セキュリティヘッダーは「現状確認→Nginxヘッダー設定→functions.phpで追加→CSPをReport-Onlyで試験→本番適用」の流れで実装します。securityheaders.comでA評価を目指しましょう。関連記事:WordPressのXMLRPCを無効化する方法、WordPressのログイン試行回数を制限する方法。