CSRF(クロスサイトリクエストフォージェリ)の対策を自分の中で決めてみましたが、根本的に間違った理解をしてることがわかりました

CSRFはそのユーザ自身(のクライアント)がアクセスする(させる)ことを利用する攻撃なんですな!

高木浩光さんの記事(via ファイさん)を元にPHPでのサンプルを作ってみました。

ログインページ(index.php):

<?php
session_start();
?>
<?="<?xml version=\"1.0\" encoding=\"utf-8\"?>"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<title>ログイン</title>
</head>
<body>
<h1>ログイン</h1>
<p>ログインしました。</p>
<p><a href="confirm.php">退会</a></p>
</body>
</html>

確認ページ(confirm.php):

<php
session_start();
?>
<?="<?xml version=\"1.0\" encoding=\"utf-8\"?>"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<title>退会処理 確認画面</title>
</head>
<body>
<h1>退会処理 確認画面</h1>
<p>本当に退会しますか?</p>
<form method="post" action="resign.php">
<strong>&lt;input type="hidden" name="sessionid" value="&lt;?=session_id()?&gt;" /&gt;</strong>
&lt;input type="submit" value="退会する" /&gt;
&lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;

処理ページ(resign.php):

&lt;?php
session_start();
if (<strong>session_id() == $_POST["sessionid"]</strong>) {
    $message = "退会しました。";
} else {
    $message = "退会・・・するかよ!";    
}
?&gt;
&lt;?="&lt;?xml version=\"1.0\" encoding=\"utf-8\"?&gt;"?&gt;
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
&lt;html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja"&gt;
&lt;head&gt;
&lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8" /&gt;
&lt;meta http-equiv="Content-Style-Type" content="text/css" /&gt;
&lt;meta http-equiv="Content-Script-Type" content="text/javascript" /&gt;
&lt;title&gt;退会処理 完了画面&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h1&gt;退会処理 完了画面&lt;/h1&gt;
&lt;p&gt;&lt;?=$message?&gt;&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;

動いてるサンプル:http://p0t.jp/anti-csrf/

ソース:anti-csrf-0.2.zip

外部サイトでは(本人がアクセスしたとしても)対象サイトのクッキーを取ることができないっていうのがミソ・・・だと思う。
あってるのかどうか気になります!

それほど面倒ではないのでコンシューマサイトは全部これで行くことにします!

ref: CSRF対策俺ルール

2005/07/08追記:

$_COOKIE[””PHPSESSID”“] から session_id() に変更しました。(via ishinao

Comments


Option