CSPとは
Content Security Policy
ブラウザ側で実装されたセキュリティ機構
詳しい話とかはこちらを参照
https://developer.mozilla.org/ja/docs/Web/Security/CSP
どんな効果があるか
- クロスサイトスクリプティングの軽減
- パケット盗聴攻撃の軽減
具体的に何がされるか
インラインCSSやインラインJavascriptを書いた時にサイト自体見れないようにブロックする
XSSの典型的な攻撃方法として以下のような攻撃をされても弾ける
<form>
<input type="hidden" name="message" value="#{params['message']}"/>
</form>
このmessageにこんな内容を仕込まれたとする
"><script>alert('hogehoge');</script><input type="hidden" name="hoge" value="
展開する
<form>
<input type="hidden" name="message" value=""><script>alert('hogehoge');</script><input type="hidden" name="hoge" value=""/>
</form>
見やすくする
<form>
<input type="hidden" name="message" value="">
<script>alert('hogehoge');</script>
<input type="hidden" name="hoge" value=""/>
</form>
これは典型的なXSSの攻撃だがCSPを実装していると、コード内にインラインJavascriptがあるので弾いてくれる
もちろん各Webserverフレームワークである程度防御機構はあるがブラウザレベルで検知して表示をブロックしてくれるので、言語問わず使える上にフレームワーク側の脆弱性があったとしても防げる
指定URL以外へのアクセスを防ぐことができる
自分の想定していないURLへのアクセスがあった場合ページをブロックする
例えばexample.comとcdn.example.com以外のURLにアクセスしていたらブロックすることができる
これは不正なコンテンツへのアクセスを防ぐことができるので、結果安全となる
現実的な対応
インラインCSSとJSは多くのサイトではあると思います。
また広告とかを貼っている場合、広告のSDKがさらに別ドメインのURL呼び出したりしているのでURL規制も難しいと思う。
そういった時に対応工数とか考えるとSSLを必須にする程度が着地点かと思われる。
SEOやユーザーからの信頼を考えるとページのSSL化は必須です。
こんな話も出てます。
Google Chrome、2017 年から HTTP ページで警告表示
https://www.digicert.ne.jp/blog/chrome56-direction.html
ブロックとレポート
しかしブロックしてしまうとページが見えなくなるのでそれは困ります。
ブラウザの機能としてCSP Reportという機能があり、コンテンツがCSPに違反している場合指定のURLにPOSTでアクセスしてCSPの違反の内容を送信してページは表示してくれます。
以下の二種類です。
add_header Content-Security-Policy "default-src https://* ; report-uri https://example.com/" ;
add_header Content-Security-Policy-Report-Only "default-src https://* ; report-uri https://example.com/" ;
設定例
Nginxだとこんなところになる。
server {
listen 80;
server_name localhost;
location / {
add_header Content-Security-Policy-Report-Only "default-src https://* ; report-uri https://example.com/" ;
root /var/www/html;
}
}
体験して欲しいこと
今回作ったコードはDockerとSlackがあればCSPをすぐにでも体験して通知できます。
通知がなくていいのであれば、Dockerだけで体験できます。
SSL証明書はオレオレ証明書なので警告出ますので無視していただく必要があります。
またドメイン別に通知する仕組みも一応作ってあります。
構築した後にこのページにアクセスして、ソースコードを見てもらえるとわかります。
CSSで赤文字を指定しているのに無効化されています。
https://localhost:8080/css.html?csp=block
さいごに
CSPはまだまだ認知度が低いので今後広めていきたいです。