home ホーム search 検索 -  login ログイン  | reload edit datainfo version cmd icon diff delete  | help ヘルプ

PHP/セッションとクッキーの共存/セッション固定化問題への影響

PHP/セッションとクッキーの共存/セッション固定化問題への影響

PHP / セッションとクッキーの共存 / セッション固定化問題への影響
id: 1094 所有者: msakamoto-sf    作成日: 2012-06-24 19:39:20
カテゴリ: PHP 

Java/ServletとJSESSIONIDのURL管理 でServletコンテナでのJSESSIONIDのURL管理について調べました。今回はPHPの"session.use_only_cookies"と"session.use_trans_sid"の組み合わせについて、セッション固定化の問題に対する影響を調べてみました。

結論から言うと、やはり"session.use_only_cookies=Off"と"session.use_trans_sid=1"の組み合わせがもっとも影響度が大きいと思われます。一方で同じ"session.use_only_cookies=Off"でも、"session.use_trans_sid=0"であれば影響は限定的と思われます。


サンプルコード

Win7 SP1 日本語 32bit
PHP 5.2.14 (古くてすみません・・・)

今回使ったサンプルコード:t01.php

<?php
ini_set("display_errors", 1);
ini_set("session.use_only_cookies", 0);
ini_set("session.use_trans_sid", 0);
session_name("trans_sid_test");
session_start();
 
if (!isset($_SESSION['c1'])) {
    $_SESSION['c1'] = 0;
}
$_SESSION['c1']++;
?>
<html>
<body>
<h2>$_COOKIE</h2>
<pre>
<?php var_export($_COOKIE); ?>
</pre>
<h2>$_SESSION</h2>
<pre>
<?php var_export($_SESSION); ?>
</pre>
<h2>session_id() = <?php echo session_id(); ?></h2>
<hr>
<a href="./t01.php">a link</a><br>
<form action="./t01.php" method="POST">
<input type="text" name="dummy1" value="v1">
<input type="submit" value="POST">
</form>
<form action="./t01.php" method="GET">
<input type="text" name="dummy1" value="v2">
<input type="submit" value="GET">
</form>
</body>
</html>
ini_set("session.use_only_cookies", 0);
ini_set("session.use_trans_sid", 0);

の部分を書き換えて組み合わせを試しました。

"session.use_only_cookies=Off" && "session.use_trans_sid=1"

最初に一番問題となりやすい組み合わせです。
一昔前のケータイサイトを作るときとかはこの設定が多かったように思います。Cookieに対応してなくて、GETメソッドでリンクを作らざるをえないとなると、自前で特殊な管理を行わない限りはこの設定になってしまいます。

ini_set("session.use_only_cookies", 0);
ini_set("session.use_trans_sid", 1);

通常遷移のケース

初回アクセス:ブラウザにはCookieはセットされていないので、送られていない。

[request]:
GET /webtoys/phpsessid/trans_sid/t01.php HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:13.0) Gecko/20100101 Firefox/13.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Proxy-Connection: keep-alive

[response]:
HTTP/1.1 200 OK
Date: Sun, 24 Jun 2012 09:01:56 GMT
Server: Apache
Set-Cookie: trans_sid_test=9hkr08m2hlvgjv3e0eupsmsc30; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-Length: 692
Content-Type: text/html; charset=EUC-JP

<html>
<body>
<h2>$_COOKIE</h2>
<pre>
array (
)</pre>
<h2>$_SESSION</h2>
<pre>
array (
  'c1' => 1,
)</pre>
<h2>session_id() = 9hkr08m2hlvgjv3e0eupsmsc30</h2>
<hr>
<a href="./t01.php?trans_sid_test=9hkr08m2hlvgjv3e0eupsmsc30">a link</a><br>
<form action="./t01.php" method="POST"><input type="hidden" name="trans_sid_test" value="9hkr08m2hlvgjv3e0eupsmsc30" />
<input type="text" name="dummy1" value="v1">
<input type="submit" value="POST">
</form>
<form action="./t01.php" method="GET"><input type="hidden" name="trans_sid_test" value="9hkr08m2hlvgjv3e0eupsmsc30" />
<input type="text" name="dummy1" value="v2">
<input type="submit" value="GET">
</form>
</body>
</html>
  • PHPのtrans_sidの機能により、"<a>"リンクの"href"属性のURLに"?trans_sid_test=..."が追加されています。
  • "<form>"には自動的にhiddenの"trans_sid_test"が追加されています。

ここで"<a>"リンクをクリックします。

Cookie無しでtrans_sidで書き換えられたリンクをクリック
[request]:
GET /webtoys/phpsessid/trans_sid/t01.php?trans_sid_test=9hkr08m2hlvgjv3e0eupsmsc30 HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:13.0) Gecko/20100101 Firefox/13.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Proxy-Connection: keep-alive
Referer: http://localhost/webtoys/phpsessid/trans_sid/t01.php

[response]:
HTTP/1.1 200 OK
Date: Sun, 24 Jun 2012 09:02:00 GMT
Server: Apache
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-Length: 692
Content-Type: text/html; charset=EUC-JP

<html>
<body>
<h2>$_COOKIE</h2>
<pre>
array (
)</pre>
<h2>$_SESSION</h2>
<pre>
array (
  'c1' => 2,
)</pre>
<h2>session_id() = 9hkr08m2hlvgjv3e0eupsmsc30</h2>
<hr>
<a href="./t01.php?trans_sid_test=9hkr08m2hlvgjv3e0eupsmsc30">a link</a><br>
<form action="./t01.php" method="POST"><input type="hidden" name="trans_sid_test" value="9hkr08m2hlvgjv3e0eupsmsc30" />
<input type="text" name="dummy1" value="v1">
<input type="submit" value="POST">
</form>
<form action="./t01.php" method="GET"><input type="hidden" name="trans_sid_test" value="9hkr08m2hlvgjv3e0eupsmsc30" />
<input type="text" name="dummy1" value="v2">
<input type="submit" value="GET">
</form>
</body>
</html>
  • Cookie無しの初回と同様、trans_sid機能により"<a>"リンクには"?trans_sid_test=..."自動追加、formにもhidden要素が自動追加されています。
  • リクエストでセッションIDを渡しているため、"Set-Cookie"はレスポンスにありません。
Cookie有りでtrans_sidで書き換えられたリンクをクリック
[request]:
GET /webtoys/phpsessid/trans_sid/t01.php?trans_sid_test=9hkr08m2hlvgjv3e0eupsmsc30 HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:13.0) Gecko/20100101 Firefox/13.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Proxy-Connection: keep-alive
Referer: http://localhost/webtoys/phpsessid/trans_sid/t01.php?trans_sid_test=9hkr08m2hlvgjv3e0eupsmsc30
Cookie: trans_sid_test=9hkr08m2hlvgjv3e0eupsmsc30

[response]:
HTTP/1.1 200 OK
Date: Sun, 24 Jun 2012 09:05:38 GMT
Server: Apache
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-Length: 542
Content-Type: text/html; charset=EUC-JP

<html>
<body>
<h2>$_COOKIE</h2>
<pre>
array (
  'trans_sid_test' => '9hkr08m2hlvgjv3e0eupsmsc30',
)</pre>
<h2>$_SESSION</h2>
<pre>
array (
  'c1' => 4,
)</pre>
<h2>session_id() = 9hkr08m2hlvgjv3e0eupsmsc30</h2>
<hr>
<a href="./t01.php">a link</a><br>
<form action="./t01.php" method="POST">
<input type="text" name="dummy1" value="v1">
<input type="submit" value="POST">
</form>
<form action="./t01.php" method="GET">
<input type="text" name="dummy1" value="v2">
<input type="submit" value="GET">
</form>
</body>
</html>
  • Cookieが送信されているため、"<a>"リンクやform要素には特に書き換えは行われていません。

セッション固定化の問題を悪用されるケース

攻撃者が準備したCookie:1

被害者のブラウザにはまだCookieはセットされていない、初回アクセスのタイミングで攻撃者が準備したリンクをクリックしてしまったケース
[request]:
GET /webtoys/phpsessid/trans_sid/t01.php?trans_sid_test=1 HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:13.0) Gecko/20100101 Firefox/13.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Proxy-Connection: keep-alive

[response]:
HTTP/1.1 200 OK
Date: Sun, 24 Jun 2012 09:19:19 GMT
Server: Apache
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-Length: 592
Content-Type: text/html; charset=EUC-JP

<html>
<body>
<h2>$_COOKIE</h2>
<pre>
array (
)</pre>
<h2>$_SESSION</h2>
<pre>
array (
  'c1' => 1,
)</pre>
<h2>session_id() = 1</h2>
<hr>
<a href="./t01.php?trans_sid_test=1">a link</a><br>
<form action="./t01.php" method="POST"><input type="hidden" name="trans_sid_test" value="1" />
<input type="text" name="dummy1" value="v1">
<input type="submit" value="POST">
</form>
<form action="./t01.php" method="GET"><input type="hidden" name="trans_sid_test" value="1" />
<input type="text" name="dummy1" value="v2">
<input type="submit" value="GET">
</form>
</body>
</html>
  • 攻撃者の準備したセッションIDをそのまま受け付けています。
  • リクエストでセッションIDを渡しているため、"Set-Cookie"はレスポンスにありません。
被害者のブラウザには被害者自身のCookieがセットされていて、攻撃者攻撃者が準備したリンクをクリックしてしまったケース
[request]:
GET /webtoys/phpsessid/trans_sid/t01.php?trans_sid_test=1 HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:13.0) Gecko/20100101 Firefox/13.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Proxy-Connection: keep-alive
Cookie: trans_sid_test=1bseoje3qpd19n6f69ppfqrm40

[response]:
HTTP/1.1 200 OK
Date: Sun, 24 Jun 2012 09:25:24 GMT
Server: Apache
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-Length: 542
Content-Type: text/html; charset=EUC-JP

<html>
<body>
<h2>$_COOKIE</h2>
<pre>
array (
  'trans_sid_test' => '1bseoje3qpd19n6f69ppfqrm40',
)</pre>
<h2>$_SESSION</h2>
<pre>
array (
  'c1' => 4,
)</pre>
<h2>session_id() = 1bseoje3qpd19n6f69ppfqrm40</h2>
<hr>
<a href="./t01.php">a link</a><br>
<form action="./t01.php" method="POST">
<input type="text" name="dummy1" value="v1">
<input type="submit" value="POST">
</form>
<form action="./t01.php" method="GET">
<input type="text" name="dummy1" value="v2">
<input type="submit" value="GET">
</form>
</body>
</html>
  • Cookieで指定したセッションIDが使われています。
  • Cookieが送信されているため、trans_sid機能は使われていない。

"session.use_only_cookies=Off" && "session.use_trans_sid=0"

次に、PHP5.2までの殆どの場合のデフォルト状態です。(PHP5.3.0以降はuse_only_cookiesがデフォルト1に)

ini_set("session.use_only_cookies", 0);
ini_set("session.use_trans_sid", 0);

trans_sidが無効化されているので、注目するのはCookieとURLの両方で指定された場合の挙動になります。

Cookie無し + URLからセッションID

[request]:
GET /webtoys/phpsessid/trans_sid/t01.php?trans_sid_test=1 HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:13.0) Gecko/20100101 Firefox/13.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Proxy-Connection: keep-alive
Cache-Control: max-age=0

[response]:
HTTP/1.1 200 OK
Date: Sun, 24 Jun 2012 09:57:43 GMT
Server: Apache
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-Length: 465
Content-Type: text/html; charset=EUC-JP

<html>
<body>
<h2>$_COOKIE</h2>
<pre>
array (
)</pre>
<h2>$_SESSION</h2>
<pre>
array (
  'c1' => 3,
)</pre>
<h2>session_id() = 1</h2>
<hr>
<a href="./t01.php">a link</a><br>
<form action="./t01.php" method="POST">
<input type="text" name="dummy1" value="v1">
<input type="submit" value="POST">
</form>
<form action="./t01.php" method="GET">
<input type="text" name="dummy1" value="v2">
<input type="submit" value="GET">
</form>
</body>
</html>
  • URLで指定されたセッションIDが使われています。
  • Set-Cookieは発行されていません。
  • trans_sidが無効なので、次の遷移ではURLで与えられたセッションIDが無いため、新たにSet-Cookieで発行される形になります。つまり、URLで与えられたセッションIDを使い続けることはできません。(※但しアプリケーションの作りの問題で、リンクやformのaction属性に自動的にURLのリクエストパラメータが付加される場合を除く。)

Cookie有り + URLからもセッションID

[request]:
GET /webtoys/phpsessid/trans_sid/t01.php?trans_sid_test=1 HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:13.0) Gecko/20100101 Firefox/13.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Proxy-Connection: keep-alive
Cookie: trans_sid_test=v3s5g3q6hdd5g1rc17p3k32l60

[response]:
HTTP/1.1 200 OK
Date: Sun, 24 Jun 2012 09:57:11 GMT
Server: Apache
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-Length: 542
Content-Type: text/html; charset=EUC-JP

<html>
<body>
<h2>$_COOKIE</h2>
<pre>
array (
  'trans_sid_test' => 'v3s5g3q6hdd5g1rc17p3k32l60',
)</pre>
<h2>$_SESSION</h2>
<pre>
array (
  'c1' => 6,
)</pre>
<h2>session_id() = v3s5g3q6hdd5g1rc17p3k32l60</h2>
<hr>
<a href="./t01.php">a link</a><br>
<form action="./t01.php" method="POST">
<input type="text" name="dummy1" value="v1">
<input type="submit" value="POST">
</form>
<form action="./t01.php" method="GET">
<input type="text" name="dummy1" value="v2">
<input type="submit" value="GET">
</form>
</body>
</html>
  • Cookieで送信されたセッションIDが使われています。

"session.use_only_cookies=On" && "session.use_trans_sid=0"

サーバ側ではCookieで送信されてきたセッションIDのみを受け付けるため、URLセッション管理の問題を考える必要がありません。

ini_set("session.use_only_cookies", 1);
ini_set("session.use_trans_sid", 0);

Cookie無し + URLからセッションID

[request]:
GET /webtoys/phpsessid/trans_sid/t01.php?trans_sid_test=1 HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:13.0) Gecko/20100101 Firefox/13.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Proxy-Connection: keep-alive

[response]:
HTTP/1.1 200 OK
Date: Sun, 24 Jun 2012 09:32:15 GMT
Server: Apache
Set-Cookie: trans_sid_test=dfqi0odg0gkuojrbai3qqvl104; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-Length: 490
Content-Type: text/html; charset=EUC-JP

<html>
<body>
<h2>$_COOKIE</h2>
<pre>
array (
)</pre>
<h2>$_SESSION</h2>
<pre>
array (
  'c1' => 1,
)</pre>
<h2>session_id() = dfqi0odg0gkuojrbai3qqvl104</h2>
<hr>
<a href="./t01.php">a link</a><br>
<form action="./t01.php" method="POST">
<input type="text" name="dummy1" value="v1">
<input type="submit" value="POST">
</form>
<form action="./t01.php" method="GET">
<input type="text" name="dummy1" value="v2">
<input type="submit" value="GET">
</form>
</body>
</html>
  • URLで指定されたセッションIDは無視され、新しいセッションIDが発行されています。

Cookie有り + URLからもセッションID

[request]:
GET /webtoys/phpsessid/trans_sid/t01.php?trans_sid_test=1 HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:13.0) Gecko/20100101 Firefox/13.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Proxy-Connection: keep-alive
Cookie: trans_sid_test=1bseoje3qpd19n6f69ppfqrm40

[response]:
HTTP/1.1 200 OK
Date: Sun, 24 Jun 2012 09:32:00 GMT
Server: Apache
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-Length: 543
Content-Type: text/html; charset=EUC-JP

<html>
<body>
<h2>$_COOKIE</h2>
<pre>
array (
  'trans_sid_test' => '1bseoje3qpd19n6f69ppfqrm40',
)</pre>
<h2>$_SESSION</h2>
<pre>
array (
  'c1' => 10,
)</pre>
<h2>session_id() = 1bseoje3qpd19n6f69ppfqrm40</h2>
<hr>
<a href="./t01.php">a link</a><br>
<form action="./t01.php" method="POST">
<input type="text" name="dummy1" value="v1">
<input type="submit" value="POST">
</form>
<form action="./t01.php" method="GET">
<input type="text" name="dummy1" value="v2">
<input type="submit" value="GET">
</form>
</body>
</html>
  • Cookieで送信されてきたセッションIDが使われ、URLで指定されたセッションIDは無視されています。

"session.use_only_cookies=On" && "session.use_trans_sid=1"

ini_set("session.use_only_cookies", 1);
ini_set("session.use_trans_sid", 1);

エビデンスは"session.use_trans_sid=0"の時と全くおなじになりました。use_only_cookiesが有効ですとuse_trans_sidは強制的に無効になるのかもしれません。何れにしても、URLでセッションIDを指定しても無視される挙動は同じです。

まとめ

  • PHPの場合、URLまたはPOSTパラメータで指定したセッションIDが使われるのは以下の条件になります。
    • "session.use_only_cookies=Off"
    • リクエストのCookieでセッションIDを送信していない。
  • また、URLまたはPOSTパラメータでセッション管理を続けるには"session.use_trans_sid=1"の設定が必要です。

外部の利用者が"use_trans_sid=1"であることを確かめるには、ブラウザの設定またはプロキシツールの設定でCookieを無効化してサイトにアクセスし、常にURLやPOSTパラメータでセッションIDをやり取りしていることを確認します。

セッション固定化の悪用への影響については、"use_trans_sid=0"の場合は低いと思われます。なぜなら、以下のように攻撃者がせっかくセッションIDを用意して被害者を誘導できたとしても、その先の本来の目的である被害者の操作とセッションIDの結びつけが出来ないと思われるからです。

  1. 攻撃者が被害者を誘導
  2. 被害者が攻撃者が用意したセッションIDでログイン画面などアクセス
  3. trans_sidが動いていないため、ログインなどのPOST用FormやリンクにはセッションIDが入っていない
  4. 被害者はログインなどのPOST用Formやリンクをクリックしても、攻撃者が用意したセッションIDは被害者の操作と結びつかない。

スマホの台頭や、ガラパゴスケータイのブラウザでもCookieが利用可能なものが増えていると思いますので、新規にサイトを開発する場合や、既存のサイト改修でいい加減Cookie未対応のガラパゴスケータイを考慮しなくても良くなるのであれば、思い切って(?) "session.use_only_cookies=1" にすると安全だと思います。



プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2012-06-24 19:39:47
md5:9898b51aa40ca7669aa2e91dfe598c1c
sha1:48a6c1dbd32994826c003082a88256373dbe4880
コメント
コメントを投稿するにはログインして下さい。