ぽかぽかコード日和

とっても暑い夏の日にプログラミングはじめました☀️

【Security】クロスサイト・スクリプティング(XSS)+Laravel実装

概要

Webアプリケーションの出力処理に脆弱性があると、
攻撃者にHTML内に悪意のあるスクリプトを埋め込まれる
ユーザーのブラウザ上でスクリプトを実行させ、 出力されたその情報を盗み取る(攻撃者のサーバーに送信させるなど)攻撃。

  • Cookieを使ってログインのセッション管理をしているサイトは特に注意する。


ユーザーにスクリプトを送信させる方法
  • 反射型:悪意のあるメール等のURLをユーザーがクリックしたとき
  • 格納型:掲示板などでスクリプト付きの投稿をユーザーにさせて、他のユーザーが閲覧したとき
  • DOM型:javascript脆弱性を狙う


発生しうる脅威

原因

  • 出力前のエスケープ処理の未実施や抜けもれ
  • 文字コードの未指定
  • 入力値のバリデーションの不足

対策

根本的解決

1.すべての出力要素にエスケープ処理をする
  • 特別な意味を持つ文字をHTMLエンティティへ変換し、無害化(サニタイジング)する。
  • HTMLタグを出力するときは、属性値を必ずダブルクォートでくくる。
  • すべての出力に対して処理を行うが、ユーザーからの入力、データベースやファイルから読み込んだ文字列、演算によって生成した文字列等に特に注意する。
$keyword = param('keyword'):

print "<input  value="$keyword">”
↓
print "<input  value=\"" . htmlspecialchars($keyword, ENT_QUOTES). "\">";

☀︎PHPのhtmlspecialchars()は、
スクリプトの構成に必要な特殊文字(&,<,>,”,’)を、(&amp:, <, >, " ')へ置換する関数。 「ENT_QUOTES」と指定すると、"と'の両方がエスケープされる。

2.「http://」「https://」で始まるURLのみ許可する
  • href, rel, src などの属性値にユーザからの入力を使うとき、「javascript:」から始まるスクリプトを埋め込まれてしまう。
3.文字コードの指定する
  • ブラウザは受け取ったHTMLを指定した文字コードで解釈する。

① HTTPレスポンスヘッダの「Content-Type」フィールドに、「charaset=UTF-8」と指定する
② HTMLのMETA宣言に、「charaset=UTF-8」と指定する
③設定など外部リソースを指しているファイルにも文字コードを指定する

保険的対策

4.Cookieの発行時にHttpOnly属性をつける
  • Cookie情報の漏洩対策の一つで、盗用を防ぐ。
  • HTMLテキスト内のスクリプトからアクセスできなくなる。
  • 発行するときに「Set-Cookie: HttpOnly」と設定する。
5.ユーザーからの入力値を制限する
  • XSS攻撃ではリンク等を踏ませるため、入力側のバリデーションを経由することはないが、
    入力値のバリデーションで不正な入力を排除することができ、
    攻撃のリスクを減らすことはできる。

  • ホワイトリスト方式を使う
    その引数に許可する文字の組み合わせを決めておき、それ以外は許可しない方式。 郵便番号の入力なら、数字以外の入力を許可しない。 他にも入力値の長さ制限をつけることで、攻撃が可能となるスクリプトの挿入を抑制することもできる。

  • 出力の文字列は削除ではなく、無害化(サニタイジング)で置換するようにする。 削除したことにより、スクリプト文字列を形成してしまう。

Laravelでの実装例

1. {{ }}で囲みエスケープ処理をする

  • 出力する変数を{{ $変数名 }}と囲むだけで、自動的にPHPのhtmlspecialchars関数を通されエスケープ処理をしてくれる。

  • エスケープ処理をしたくないときは、{!! $変数名 !!}と囲む。非推奨

ビューのblade.phpファイルに

<body class="antialiased">
    @auth
        <p>
            {{ Auth::user()->name }}さん、こんにちは。
        </p>
    @endauth
</body>

☀︎ログイン中のユーザーの名前を表示している。

  • @authディレクティブで、ログイン済みユーザーだけに表示している。

参考にしたサイト