<前の日記(2005年04月24日) 次の日記(2005年05月20日)> 最新 編集

高木浩光@自宅の日記

目次 はじめに 連絡先:blog@takagi-hiromitsu.jp
訪問者数 本日: 1483   昨日: 1412

2005年04月27日

クロスサイトリクエストフォージェリ(CSRF)の正しい対策方法

「クロスサイトリクエストフォージェリ」がにわかに注目を集めている。古く から存在したこの問題がなぜ今まであまり注目されてこなかったかについて考 えているところだが、引越しやら転勤やらでいまひとつ日記を書く時間がない。 しかし、 @ITの記事などのように混乱させる解説も散見されるので、一点だけ対策 方法について書いておくとする。

クロスサイトリクエストフォージェリ――Cross-Site Request Forgeries (CSRF)を防止する簡潔で自然な解決策は以下のとおりである。

前提

ログインしていないWeb閲覧者に対するCSRF攻撃(掲示板荒らしや、ユーザ登 録を他人にさせる等、サイト運営者に対する業務妨害行為)はここでは対象と しない。

ログイン機能を持つWebアプリケーションの場合、何らかの方法でセッション 追跡(セッション管理)を行っているはずであり、それをcookieの値を頼りに 行っている場合、そのcookieの値は第三者には予測不能な値が選ばれているは ずである。(でなければ、セッションハイジャックされたり、なりすましログ インされてしまうのだから、CSRF以前の重大な欠陥があることになる。)

最も自然な方式では、ログインごとに発行するランダムな受付番号、つまり 「セッションID」を1個(ないし https:// 専用を含む2個)用いて、どのユー ザからのアクセスなのかを検索して特定する――(A)。この値を十数桁以上の 乱数とすることで、偶然に的中する確率を何億分の1までに小さくしている。

あまり適切ではないが何らかの都合でセッションIDを使わずに、cookieにユー ザIDを入れる方式となっている場合もあるが、それだけでは予測不能とはなら ないので、そうした場合はそのユーザのパスワードのハッシュ値などもcookie に格納して、ページ毎に両方を確認することによって、なりすましされないセッ ション追跡を実現することになる――(B)。この場合の予測不能性は、パスワー ドが予測不能なはずであることに立脚している。

CSRFを防ぐ必要があるのは、Webアプリケーションに対して何らかの恒久的な データ変更を発生させるアクセスとなるページ(登録情報変更、設定変更、退 会処理、注文実行、取り消しなど)である。たとえば、情報を表示するだけの ページには対策が不要、もしくは重要性が低い(後述の「2ページ目」など)。 ショッピングカートへの商品追加などのように、一時的な状態変更を加えるだ けのページに対するCSRF対策の重要性は低めとなる*1

たとえば住所変更の機能を想定すると、1ページ目で現在の登録情報が入力欄 に埋め込まれて表示され、その入力欄の必要な部分を書き換えてボタンを押す と 2ページ目で確認画面となり、「変更」ボタンを押すと変更が処理されて 3 ページ目が表示されるという構成が多い。ここで、3ページ目に直接外部から ジャンプさせられると、住所を勝手に変更されてしまうことが起きる。

簡潔な対策方法

Webアプリケーションに対してデータ変更を処理させるページ(前述の「3ペー ジ目」)の前のページ(前述の「2ページ目」)に以下のHTML要素を含ませる。

 <input type="hidden" name="sessionid" value="セッション追跡用cookieの値"> 

そして、「3ページ目」で、そこに送信されてくるこの値が、cookieのその値 と一致しているかを調べて、一致しているときだけ処理を実行する。

「セッション追跡用cookieの値」には、前述の(A)方式ならばセッションIDの 値、(B)方式ならばユーザIDとパスワード(のハッシュ値など)の両方を格納 し、「3ページ目」でそれぞれの一致を確かめる。

第三者サイトから「3ページ目」へのハイパーリンク(JavaScriptによる自動 POSTを含む)が作られても、一致させる値を予測することは不能であるはずな ので、CSRF攻撃は成功しない。

制限事項

一致するかを確認するのは「3ページ目」だけでよいのか。そのままでは、 「2ページ目」へのハイパーリンクを作ることはできてしまう。しかしその場 合、被害者は「2ページ目」が現れたところで自発的に「3ページ目」へ進む ボタンを押さない限り被害に遭わない(XSS脆弱性など他の脆弱性がなければ)。

そこでボタンを押してしまいやすいかどうかは、「2ページ目」の画面内容に 依存する。たとえば、「本当に実行しますか?」以外に何も書かれていない 「2ページ目」である場合には、ボタンを押してしまうかもしれないので、 さらに前のページから同様の対策が必要となる。もっとも、ボタンを押すと何 が起きるのかを適切に説明しておくことは、もとより要求されるところである。

不適切な解説の例

  • GETを使わずPOSTを使え。*2
  • 実行の前に確認画面を挟め。*3
  • Referer:は偽装できるので対策にならない。*4
  • ワンタイムトークンを使わなくてはならない。*5
  • ログインなしのWebアプリケーションに対するCSRF攻撃(掲示板荒らし) を防止するには、セッションIDやワンタイムトークンを使えばよい。*6
  • 実行画面(「3ページ目」)に必要な情報を引数(hiddenを含む)に持た せず、「2ページ目」までにそれら必要な情報はセッション変数(Webアプリケー ション側で、セッションIDに結び付けて記憶している情報)に格納しておき、 「3ページ目」の処理ではそれを利用すればよい。*7

BASIC認証の場合

(続く)

*1 注文実行時にカー トの内容を確認するように作られているべきなので、そうなっていれば、気付 かないユーザの責任となる。

*2 JavaScriptで自動POSTさせられる。

*3 確認画面の次の実行画面に直接ジャ ンプさせられる。

*4 対策にならない理由 は、Referer:を送信しない設定にしているユーザがいるため。Referer:偽装が 問題となるのは、セッションハイジャック防止や、なりすましアクセス防止の ためにReferer:チェックをする話の場合。攻撃者が被害者の送信するReferer: を書き換えることはできないのだから、CSRFにReferer:偽装は関係ない。

*5 元々あるセッショ ン追跡用の秘密情報を使えばよい。

*6 Session Fixation攻撃によって回避される。

*7 「2ページ目」(引 数を持つ)に対してCSRF攻撃され、続いて「3ページ目」にCSRF攻撃される可 能性があるので、対策にならない。

本日のTrackBacks(全100件) [TrackBack URL: http://takagi-hiromitsu.jp/diary/tb.rb/20050427]

昨日の「コラムが検閲引っかかりまくり」で触れた@IT:「ぼくはまちちゃん」 ――知られざるCSRF攻撃が本日より公開しています。 追記:2005/4/27 下記で補足して頂いています。 ・hoshikuzu | star_dust の書斎 - CSRF対策とCAPTCHA ・yoggy’s diary~せかいのすみっこ..

ある nakagami の日記:CSRF 攻撃 (2005年04月28日 12:47)

mixi には入ってないので詳細もわからないし、いちいちはやりものに反応 しているときりがないので静観していたが高木さんの日記に取り上げられているので、 CSRF攻撃のことをちと書いてみる。 http://takagi-hiromitsu.jp/diary/20050427.html#p01 全体的に、わかりやす..

http://takagi-hiromitsu.jp/diary/20050427.html http://www.atmarkit.co.jp/fsecurity/column/ueno/33.html http://www.google.com/search?hl=ja&amp;q=CSRF&amp;btnG=Google+%E6%A4%9C%E7%B4%A2&amp;lr=lang_ja クロスサイトリクエストフォージェリ ( CSRF ) 関連のお..

-[http://takagi-hiromitsu.jp/diary/:title] --「目次」のリンクだけ、はてなダイアリのままです。移行期間中は、有意義だったものを直し忘れているのでは?

p0t:CSRF対策俺ルール2 (2005年07月07日 16:40)

CSRF(クロスサイトリクエストフォージェリ)の対策を自分の中で決めてみましたが...

おさかなラボ:CSRFの現状 (2005年08月09日 02:35)

CSRFについて。
「CSRFって何?」って話はGoogleに譲るとして、CSRFの対策について誤解をしていたり、正しくない対処を推奨しているサイトが多い気がします。
とりあえず
googleで「CSRF」で引っかかるサイトの上位に1つずつツッコミ入れてみます。

http://www.s...

クロス サイト リクエスト フォージェリぃ被害者??

p0t:サテ技本のCSRF対策に疑問 (2005年12月26日 21:25)

PHPサイバーテロの技法―攻撃と防御の実際ソシム(2005-11)(著)GIJO...

開発者のための正しいCSRF対策 高木浩光@自宅の日記 - クロスサイトリクエストフォージェリ(CSRF)の正しい対策方法 こめんと(2006-03-30) 最近Webアプリ自体組まないんですけど… ...

検索

<前の日記(2005年04月24日) 次の日記(2005年05月20日)> 最新 編集

最近のタイトル

2025年03月06日

2025年03月04日

2025年03月01日

2025年02月11日

2025年02月08日

2025年02月01日

2025年01月26日

2025年01月03日

2024年12月28日

2024年12月22日

2024年12月07日

2024年12月02日

2024年11月24日

2024年11月11日

2024年07月28日

2024年07月27日

2024年07月07日

2024年04月07日

2024年04月01日

2024年03月23日

2024年03月19日

2024年03月16日

2024年03月13日

2024年03月11日

2023年03月27日

2022年12月30日

2022年12月25日

2022年06月09日

2022年04月01日

2022年01月19日

2021年12月26日

2021年10月06日

2021年08月23日

2021年07月12日

2020年09月14日

2020年08月01日

2019年10月05日

2019年08月03日

2019年07月08日

2019年06月25日

2019年06月09日

2019年05月19日

2019年05月12日

2019年03月19日

2019年03月16日

2019年03月09日

2019年03月07日

2019年02月19日

2019年02月11日

2018年12月26日

2018年10月31日

2018年06月17日

2018年06月10日

2018年05月19日

2018年05月04日

2018年03月07日

2017年12月29日

2017年10月29日

2017年10月22日

2017年07月22日

2017年06月04日

2017年05月13日

2017年05月05日

2017年04月08日

2017年03月10日

2017年03月05日

2017年02月18日

2017年01月08日

2017年01月04日

2016年12月30日

2016年12月04日

2016年11月29日

2016年11月23日

2016年11月05日

2016年10月25日

2016年10月10日

2016年08月23日

2016年07月23日

2016年07月16日

2016年07月02日

2016年06月12日

2016年06月03日

2016年04月23日

2016年04月06日

2016年03月27日

2016年03月14日

2016年03月06日

2016年02月24日

2016年02月20日

2016年02月11日

2016年02月05日

2016年01月31日

2015年12月12日

2015年12月06日

2015年11月23日

2015年11月21日

2015年11月07日

2015年10月20日

2015年07月02日

2015年06月14日

2015年03月15日

2015年03月10日

2015年03月08日

2015年01月05日

2014年12月27日

2014年11月12日

2014年09月07日

2014年07月18日

2014年04月23日

2014年04月22日

2000|01|
2003|05|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|05|06|07|08|09|10|11|12|
2012|02|03|04|05|06|07|08|09|
2013|01|02|03|04|05|06|07|
2014|01|04|07|09|11|12|
2015|01|03|06|07|10|11|12|
2016|01|02|03|04|06|07|08|10|11|12|
2017|01|02|03|04|05|06|07|10|12|
2018|03|05|06|10|12|
2019|02|03|05|06|07|08|10|
2020|08|09|
2021|07|08|10|12|
2022|01|04|06|12|
2023|03|
2024|03|04|07|11|12|
2025|01|02|03|
<前の日記(2005年04月24日) 次の日記(2005年05月20日)> 最新 編集