Content Security PolicyでXSS攻撃を軽減する

:bookmark: このガイドでは、Discourse におけるクロスサイトスクリプティング(XSS)攻撃を緩和するために、コンテンツセキュリティポリシー(CSP)を使用する方法について説明します。CSP の基礎、設定、およびベストプラクティスをカバーしています。

:person_raising_hand: 必要なユーザーレベル:管理者

まとめ

コンテンツセキュリティポリシー(CSP)は、クロスサイトスクリプティング(XSS)やその他のインジェクション攻撃から保護するための、Discourse における重要なセキュリティ機能です。このガイドでは、CSP の基礎、Discourse での実装方法、およびサイトでの設定方法について解説します。

コンテンツセキュリティポリシーとは?

コンテンツセキュリティポリシーは、クロスサイトスクリプティング(XSS)やデータインジェクション攻撃など、特定の種類の攻撃を検出および緩和するための追加のセキュリティ層です。CSP は、信頼できるコンテンツソースを指定し、ブラウザに対してそれらの信頼できるソースからのリソースのみを実行またはレンダリングするように指示することで機能します。

XSS は依然として最も一般的な Web の脆弱性の一つです。CSP を実装することで、Discourse は信頼できるソースからのスクリプトのみをロードおよび実行することを許可し、XSS 攻撃のリスクを大幅に低減します。

Discourse の CSP 実装

Discourse バージョン 3.3.0.beta1 以降、Discourse は「strict-dynamic」CSP を実装しています。このアプローチでは、script-src ディレクティブに単一の nonce- 値と strict-dynamic キーワードを使用します。コアおよびテーマ内のすべての初期の <script> タグには、自動的に適切な nonce= 属性が割り当てられます。

デフォルトのポリシーには、以下のディレクティブが含まれています。

  • script-src:JavaScript の有効なソースを指定
  • worker-src:ServiceWorker スクリプトの有効なソースを指定
  • object-src:プラグイン(Flash、Java など)の実行をブロック
  • base-uri<base> 要素の URL を制限
  • manifest-src:Web アプリマニフェストの URL を制限
  • frame-ancestors:どのサイトが iframe 内に Discourse インスタンスを埋め込むことができるかを制御
  • upgrade-insecure-requests:HTTP リクエストを自動的に HTTPS にアップグレード(force_https が有効な場合に含まれる)

Discourse での CSP の設定

利用可能な設定

  • content_security_policy:CSP の有効化または無効化(デフォルト:オン)
  • content_security_policy_report_only:CSP レポートオンリーモードの有効化(デフォルト:オフ)
  • content_security_policy_script_src:デフォルトの script-src ディレクティブ を拡張可能
  • content_security_policy_frame_ancestorsframe_ancestors ディレクティブ を有効化(デフォルト:オン)

CSP の有効化方法

  1. 管理パネルに移動
  2. セキュリティ設定へ移動
  3. content_security_policy 設定を見つけ、有効になっていることを確認

CSP を完全に有効にする前に、潜在的な問題を確認するために、CSP レポートオンリーモードから開始することをお勧めします。

  1. content_security_policy_report_only 設定を有効化
  2. ブラウザのコンソールで CSP 違反を監視
  3. 必要に応じて CSP を拡張し、正当な違反に対処
  4. 誤検知がないことを確信したら、レポートオンリーモードを無効化し、CSP を完全に有効化

デフォルトの CSP の拡張

追加のスクリプトソースを許可する必要がある場合は、content_security_policy_script_src 設定を使用して script-src ディレクティブを拡張できます。以下を追加できます。

  • ハッシュソース
  • 'wasm-unsafe-eval'
  • 'unsafe-eval'(注意して使用してください)

例:

'sha256-QFlnYO2Ll+rgFRKkUmtyRublBc7KFNsbzF7BzoCqjgA=' 'unsafe-eval'

:warning: 'unsafe-eval' や他の寛容なディレクティブを追加する際は注意してください。これらは CSP の効果を低下させる可能性があります。

CSP とサードパーティとの統合

Google タグマネージャー、Google アナリティクス、広告サービスなどのサードパーティサービスを使用する場合は、CSP 設定を調整する必要がある場合があります。Discourse バージョン 3.3.0.beta1 以降のほとんどの場合、‘strict-dynamic’ CSP の実装により、追加の設定なしで外部スクリプトが動作します。

問題が発生した場合は、以下を行う必要がある場合があります。

  1. ブラウザのコンソールを監視して、必要なスクリプトソースを特定
  2. 必要なソースを content_security_policy_script_src 設定に追加
  3. 外部リソースをロードする広告サービスなどの複雑な統合の場合、ドメイン間レンダリングを有効にする必要があるかもしれません(これを行う discourse-adplugin の例 PR を参照)。

ベストプラクティス

  1. 潜在的な問題を確認するために、CSP レポートオンリーモードから開始
  2. 正当な違反を解決するにつれて、CSP を徐々に強化
  3. CSP 設定を定期的にレビューし、必要に応じて調整
  4. 'unsafe-eval''wasm-unsafe-eval' のような寛容なディレクティブを追加する際は注意
  5. 最新の CSP の改善を活用するために、Discourse インスタンスを最新の状態に保つ

よくある質問

Q: CSP 違反レポートが多数表示されています。心配すべきですか?
A: 多くの CSP 違反は誤検知であり、ブラウザ拡張機能や他の無関係なスクリプトが原因であることが多いです。サイトの機能に関連する違反に対処することに集中してください。

Q: Google AdSense や他の広告ネットワークと CSP を併用できますか?
A: はい、ただしより寛容な CSP 設定を使用する必要がある場合があります。レポートオンリーモードから開始し、報告された違反に基づいて設定を調整してください。

Q: CSP の問題をトラブルシューティングするにはどうすればよいですか?
A: ブラウザの開発者ツールを使用して、CSP 違反メッセージをコンソールで監視してください。これにより、どのリソースがブロックされているか、その理由を特定できます。

追加リソース

「いいね!」 56
Adsense Not Working after Recent Discourse Update
Discourse 2.2.0.beta6 Release Notes
Adding statcounter code
How to restart Discourse after server reboot?
How to install npm packages in custom themes/plugins
Interactive SVG using <object>?
Video Upload to YouTube and Vimeo using Theme Component
Embed HTML5 player for MP3 file
2.5.0.beta5 breaks retort plugin
Should I load third-party libraries from vendor or cdn?
Word Cloud plugin
Embed widget within text in a topic
Discourse Intercom (Advanced)
"Unsafe JavaScript attempt to initiate navigation"
Google Tag Manager and Discourse CSP (Content Security Policy)
Cookie Consent, GDPR, and Discourse
A strange question about google ad display in my site
How to pass a component setting as a value to an attribute?
Need help integrating code wrote on Edittext to the Discourse
Issue with Activate Account Page After Update to 3.4.0 (Blank Page)
Any approved method for adding Javascript before body close?
(Superseded) Experimenting with a 'strict-dynamic' Content Security Policy (CSP)
Can't get script tag to work in landing pages plugin due to content-security-policy
How to embed Razorpay subscription button with CSP restrictions
Push custom events to Google Tag Manager and Analytics
Can I add a snippet to the header?
JS script is not loading
How do we fire scripts after topic HTML is rendered in DOM?
Iframe issue without URL
Where to place ad script?
We couldn't find the code on your site
Javascript not working in customised areas
Difficulties in correctly adding external JavaScript
Report Only CSP Violations
Nginx config in Discourse Docker?
EPN Smart Links
Discourse 2.2.0.beta9 Release Notes
"Refused to load the script" when adding adsense
Why Cookie Consent Doesn't Show Up?
[DigitalOcean] hostname having "www" in A records showing blank page
[DigitalOcean] hostname having "www" in A records showing blank page
Communities with embedded Twitter Feeds
How to add analytics and pixel scripts avoiding Content Security Policy (XSS)
When install html script facing issue?
Discourse 2.4.0.beta10 Release Notes
Add CSP sources to the plugin
IP does not redirect to domain, domain shows white page
DISCOURSE_CDN_URL causes content security policy violations?
Header content is missing due to CSP
How to insert something right after <head>?
How can I embed tracking JS into Discourse
How do I integrate ? cookiebot.com in meinen Forum?
Adding Cookie Consent Banner
Confused about remotely loaded javascript content
User input validation
Custom JS script in theme component not loading