1週間程度、Content Security Policy (CSP)
の
ログを
ログの 整形 取り 込みまで
- ログの
形式 以下のような 形式で 出力されています。
django-csp-reports という、 plugin で、 レポートの ログ出力を 行なってます。
Django製のMezzanine で 構築された ブログに 対して http-observatory-cli で 脆弱性を 検証してみる | Monotalk
で、インストールを 行なっていますが、 そちらの ログフォーマットで 設定すると 以下のようになります。
WARNING 2017-04-17 02:40:06,206 utils 17040 140383643092736 Content Security Policy violation: { "csp-report": { "blocked-uri": "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js", "disposition": "report", "document-uri": "https://www.monotalk.xyz/", "effective-directive": "script-src", "original-policy": "default-src 'self'; report-uri /report/", "referrer": "", "status-code": 0, "violated-directive": "script-src" } }
ログ出力されたjson を、
MongoDBに 取り込める 形に 成形
直接取り込んで おけばですが、 ワンライナーで 取り込める 形式に 変換が できたので、 よしと して おきます。 cat your_app.log | sed -e "s/^WARNING.*/{/g" | sed ':loop; N; $!b loop; s/\n//g' | sed 's/}{ "csp-report": /\ /g' | sed 's/{ "csp-report": //g' | sed 's/ }}/ }/g' > seikei.json
MongoDB に、
db csp_analyze
を作成して、 reports
という collection名で、 データを インポートする
上記で作成した jsonファイルを、 取り込みます。 mongoimport --db csp_analyze --collection reports --type json --file seikei.json
reportと して、 どんな 情報が 出ているかわからないので、 調べる。
report と
どんな
全データの
保持する キーを 重複を 排除して 出力する 上記スクリプトのvar keyArray = new Array(); db.reports.find().forEach(function(elem){for(key in elem) keyArray.push(key); }); var distinctKeyArray = keyArray.filter(function (x, i, self) { return self.indexOf(x) === i; }); for(key in distinctKeyArray) print(distinctKeyArray[key]);
実行で、 コンソールに 以下の キー値が 出力されました。
_id は、MongoDB の キー値ですね。 キーの_id blocked-uri column-number disposition document-uri effective-directive line-number original-policy referrer source-file status-code violated-directive
一覧が 得られましたので、
各キーの設定値に ついて 確認します。 各項目の
説明
項目名 | 説明 | 値の例 |
---|---|---|
blocked-uri | Content Security Policy により読み込みがブロックされたリソースの URI | https://doc-00-0c-docs.googleusercontent.com 等 |
column-number | エラーレポートが報告されたコンテンツの対象の列を表示(していると思います) | 27224 等 |
disposition | “enforce” か “reporting” が設定される。 reportしているので、”reporting”のみ | enforce or reporting |
document-uri | 違反が生じたドキュメントの URI。アクセスのあったぺージのURLが設定されます。 | https://www.monotalk.xyz/blog/archive/2017/4/ 等 |
effective-directive | 違反 を検知したポリシー設定 | script-src 等 |
line-number | 違反が検知されたソース上の行数 | 4985 等 |
original-policy | サイトに適用しているCSPヘッダの内容 | default-src ‘self’; report-uri /report/ 等 |
referrer | referrerの内容 | https://www.google.co.in/ 等 |
source-file | ポリシー違反したリソース名 | https://pagead2.googlesyndication.com/pagead/js/r20170417/r20170110/rum.js 等 |
status-code | 元のリソースのHTTPステータスコードを表す非負整数値 | 200, 0 等 |
violated-directive | 違反があったポリシーセクションの名前 | img-src 等 |
- 各項目の
サンプル値取得に 使用した distinct クエリ // blocked-uri db.reports.distinct("blocked-uri").forEach(function(elem) { print(elem); }); // column-number db.reports.distinct("column-number").forEach(function(elem) { print(elem); }); // disposition db.reports.distinct("disposition").forEach(function(elem) { print(elem); }); // line-number db.reports.distinct("line-number").forEach(function(elem) { print(elem); }); // original-policy db.reports.distinct("original-policy").forEach(function(elem) { print(elem); }); // referrer db.reports.distinct("referrer").forEach(function(elem) { print(elem); }); // source-file db.reports.distinct("source-file").forEach(function(elem) { print(elem); }); // status-code db.reports.distinct("status-code").forEach(function(elem) { print(elem); }); db.reports.distinct("violated-directive").forEach(function(elem) { print(elem); });
どんな 情報が 出力されるのかは わかったので、 集計する
現在の ポリシー定義
実際の
Content-Security-Policy-Report-Only
で
Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self' pagead2.googlesyndication.com www.google-analytics.com monotalkxyz.disqus.com; report-uri /report/
script-src の 定義を してみる
script-src の
source-file
が自ドメインで、 violated-directive
がscript-src
のデータを 集計
var count = 0; // Query db.reports.aggregate([{ $match: { "violated-directive": "script-src", "source-file" : { $regex: /https:\/\/www.monotalk.xyz/ } } }, { $group: { "_id": { "source-file": "$source-file", "blocked-uri": "$blocked-uri" }, "count": { "$sum": 1 } } }, { $sort: { "count": -1 } } ]).forEach(function(element){ if(count == 0) { print("|" + "count" + "|" + "source-file" + "|" + "blocked-uri" + "|"); print("|:-------------------|:--------------------|:--------------|"); } count++; print("|" + element.count + "|" + element._id["source-file"] + "|" + element._id["blocked-uri"] + "|"); });
blog の
"blocked-uri" : "eval"
の放置します。
source-file
がjs
ファイルで、violated-directive
がscript-src
のデータを 集計
結果セットをMarkdown
の
var count = 0; // Query db.reports.aggregate([{ $match: { "violated-directive": "script-src", "source-file" : { $regex: /.js$/ } } }, { $group: { "_id": { "source-file": "$source-file", "blocked-uri": "$blocked-uri" }, "count": { "$sum": 1 } } }, { $sort: { "count": -1 } } ]).forEach(function(element){ if(count == 0) { print("|" + "count" + "|" + "source-file" + "|" + "blocked-uri" + "|"); print("|:-------------------|:--------------------|:--------------|"); } count++; print("|" + element.count + "|" + element._id["source-file"] + "|" + element._id["blocked-uri"] + "|"); });
- 結果
img-src の 定義を してみる
source-file
が自ドメインで、 violated-directive
がimg-src
のデータを 集計 var count = 0; // Query db.reports.aggregate([{ $match: { "violated-directive": "img-src", "source-file" : { $regex: /https:\/\/www.monotalk.xyz/ } } }, { $group: { "_id": { "source-file": "$source-file", "blocked-uri": "$blocked-uri" }, "count": { "$sum": 1 } } }, { $sort: { "count": -1 } } ]).forEach(function(element){ if(count == 0) { print("|" + "count" + "|" + "source-file" + "|" + "blocked-uri" + "|"); print("|:-------------------|:--------------------|:--------------|"); } count++; print("|" + element.count + "|" + element._id["source-file"] + "|" + element._id["blocked-uri"] + "|"); });
結果
violated-directive
がscript-src
のデータの blocked-uri
を集計
var count = 0; // Query db.reports.aggregate([ { $match: { "violated-directive": "img-src" } }, { $group: { "_id": { "blocked-uri": "$blocked-uri" }, "count": { "$sum": 1 } } }, { $sort: { "count": -1 } } ]).forEach(function(element){ if(count == 0) { print("|" + "count" + "|" + "blocked-uri" + "|"); print("|:-------------------|:--------------|"); } count++; print("|" + element.count + "|" + element._id["blocked-uri"] + "|"); });
- 結果
一旦集計を やめて、 ポリシー定義
CSP の
やめて、
上記の
google の
alaytics や、 adsense、 google drive の コンテンツへの リンクを 貼り付けているが、
結構知らないドメイン(google所有)に リンクされている。 monotalkxyz.disqus.com
に対して、 c.disquscdn.com
(CDNサーバ) 等、ソーシャルサービスが 使っている、
CDNドメインがあって、 その あたりの 警告が 出力されている。 goole の
alaytics や、 adsense、 などは、 結構 inline スクリプトが 記載されている。
これを
Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self' *.disqus.com pagead2.googlesyndication.com www.google-analytics.com; img-src 'self' *.disqus.com *.disquscdn.com *.googleusercontent.com *.google.com googledrive.com report-uri /report/
完全に
だいぶ先は
未だに
以上です。
コメント