17
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

同一ドメイン上の別ユーザからのCookie盗難を防ぐ

Last updated at Posted at 2016-09-05

同一ドメイン上に複数のユーザがいる

これでセキュリティ問題は解決です。めでたし。

     *      *
  *     +  うそです
     n ∧_∧ n
 + (ヨ(* ´∀`)E)
      Y     Y    *

全然めでたしじゃなかった
思いっきり嘘書いてしまったのでもう少し調べてみます。

bの攻撃

/b/hoge.html
<iframe src="/a/list.php" name="iframeid" id="iframeid" onLoad="hoge();"></iframe>
<a href="#" id="href" onClick="document.body.appendChild(document.createTextNode(iframeid.document.cookie));return false;">Get cookie</a>

<script>
	function hoge(){
		// /b/上にいるが/a/のCookieが取得できる
		document.body.appendChild(document.createTextNode(iframeid.document.cookie));
		document.getElementById("href").click();
		
		// 本文も取れる
		console.log(document.getElementById('iframeid').contentWindow.document.body);
	}
</script>

リンク先のサイトでは手動でクリックさせていましたが、実際はクリックすら不要で、間違って画面を読み込んでしまうだけで/a/のCookieを取得することが可能です。

aの抵抗

a側には対抗策があり、/a/list.phpに

/a/list.php
	header('X-FRAME-OPTIONS: DENY');

と書いておけばフレームでのファイル読み込みを防ぐことができます。
b側にはBlocked a frameのSecurityErrorが返され、その場合bはaのCookieを読むことはできません。

aもFRAMEを使えなくなりますが、まあ今時フレームなんか使わないから問題ないでしょう。
$.ajax()等では問題なく取得可能です。

b側からフレームでのアクセスはできなくなりましたが、もちろん$.ajax()で本文を取得することは可能です。
しかし、うっかりCookieを画面上に表示していたなどという事故でもないかぎり、aのCookieは取得できません。

bの反撃

b側もこれに対応して、src="/a/image.png"とかsrc="/a/notexist.php"とか指定してきます。
画像などのX-FRAME-OPTIONSを仕込めないファイルはPHPでは対抗できません。
また存在しないファイルを指定した場合は404 Not Foundのエラーが返りますが、その場合は何故かaのCookieが読めてしまいます。

aの絶対防御

これに対抗するには、a側は.htaccessで

	Header always append X-Frame-Options DENY
	RewriteEngine On
	RewriteCond %{REQUEST_FILENAME} !-f
	RewriteRule ^.*$ /a/notfound.html [L]

などとしないといけません。
これによって、あらゆるファイルに常にDENYのX-Frame-Optionsがつきます。
また存在しないファイルへのアクセスはエラーページを出すことで、こちらも404 Not FoundではなくSecurityErrorを返すことができます。

逆に言うと.htaccessが設置できないサーバ、設置できてもRewriteEngineが使用できないサーバでは対抗する術がありません。

bのさらなる攻撃

とりあえずこの状態で、私が調べた限りでは/b/以下から/a/のCookieを読み取ることはできませんでした。

が、逆に考えればよいのだ。
読めなければ書き込めばいいと。

/b/set.php
	setcookie('PHPSESSID', 'evil', time()+999999, '/a/');

同一ドメインなので何の抵抗もなくCookieをセット可能です。
あとは/b/set.phpにアクセスした人がaにログインした頃合いを見計らってアクセスすれば、個人情報を取り出せるという寸法です。

まあ、これはセッション固定攻撃そのものなので、きちんとsession_regenerate_id(true)していれば特に問題ないですが。

まとめ

設定次第では、別ディレクトリからのCookie読み取りを防ぐことは可能のように見える。
何か見逃しているだけだとは思うけど。
書き込みは防げないため、勝手にログアウトされてしまったりという悪戯は可能。

とはいえ、小手先の対策を弄するより、サブドメ切ってくれるサーバに引っ越すのが一番いい。

17
15
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?