
「〇〇さんのサイト、なんか変な広告が出ますよ」
ある日の午後、懇意にしているクライアントから、一本の電話がかかってきた。彼の声は、明らかに困惑していた。
「変な広告、ですか?僕のほうでは特に何も…」
そう言いながら、僕は彼の会社のホームページを開いた。一見、いつもと変わらない。しかし、数秒後、画面の右下から、いかにも怪しげな「最新iPhoneが1円!」というポップアップ広告が、ぬるっと表示されたのだ。
「うわ、本当だ…なんだこれ…」

心臓が、ドクンと嫌な音を立てた。これは、ただの広告じゃない。サイトが、何者かによって改ざんされている。直感的に、僕は悟った。これは、クロスサイトスクリプティング(XSS)攻撃だ、と。
幸い、すぐに原因を特定して対処できたから、顧客情報の流出といった最悪の事態は免れた。でも、もし発見が遅れていたら…?サイトの信頼は失墜し、ビジネスに深刻なダメージを与えていたかもしれない。あの時の、背筋が凍るような感覚は、今でも鮮明に覚えている。
こんにちは!XSS攻撃の本当の怖さを、身をもって体験したWeb開発者の僕です。
今日は、多くのWordPressサイトが見過ごしがちな、しかし非常に危険な脆弱性である「XSS攻撃」と、それを防ぐための強力な武器、「コンテンツセキュリティポリシー(CSP)」について、僕の失敗談を交えながら、どこよりも分かりやすく解説していくよ。
「セキュリティ対策?WAFとウイルススキャンやってるから大丈夫」なんて思っているあなた。その考え、もしかしたら、大きな穴が空いているかもしれないぜ。
XSS攻撃って何? なんでそんなにヤバいの?
まず、敵を知ることから始めよう。XSS(クロスサイトスクリプティング)攻撃とは、攻撃者が、脆弱性のあるWebサイトの入力フォーム(コメント欄や検索窓など)に、悪意のあるスクリプト(JavaScriptなど)を埋め込み、そのサイトを訪れた他のユーザーのブラウザ上で、そのスクリプトを実行させてしまう攻撃のことだ。
例えるなら、お店の伝言板に、一見普通のメッセージに見せかけた「見た人全員の財布からお金を盗む」という呪いのメモを貼り付けるようなものだ。伝言板を管理しているお店(Webサイト)は、それが悪意のあるものだと気づかずに、他の来店客(サイト訪問者)に見せてしまう。そして、メモを見てしまった人は、知らず知らずのうちに被害に遭ってしまうんだ。
具体的に、どんな被害があるのか?

- 個人情報の窃取: ユーザーのCookie情報を盗み出し、そのユーザーになりすましてログインする(セッションハイジャック)。
- サイトの改ざん: 偽の入力フォームを表示して、クレジットカード情報やパスワードを盗み出す(フィッシング)。
- マルウェアの拡散: サイトを訪れたユーザーを、ウイルスに感染した別のサイトに強制的にリダイレクトさせる。
ね?笑えないでしょ?サイト運営者としては、ユーザーを危険に晒してしまったという責任問題にもなるし、サイトの信頼もガタ落ちだ。マジで、悪夢だよ。
CSP(コンテンツセキュリティポリシー)とは? XSS攻撃の新しい守護神
じゃあ、どうやってこの厄介なXSS攻撃からサイトを守ればいいのか。そこで登場するのが、今日の主役、CSP(コンテンツセキュリティポリシー)だ。
CSPは、サーバーがブラウザに対して、「このサイトでは、ここから読み込むスクリプトや画像は信頼できるけど、それ以外は全部ブロックしてね!」というルールを伝えるための仕組み(HTTPレスポンスヘッダー)だ。
さっきの伝言板の例で言うなら、お店が「うちの伝言板に貼っていいのは、常連の〇〇さんが書いたメモだけです。それ以外の人が書いたメモは、たとえ貼ってあっても、お客さんは絶対に見ないでください!」と、あらかじめルールを宣言しておくようなものだ。
こうすることで、たとえ攻撃者が悪意のあるスクリプトをサイトに埋め込むことに成功したとしても、ブラウザが「おっと、このスクリプトは許可されてない場所から来たやつだな。実行は中止だ!」と、水際でブロックしてくれるんだ。
つまり、CSPは、万が一、脆弱性を突かれてスクリプトが埋め込まれてしまっても、それが実行されるのを防ぐ「最後の砦」として機能してくれる、超頼もしいセキュリティ機能なんだよ。

CSP導入のメリットと、ちょっと厄介なデメリット
「なんだ、最強じゃん!今すぐ導入しよう!」って思うよね。でも、落ち着いて。CSPは強力な分、導入には少しコツがいる。メリットとデメリットをちゃんと理解しておこう。
メリット
- 強力なXSS対策: これが最大のメリット。インラインスクリプトや、許可されていないドメインからのリソース読み込みをブロックすることで、XSS攻撃のリスクを劇的に減らせる。
- データ漏洩の防止:
frame-ancestorsディレクティブを使えば、クリックジャッキング攻撃(透明なiframeを重ねて、意図しないクリックをさせる攻撃)も防げる。 - 脆弱性の可視化:
report-uriやreport-toディレクティブを使えば、CSPに違反するリソースの読み込みが試みられた時に、それを検知して管理者に通知できる。つまり、自分のサイトのどこに問題があるのかを把握しやすくなるんだ。
デメリット
- 設定が複雑で難しい: これが最大の壁だ。どのリソースを許可して、どれをブロックするか、自分でルールを細かく定義しないといけない。一つでも設定を間違えると、サイトの表示が崩れたり、正常に機能しなくなったりする。
- メンテナンスの手間: 新しいプラグインを追加したり、外部のWebサービス(Google Analyticsとか)を導入したりするたびに、CSPのルールを見直して、許可リストに追加してあげる必要がある。これを忘れると、その機能が動かなくなる。
- 古いブラウザでは対応していない: まあ、今どきほとんどのモダンブラウザは対応してるけど、IEみたいな化石級のブラウザでは機能しない。まあ、これはもう気にしなくていいレベルかな。
WordPressにCSPを導入する3つの方法
デメリットを聞いて、ちょっと尻込みしちゃったかな?大丈夫。これから、WordPressにCSPを導入するための、具体的な3つの方法と、失敗しないための「段階的導入」のコツを教えるからね。

方法1:.htaccessファイルに記述する(Apacheサーバー向け)
多くのレンタルサーバーで使われているApacheというWebサーバーなら、この方法が一番手軽だ。WordPressのルートディレクトリにある.htaccessというファイルに、以下のコードを追記する。
<IfModule mod_headers.c>
Header set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; img-src 'self' data:; style-src 'self' 'unsafe-inline';"
</IfModule>【注意!】このコードはあくまで一例だ。 このままコピペしても、あなたのサイトでは動かない可能性が高い。`default-src
'self'」は「自分自身のドメイン」を意味する。'unsafe-inline'はインラインのスクリプトやスタイルを許可するという意味だけど、これはXSS対策としては不十分だ。まずは、この緩い設定から始めて、少しずつルールを厳しくしていくのがコツなんだ。(詳しくは後述するよ)
方法2:wp-config.phpに記述する
wp-config.phpにPHPのheader()関数を使って記述する方法もある。サーバーの種類(ApacheかNginxか)を問わず使えるのがメリットだ。
@header("Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; img-src 'self' data:; style-src 'self' 'unsafe-inline';");.htaccessと同じで、これもあくまで一例。自分のサイトに合わせて、ルールをカスタマイズする必要があるよ。
方法3:プラグインを使う
「やっぱりコードをいじるのは怖い…」という人には、プラグインを使う方法もある。設定画面から、比較的簡単にCSPルールを管理できるのが魅力だ。
- WP-Content-Security-Policy: シンプルで使いやすい。基本的なディレクティブを設定できる。
- HTTP Headers: CSPだけでなく、他の多くのセキュリティヘッダーも設定できる高機能なプラグイン。
ただし、プラグインは、そのプラグイン自体の脆弱性がリスクになることもあるし、細かい設定ができない場合もある。個人的には、コードで管理する方法をマスターするのが、長期的には一番良いと思ってるよ。
失敗しない!CSP「段階的導入」のススメ
さて、ここからが一番大事な話だ。CSPをいきなり導入すると、サイトが壊れるリスクが高い。だから、プロは必ず「Report-Onlyモード」を使って、段階的に導入を進めていくんだ。

Content-Security-Policy-Report-Onlyというヘッダーを使うと、CSPルールに違反しても、ブラウザはリソースをブロックせずに、違反レポートだけを送信してくれる。つまり、「もし有効だったら、こんな違反がありましたよ」と、予行演習をしてくれるわけだ。
ステップ1:Report-Onlyモードで現状を把握する
まず、非常に緩いポリシーをContent-Security-Policy-Report-Onlyヘッダーで設定する。そして、違反レポートを送信するためのreport-uriも指定する。report-uriの送信先には、report-uri.comのような専門サービスを使うのが便利だよ。
.htaccessの例:
Header set Content-Security-Policy-Report-Only "default-src 'none'; report-uri https://your-company.report-uri.com/r/d/csp/enforce;"default-src 'none'という、一番厳しいルールで設定するのがポイントだ。こうすることで、自分のサイトが読み込んでいるすべてのリソース(CSS, JS, 画像, フォントなど)が、違反レポートとして上がってくる。
ステップ2:レポートを分析し、ポリシーを調整する
数日間、Report-Onlyモードでサイトを運用すると、report-uri.comの管理画面に、山のような違反レポートが届くはずだ。最初はびっくりするかもしれないけど、これが君のサイトの「本当の姿」なんだ。
レポートを一つずつ見ていくと、「あ、Google Analyticsのスクリプトを読み込んでるな」とか、「Google Fontsからフォントを読み込んでるな」とか、自分のサイトが必要としている外部リソースがすべて洗い出せる。
それらを元に、script-srcやstyle-src、font-srcなどのディレクティブに、許可するドメインを一つずつ追加していくんだ。
# 調整後のポリシー(例)
Header set Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self' https://www.google-analytics.com; style-src 'self' https://fonts.googleapis.com; font-src https://fonts.gstatic.com; report-uri https://your-company.report-uri.com/r/d/csp/enforce;"ステップ3:ポリシーを適用(Enforce)する
レポートが出なくなり、サイトの表示や機能に問題がないことを確認できたら、いよいよ本番適用だ。Content-Security-Policy-Report-Onlyを、Content-Security-Policyに変更する。
# 本番適用
Header set Content-Security-Policy "default-src 'self'; script-src 'self' https://www.google-analytics.com; style-src 'self' https://fonts.googleapis.com; font-src https://fonts.gstatic.com;"これで、CSPが有効になり、許可されていないリソースはブロックされるようになる。report-uriは、本番適用後も残しておくと、新たな違反が起きた時に検知できるから便利だよ。
この「Report-Only → 分析・調整 → Enforce」というサイクルを繰り返して、少しずつポリシーを強化していくのが、CSP導入を成功させるための、唯一にして絶対の道筋なんだ。
よくある質問(FAQ)
Q1. unsafe-inlineやunsafe-evalって、使っても大丈夫?
A1. これらは、CSPの保護を弱めてしまうから、使わないのが理想だ。unsafe-inlineはインラインの<script>タグやonclick属性を、unsafe-evalはeval()のような文字列をコードとして実行する関数を許可してしまう。WordPressは、コアや多くのプラグインがこれらに依存しているため、完全に排除するのは難しい。でも、可能な限り、外部ファイル化するなどのリファクタリングを行って、これらの使用を避ける努力をすべきだね。
Q2. nonceやhashを使えば、もっと安全になるって本当?
A2. 本当だよ。nonce(ノンス)は、リクエストごとに生成されるユニークな値を<script>タグに付与し、同じ値をCSPヘッダーでも指定することで、そのスクリプトの実行を許可する仕組みだ。hashは、スクリプトの内容からハッシュ値を計算し、それをCSPヘッダーで指定する方法。これらを使えば、unsafe-inlineを排除しつつ、安全にインラインスクリプトを許可できる。ただ、WordPressで動的に実装するのは、かなり高度な知識が必要になる。
Q3. 全部'self'だけじゃダメなの?
A3. 多くのサイトではダメだろうね。Google Analytics、Google Fonts、各種SNSのウィジェット、広告配信スクリプトなど、現代のWebサイトは、多くの外部サービスに依存している。それらのドメインを、一つずつ丁寧に許可リストに追加していく作業が必要になるんだ。
まとめ:CSPは「育てる」セキュリティ対策
今日の話をまとめよう。

- XSS攻撃は、サイトの信頼を根底から揺るがす危険な攻撃
- CSPは、万が一XSS脆弱性があっても、その実行を防ぐ「最後の砦」
- 設定が複雑というデメリットがあるが、段階的に導入すれば怖くない
- 「Report-Onlyモード」で現状を把握し、レポートを元にポリシーを調整するのが成功の鍵
- CSPは、一度設定して終わりではなく、サイトの変更に合わせて「育てていく」もの
僕がXSS攻撃を受けたあの時、もしCSPを正しく導入していたら、被害は起きなかったかもしれない。そう思うと、今でも悔しいよ。
セキュリティ対策に、「これで完璧」というゴールはない。新しい攻撃手法は次々と生まれてくるし、サイトの構成も日々変わっていく。CSPは、そんな変化に対応しながら、サイトと一緒に育てていくパートナーのような存在だ。
最初は、難しく感じるかもしれない。でも、この記事で紹介した「段階的導入」の方法なら、必ず乗り越えられるはずだ。君の大切なサイトと、そのサイトを訪れるユーザーを守るために、今日から、CSPという新しい守護神を育てる第一歩を踏み出してみないか?
WordPressのセキュリティ、不安に思っていませんか?

「自分のサイトは大丈夫だろうか…」
「何から手をつければいいか分からない…」
もしあなたが少しでもそう感じているなら、専門家によるセキュリティ診断を受けてみることを強くお勧めします。
上記のサイトでは、WordPressのプロがあなたのサイトの脆弱性を無料で診断してくれます。問題が見つかれば、具体的な対策方法についてもアドバイスをもらえます。手遅れになる前に、一度プロの目でチェックしてもらい、安心を手に入れましょう。