Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
9
Help us understand the problem. What is going on with this article?
@clustfe

CSPのreport-uriを試してみたよ

More than 3 years have passed since last update.

まえがき

業務でCSPを設定してるサイトに広告を入れることになりまして。
CSPの設定自体がはじめてだったのでどうしていいのか分からず、結局人海戦術で対応しました。。。

で、その後でreport-uriを知ったので、備忘として残します。

なお、そのサイトではまだ使っておらず、ローカルで試しただけです。。
ダメだったらゴメンね(´・ω・`)
ヤ、でも自分のPCでは動いたんだ(;´Д`)

あと、業務に関わるパラメータはテキトーに一括置換で書き換えてます。
たぶん大枠問題ないと思うんですが、なんか変になってても許してください(;´Д`)

2018/02/19 追記
わたくし、嘘をついておりました・・・・(´・ω・`)
いや、元々記述していた内容でも動くんですが、そんなまだるっこしいことしなくて良かったので、
記事の内容を直しておきます。

通常の設定

CSPを有効にするには、要はレスポンスヘッダーに入ればいいので、
Nginxの設定で入れてもよいし、プログラム側でヘッダーに出力してもよいです。

今回は、Nginxに add_header で入れてます。

add_header Content-Security-Policy "default-src 'self' 'unsafe-inline' 'unsafe-eval' local.izunak.com;"

・・・・ホントはscript_srcとかimage-srcとかも入れてるんですが、あまりにも長いのでdefault-srcのみ書いときます。

report-uriによる報告機能

問題のreport-uri、設定は以下のようになります。

add_header Content-Security-Policy "default-src 'self' 'unsafe-inline' 'unsafe-eval' local.izunak.com; report-uri https://local.izunak.com/csp/report;"

report-uriに報告先へのURLを設定します。

報告の内容は、以下のようなJSONが、report-uriに設定したURLへPOSTにより送られます。

report-uriの報告内容例
{
    "csp-report": {
        "blocked-uri": "ブロックしたURL",
        "column-number": 25,
        "disposition": "report",
        "document-uri": "https://local.izunak.com/",
        "effective-directive": "default-src",
        "line-number": 67042,
        "original-policy": "default-src 'self' 'unsafe-inline' 'unsafe-eval' local.izunak.com; report-uri https://local.izunak.com/csp/report;",
        "referrer": "",
        "script-sample": "",
        "source-file": "https://local.izunak.com/bundle-pc.js",
        "status-code": 0,
        "violated-directive": "default-src"
    }
}

具体的な例

自分のローカル環境上で試した設定と、報告内容を記載します。

nginx.conf

http {

    #・・・(略)・・・

    log_format  postdata '[$time_local] request_body: [$request_body]';

    #・・・(略)・・・

}

ログの出力フォーマットを定義してます。
ゴチャゴチャ書いてあっても見づらいので、時間とPOSTパラメータだけ出力させています。

default.conf

server {
    listen 443 default ssl;
    ssl on;
    server_name local.izunak.com;

    #・・・(略)・・・

    # CSP
    # ちょっとだけ記述しやすいように変数化
    set $default_src "default-src 'self' 'unsafe-inline' 'unsafe-eval' local.izunak.com;";
    set $report_uri "report-uri https://local.izunak.com/csp/report;";

    add_header Content-Security-Policy $default_src$report_uri;

    # 報告を出力
    location /csp/report {
      access_log /var/log/nginx/postdata.log  postdata;
      fastcgi_pass unix:/run/php/php-fpm.sock;
    }

    #・・・(略)・・・
}

CSPの設定、1行で書くのがイヤになったので各変数つくって最後にくっつけてます。。
だって見づらいんだもん(´・ω・`)

report-uriの報告先として自身の/csp/reportを指定し、locationで用意した受取先で直接ログ出力をしています。

ここでfastcgi_passを設定しているのは、location内でPOSTパラメータを受け取れるようにするためです。
入れないとPOSTが空なので、なんの役にも立たないログファイルが出来上がるので気をつけて。

参考: Nginx で POST データのログをフィルタする

報告内容

ログに出力された報告内容は↓のように出力されます。

/var/log/nginx/postdata.log
[08/Feb/2018:22:17:16 +0900] request_body: [{\x22csp-report\x22:{\x22blocked-uri\x22:\x22ブロックしたURL\x22,\x22column-number\x22:25,\x22disposition\x22:\x22report\x22,\x22document-uri\x22:\x22https://local.izunak.com/\x22,\x22effective-directive\x22:\x22default-src\x22,\x22line-number\x22:67042,\x22original-policy\x22:\x22default-src 'self' 'unsafe-inline' 'unsafe-eval' local.izunak.com; report-uri https://local.izunak.com/csp/report;\x22,\x22referrer\x22:\x22\x22,\x22script-sample\x22:\x22\x22,\x22source-file\x22:\x22https://local.izunak.com/bundle-pc.js\x22,\x22status-code\x22:0,\x22violated-directive\x22:\x22default-src\x22}}]

ダブルクォーテーションが\x22になってるけど・・・・だいたいOK。

JSONを使いやすくするプラグインがあるのは知ってるけど、
これにしか使わないならわざわざ入れる必要もないかな、と・・・・。

今回はCSPにはじかれたURLさえ分かればいいのでやりませんでしたが、
report-uriの受取先としてプログラムを用意して処理することももちろん可能です。
プログラム側でCSPをヘッダー出力しているなら、
受け取った後にプログラムでワッショイワッショイした方が手間が省けるんですかねたぶん。

Content-Security-Policy-Report-Only

report-uriでNGだったURLを報告してもらえる・・・・とはいえ。
許可していないばっかりに広告が表示されないと収入が減って困る、という場合、
Content-Security-Policy-Report-Onlyを使用するとよいかも?

add_header Content-Security-Policy-Report-Only "default-src 'self' 'unsafe-inline' 'unsafe-eval' local.izunak.com; report-uri https://local.izunak.com/csp/report;"

Content-Security-Policy-Report-Onlyで設定した場合、
このパラメータ上で設定されたルールに該当しないリクエストが来た場合、リクエストのブロックはされず、report-uriに設定されたURLへ報告するだけとなります

Content-Security-Policyとの併用も可能です。

server {
    listen 443 default ssl;
    ssl on;
    server_name local.izunak.com;

    #・・・(略)・・・

    # CSP
    # ちょっとだけ記述しやすいように変数化
    set $default_src "default-src 'self' 'unsafe-inline' 'unsafe-eval' local.izunak.com;";
    set $report_uri "report-uri https://local.izunak.com/csp/report;";

    add_header Content-Security-Policy $default_src;
    add_header Content-Security-Policy-Report-Only $default_src$report_uri;

    # 報告を出力
    location /csp/report {
      access_log /var/log/nginx/postdata.log  postdata;
      fastcgi_pass unix:/run/php/php-fpm.sock;
    }

    #・・・(略)・・・
}

あとがき

まえがきに書いたとおり、まだ業務で設定した内容ではないので、
不正確だったり不備があるかもしれません。。
不備ありました・・・・orz
ごめんなさい・・・・記事にする前にローカルで動くことは確認していたんですが・・・・

修正したのは、Content-Security-Policy-Report-Onlyでしかreport-uriが使えないような記述をしていた個所です。

Content-Security-Policyへの追加も試していたんですが、
おそらく単純に書き方が悪かったせいで正常動作せず、
Content-Security-Policy-Report-Onlyを試した際にたまたまその不備が解消されていたんではないかと。。

余談

ぜんぜんCSPとも関係ないんですが、コレ書いてるときに気になったので、、、

すぐ消すようなローカル環境をチャラっと作る際、だいたいドメインを***.izunak.comにしてるんですが、これって一般的なものなんですかね・・・・?
何度か気になってググってみるも答えが見つからず・・・・orz

はじめてVirtualPCをつかうプロジェクトをやったとき、先輩からすでに用意されたのをもらったんですが、そのときに設定されてたのが***.izunak.comだったんで、なんとなく自分の中でコレが標準になってます。

9
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
clustfe
最近はフリーランスでやらしてもらっています 仕事としてはPHPが99%・・・・のわりに技術は浅いです(´・ω・`) あと、PS2「ボクと魔王」が好きです

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
9
Help us understand the problem. What is going on with this article?