@kyanny's blog

My life. Opinions are my own.

4. Webアプリケーションの機能別に見るセキュリティバグ (4.5 「重要な処理」の際に混入する脆弱性)

いわゆる CSRF の話。

  • CSRF Cross-Site Request Forgeries
    • アプリケーションの正規の利用者の権限で、意図せず重要な処理へのリクエストが発行され、悪用される(例: はまちちゃん「こんにちはこんにちは!!」)
    • XSS とは違い直接アカウントの個人情報やセッション Cookie のような情報を攻撃者が知り得るものではない
  • 罠の HTML の例
<body onload="document.forms[0].submit()">
<form action="http://target.example.jp/" method="post">
<input type="hidden" name="pwd" value="hoge">
</form>
</body>
    • 正規の利用者がログイン状態でこの HTML が含まれる罠のページを閲覧すると CSRF 脆弱性がある URL へ POST メソッドが「正規利用者の権限で」送られる
    • 罠のページに隠し iframe で仕込んで仕掛ける
    • iframe の外側(攻撃者のドメイン)から内側(攻撃対象のサイト、攻撃用の form が送信されると「変更しました」ページが表示されるので攻撃対象のドメインになる)の内容は読み取れない(直接攻撃者が情報を盗むことはできない)
  • CSRF と XSS の比較、類似性(どのステップで攻撃が成立するかを混同しない)
  • 確認画面がある場合
    • hidden で持ちまわる -> ふつうに最後の POST を攻撃対象にするだけ
    • 確認画面に遷移する際にセッションに入れる -> 複数の iframe を用意して時間差の onload="form.submit" を使う(確認画面がいくつあっても対応可能)
  • CSRF 脆弱性がうまれる原因
    • form 要素の action 属性にどのドメインの URL でも指定できる
    • クッキーに保存されたセッション ID は対象サイトに自動的に送信される
    • 利用者の意図したリクエストと意図しないリクエストにはほとんど差がない(Referer くらい)
  • 対策
    • CSRF 対策が必要なページを区別する (「重要な処理」が最終的に実行されるリクエスト)
    • 意図したリクエストであることを確認する
      • トークンの埋め込み -> 第三者に推測できないものであること -> セッション ID で良い(ワンタイムトークンに優位性はあるのか?という議論のコラム)
      • パスワード再入力(攻撃者の罠による意図しないリクエストでは送信できない情報) -> 常に「重要な処理」が最終的に実行されるリクエストで確認する(確認のために二回入力させるのが一般的)
      • Referer のチェック -> 正規表現のチェック漏れに注意(前方一致で絶対 URL && ドメイン後のスラッシュ / まで含めてチェック)必須条件!
m{\Ahttp://example\.jp/.*\z}
      • トークン埋め込み >> パスワード再入力 >> Referer 確認
  • 保険的対策
    • 「重要な処理」が実行されたことを登録メールアドレスへ通知