結論(CSPでHTTP配信元を許可していない)
CSPでHTTP配信元を許可していないとは、Content Security Policyの配信元リストに平文HTTPの指定が残っていない状態です。http://cdn.example.com のような平文HTTPのオリジンや、http:(HTTPなら何でも)というスキーム指定が該当します。HTTPの配信元を許可すると、通信経路上の第三者が平文のスクリプトや画像を書き換えられ、HTTPSで守っているページに改ざんされたコードが入り込む余地が生まれます。http:// を https:// に書き換えても、HTTPS配信されているリソースの読込は維持されます。
この記事のポイント
- http://ホスト名 はそのホストからのHTTP読込を、http: はHTTPのURLすべてを許可します。
- CSP3では http を指定したソースは https のURLにも一致するため、https:// に書き換えても正しくHTTPS配信されている読込は壊れません。
- ブラウザの混在コンテンツ制御で多くは止まりますが、HTTPで閲覧された場合は何も守られず、ブラウザ依存でもあります。
- upgrade-insecure-requests はHTTPのURLをHTTPSに書き換える仕組みで、配信元リストに http: を残す理由にはなりません。
- セキュリティAIチェッカーは報告先と 'strict-dynamic' 付きscript-srcを除き、HTTP配信元があれば×、なければ○と判定します。
| 診断項目名 | CSPでHTTP配信元を許可していない |
|---|---|
| 項目ID | headers.csp-http |
| 分類 | コンテンツセキュリティポリシー(CSP) |
| 重大度・配点の重み | 重要(high) 重み 3 |
| 関連する標準・ガイドライン | OWASP ASVS 5.0.0 V3.4.3(L2)、OWASP WSTG-CONF-12、W3C CSP Level 3(scheme-part match・upgrade-insecure-requests)、W3C Mixed Content、CWE-319(重要情報の平文送信) |
CSPでHTTP配信元を許可していないとは
CSPでHTTP配信元を許可していないとは、Content Security Policy(CSP)の配信元リストに、http://cdn.example.com のような平文HTTPのオリジンや、http:(HTTPなら何でも)というスキーム指定が残っていない状態のことです。
# 問題あり:画像をHTTPで読み込むことを許可している
Content-Security-Policy: default-src 'self'; img-src 'self' http://www.pref.example.lg.jp
CSPでHTTPの配信元を許可すると、そのリソースを暗号化されていない通信で読み込むことを許可していることになります。通信経路上の第三者(公衆Wi-Fiの運営者や攻撃者)は、平文のスクリプトや画像を書き換えられるため、HTTPSで守っているページに、改ざんされたコードが入り込む余地が生まれます。
セキュリティAIチェッカーのこの項目は、ヘッダーまたはmetaのCSPに、HTTPの配信元の指定が残っていないかを確認します。
「HTTP配信元」とは何か(CSPでの書き方と意味)
書き方ごとの意味
| 書き方 | 意味 |
|---|---|
http://cdn.example.com | 指定ホストからのHTTP読込を許可(CSP3ではHTTPSも一致) |
http: | HTTPのURLすべてを許可(CSP3では https: も一致する) |
https://cdn.example.com | HTTPSのみ(推奨) |
cdn.example.com(スキームなし) | 保護対象ページのスキームに従う。HTTPSページならHTTPSのみ |
W3C CSP3 の scheme-part match では、http を指定したソースは https のURLにも一致します(安全側へのアップグレードを許すため)。逆は成り立ちません。したがって、http:// を https:// に書き換えても、正しくHTTPS配信されているリソースの読込は維持されます。
ブラウザの混在コンテンツ制御との関係
HTTPSページからHTTPのスクリプト・iframe等(能動的コンテンツ)を読み込むことは、W3C Mixed Content 仕様に基づき、ブラウザが既定でブロックします。画像・音声・動画(受動的コンテンツ)は、近年の主要ブラウザでは自動的にHTTPSへのアップグレードを試みます。つまり、CSPで http: を許可していても、HTTPSページではブラウザ側の制御で多くが止まります。
それでも、CSPにHTTP配信元が残っていることには次の問題があります。
- HTTPで閲覧された場合(HTTPS転送やHSTSがない環境、古い端末)には、何も守られません。
- 混在コンテンツの扱いはブラウザの種類・バージョンに依存します。CSPという明示的な宣言で禁止しておくのが確実です。
- 移行前の古い外部サービスへの依存が残っている兆候であり、配信元の棚卸しが不十分であることを示します。
Mozilla HTTP Observatory も、HTTPSサイトのCSPでHTTPからの読込を許可している場合を減点しています(画像・メディアのみで-10、それ以外で-20)。
upgrade-insecure-requests について
CSPの upgrade-insecure-requests を指定すると、ページ内のHTTPのURLへのリクエストを、ブラウザがHTTPSに書き換えて送ります。HTTPで書かれた古いリンクやCMS本文の画像URLを一括で救済できる便利な仕組みですが、書き換え先がHTTPSに対応していなければ読込は失敗します。配信元リストの http: を残す理由にはなりません。
HTML本文の src="http://…" などの混在コンテンツそのものは「Mixed Contentがない」、全オリジンやスクリプトへの https: の許可は「CSPの過剰なワイルドカード」で確認します。
CSPでHTTP配信元を許可していないの診断基準(セキュリティAIチェッカー)
取得対象
- トップページの最終応答の
Content-Security-Policyヘッダー(カンマ区切りの複数ポリシーを個別に分解)と、HTML内のmeta CSPを対象にします。 - ヘッダーとmetaの両方がある場合は、両方の全ポリシーを評価します。
検出条件
各ポリシーを ; でディレクティブに分割し、値を空白区切りのトークン(小文字化)として調べます。いずれかのディレクティブの値に、次のトークンがあれば「HTTP配信元を許可」とします。
http://で始まるソース式(ホストを指定したHTTP配信元)http:と完全に一致するトークン(スキーム全体の許可)
https://、https: は一致しません。次の2つは対象外です。
report-uri・report-toの値(配信元の許可ではなく、報告先の指定のため)'strict-dynamic'を含むscript-src系のディレクティブ(script-src・script-src-elem・script-src-attr)の値(ホスト・スキームの指定がブラウザに無視されるため)
判定条件
| 判定 | 条件 | 得点への影響 |
|---|---|---|
| × 要改善(fail) | ヘッダーまたはmetaのいずれかのポリシーに、対象外を除いて http://… または http: の配信元指定がある | 0点 |
| ○ 問題なし(pass) | HTTP配信元の指定がない | 3点 |
| 対象外(na) | CSPがヘッダーにもmetaにもない | 採点に計上しない |
判定の考え方と限界
- ブラウザの混在コンテンツ制御で実害が抑えられる場合でも、CSPという宣言の段階でHTTPを許可していること自体を問題とし、×とします。
ws:(暗号化なしのWebSocket)はこの項目の対象外です。WebSocketの暗号化は「WebSocketをWSSで暗号化」で評価します。- meta側にだけ
http://が残っている場合も、ヘッダーのCSPと同じ基準で×になります。 - 報告先(
report-uri)がHTTPのURLでも、この項目は×にしません。ただし、違反レポート(閲覧URL等を含む)が平文で送られるため、報告先もHTTPSにしてください。報告先の設定は「CSP違反の報告先」で確認します。 - HTML本文の
src="http://…"などの混在コンテンツは、この項目ではなくHTML検査の項目で扱います。
自治体サイトでの判定例
| CSP | 判定 |
|---|---|
default-src 'self'; img-src 'self' http://www.pref.example.lg.jp | × |
default-src 'self' http: https: | × |
default-src 'self'; script-src 'self' https://www.googletagmanager.com | ○ |
default-src 'self'; upgrade-insecure-requests | ○ |
default-src 'self'; report-uri http://report.example.jp/csp | ○(報告先は対象外。HTTPSへの変更は推奨) |
script-src 'nonce-abc' 'strict-dynamic' http: https: | ○(strict-dynamicで無視される指定) |
ヘッダー default-src 'self' + meta img-src http://www.pref.example.lg.jp | ×(metaのポリシーも評価) |
CSPでHTTP配信元を許可しているとどんなリスクがあるか
- 通信経路での改ざん:公衆Wi-Fiなどで、平文で読み込まれたJavaScriptを攻撃者が書き換えると、ページ上で任意のコードが実行されます。入力フォームの内容の窃取や偽画面の表示につながります。
- 盗聴:HTTPで読み込むリソースのリクエストは、URLそのものに加え、Secure属性のないCookieや、条件によっては参照元の情報(Referer。ページ自体がHTTPの場合や、Referrer-Policyで送信を許可している場合)も平文で運ぶため、閲覧行動が第三者に知られます。
- HTTPで閲覧される経路:HSTSが未設定の環境では、最初のHTTPアクセスを攻撃者が中継(SSLストリップ)し、ページ全体をHTTPで見せることができます。この場合はページそのもの(CSPヘッダーを含む)が書き換えられうるため、CSPだけでは防げません。HTTPの配信元を許可するCSPは、HTTPでの閲覧を前提にした古い構成が残っている兆候でもあるため、HTTPS化・HSTSと併せて見直します。
- 防御の形骸化:サイト本体をHTTPS化・HSTS化していても、CSPがHTTPの読込を許していると、「安全な配信元だけ」という宣言の意味が弱まります。
CSPのHTTP配信元をHTTPSへ直す方法(Apache・nginx・IIS・Next.js)
修正の手順
- CSPに含まれる
http://のオリジンとhttp:を一覧にします。 - 各配信元がHTTPSに対応しているかを確認します(
curl -sI https://配信元/パス)。 - 対応していれば
https://に書き換えます。対応していなければ、ファイルを自組織のサーバーへ移す、HTTPS対応の代替サービスへ切り替えるなどで依存をなくします。 - HTML本文側の
http://で始まるsrc・hrefもHTTPSへ書き換えます。移行期間中はupgrade-insecure-requestsを併用できます。 report-uriの報告先もHTTPSにします(この項目の判定対象ではありませんが、レポートの平文送信を避けるためです)。
Apache(.htaccess)
<IfModule mod_headers.c>
# 変更前: img-src 'self' http://www.pref.example.lg.jp
Header always set Content-Security-Policy "default-src 'self'; img-src 'self' data: https://www.pref.example.lg.jp; object-src 'none'; base-uri 'self'; frame-ancestors 'self'; upgrade-insecure-requests"
</IfModule>
nginx
add_header Content-Security-Policy "default-src 'self'; img-src 'self' data: https://www.pref.example.lg.jp; object-src 'none'; base-uri 'self'; frame-ancestors 'self'; upgrade-insecure-requests" always;
IIS
<add name="Content-Security-Policy" value="default-src 'self'; img-src 'self' data: https://www.pref.example.lg.jp; object-src 'none'; base-uri 'self'; frame-ancestors 'self'; upgrade-insecure-requests" />
Next.js(Vercel)
next.config.js の headers() またはproxyで設定するCSPの文字列から http:// を除き、公式ガイドの例のように upgrade-insecure-requests を付けます。Vercelは既定でHTTPS配信のため、HTTPの配信元を許可する必要は通常ありません。
CMSを利用している場合
CMSの記事本文に、過去に貼り付けた http:// の画像・リンクが大量に残っていることがあります。データベースの一括置換はバックアップを取ってから行い、置換後に表示確認をします。WordPressでは、WP-CLIの search-replace(--dry-run で事前確認)が使えます。
外部サービスごとの確認ポイント
| よくある配信元 | 確認・対応 |
|---|---|
| 県・関係団体の旧サーバーの画像やバナー | HTTPS対応済みか確認し、URLを https:// に変更。未対応ならバナー画像を自サーバーへ複製 |
| 古いアクセスカウンター・天気予報ウィジェット | HTTPS版の提供有無を確認。なければ撤去を検討 |
| 動画・地図の埋め込み | 主要サービスはHTTPS版の埋め込みコードを提供しているため、コードを貼り直す |
| 違反レポートの受信先 | HTTPSの受信URLへ変更 |
注意点
upgrade-insecure-requestsは、HTTPSに対応していない外部配信元の画像やスクリプトを「読み込めなくする」方向に働きます。導入前にHTTPS対応状況を確認してください。- 混在コンテンツは、ブラウザの開発者ツールのコンソール(「Mixed Content」の警告)でも確認できます。
設定後の確認方法
curl -sI https://www.example.lg.jp/ | grep -i '^content-security-policy' | grep -oiE "(^|[ ;,])http:(//[^ ;,]*)?"
何も表示されなければ、HTTP配信元の指定はありません。report-uri の値や、'strict-dynamic' 付きの script-src 内の http: も表示されますが、これらはこの項目の判定対象外です。meta CSPはHTMLソースで別途確認します。
よくある質問(FAQ)
ブラウザが混在コンテンツをブロックするなら、CSPの http: は問題ないのでは?
HTTPSページでは多くがブラウザ側で止まりますが、HTTPで閲覧された場合(HTTPS転送やHSTSがない環境、古い端末)は何も守られません。混在コンテンツの扱いはブラウザの種類・バージョンに依存するため、CSPで明示的に禁止しておくのが確実です。
http:// を https:// に書き換えると読み込めなくなりませんか?
配信元がHTTPSに対応していれば読み込めます。CSP3のscheme-part matchでは http を指定したソースが https のURLにも一致する一方、逆は成り立たないため、https:// に書き換えても正しくHTTPS配信されているリソースの読込は維持されます。
upgrade-insecure-requests を付ければ http: を許可したままでよいですか?
よくありません。upgrade-insecure-requests はページ内のHTTPのURLをHTTPSに書き換えて送る仕組みで、古いリンクや画像URLの救済に便利ですが、配信元リストの http: を残す理由にはなりません。書き換え先がHTTPSに対応していなければ読込は失敗します。
report-uri の報告先が http:// でも×になりますか?
この項目では×にしません。報告先は配信元の許可ではないためです。ただし違反レポートには閲覧URL等が含まれ平文で送られるため、報告先もHTTPSにしてください。
ws: (暗号化なしのWebSocket)は、CSPでHTTP配信元を許可していないかの項目で検出されますか?
検出しません。WebSocketの暗号化は「WebSocketをWSSで暗号化」(html.insecure-websocket)で評価します。
HTTPSに対応していない外部サービスを使っている場合はどうすればよいですか?
ファイルを自組織のサーバーへ移す、HTTPS対応の代替サービスへ切り替えるなどで依存をなくします。古いアクセスカウンターや天気予報ウィジェットのようにHTTPS版がないものは、撤去も検討します。
この項目を含む127項目を、URLを入れるだけで無料診断します。