技術をかじる猫

適当に気になった技術や言語、思ったこと考えた事など。

Playframework へのアクセス全部に共通のセキュリティヘッダを食わせる

まぁやってる事は ServletFilter とあんまり変わらない。

まずは適当にフィルタを作る。

コピペで安心はモットーです(2.2.1 で確認他のバージョンは知らん)

package utils

import play.api.mvc.{RequestHeader, Filter}
import scala.concurrent.Future
import play.api.mvc
import scala.concurrent.ExecutionContext.Implicits.global

object SecurityFilter extends Filter {
  override def apply(f: (RequestHeader) => Future[mvc.SimpleResult])(rh: RequestHeader): Future[mvc.SimpleResult] = {
    val next = f(rh)
    next.map(r => r.withHeaders(
      // "Strict-Transport-Security" -> "max-age=31536000; includeSubDomains",
      "Cache-Control" -> "private",
      "X-Frame-Options" -> "DENY",
      "X-XSS-Protection" -> "1; mode=block",
      "X-Content-Type-Options" -> "nosniff",
      "X-Content-Security-Policy" -> "default-src 'self'; allow 'self'",
      "X-WebKit-CSP" -> "default-src 'self'; allow 'self'"
    ))
  }
}

これを Global で下記のように。

import play.api._
import play.api.mvc._
import utils.SecurityFilter

object Global extends GlobalSettings {
  override def doFilter(action: EssentialAction) = SecurityFilter(action)
}

ヘッダの内容は上から順に

  1. 次以降はHTTPS アクセスを要求
  2. キャッシュ個人単位(キャッシュから情報が漏れるのを防ぐ…ってやり過ぎ?)
  3. フレーム禁止
  4. XSS はクライアントでも気をつけてね
  5. サーバから指定したファイルタイプとして開いてね
  6. JavaScript とかデータとか同じドメイン以外は認めない

という感じ。

何に対する防御なのかはヘッダ名で ggr やふれ ゲイツに聞け