初めに
みなさんは、
session_start();
だけでセッションを利用していませんか?もし、この一行だけでsessionを使用しているのなら、直ちに変更したほうがいいでしょう。
どこが危ないのか
セッションの仕組みをもう一度確認してみましょう。
まず、サーバーが初アクセスのプレイヤーにクッキーでIDを作成し保存します。
そのあと、セッションIDをアクセス毎に確認し、保存データからHTML等を生成します。
ここで注意する点が、Cookieでsessionidを保存するということです。
Cookieとは、クライアント側で変更可能(ほとんどのブラウザで可能)なため、友人のsessionidを盗めばログインもできてしまいますし保存データもすべてアクセスできてしまいます。
つまり、ほとんどのサイトがsessionにログインデータを保存しているので、ユーザーを識別するためのsessinidが盗まれてしまえば保存されているデータも盗まれるということになりますし、メモサイトであればメモのデータを変更さえ削除さえできてしまいます。
簡単な事例としては、パソコンを教えに来た(ミラサポのようなサービス)人がデータを盗むのは簡単でしょう(そこまでの悪事を働く人はそういないと思いますけども)。
対策しているサイト/していないサイト
対策しているサイト/していないサイトを独自で調べたのでまとめます。
サイト/サービス名 | ドメイン名 | 対策 |
---|---|---|
google.com | 不明(多分してあると思うが作りが複雑) | |
Qiita | qiita.com | 対応(やるとコピーした側、コピーする側の両方がログアウトする) |
ネットショップ作成BASE | base.com | 非対応 |
MyNintendoStore | store.nintendo.co.jp | 対応しているよう |
プログラミングを学べる!Scratch | scratch.mit.edu | 非対応 |
teratail | teratail.com | 対応しているよう |
Amazon | amazon.com | 非対応(セッションID以外のデータもコピーが必要) |
(基準:セッションID等保存データをコピーした時ログインされるかどうか。) | ||
基準はCookieのsessionid貼り付けと関連していそうなものがあったとき張り付けたときログインされるかされないかです。(自己判断なので間違っていたらコメントください。) |
対処法は?
方法1 IPアドレスで確認
<?php
session_start();
if(isset($_SESSION["ipdata"])){
if( !$_SESSION["ipdata"]===$_SERVER["REMOTE_ADDR"] ){
exit("いつもとちょっと違うからログインを一時停止中");
}
}else{
$_SESSION["ipdata"]=$_SERVER["REMOTE_ADDR"];
}
?>
メリット・デメリット
メリット:
- 簡単
- 処理が少ない
- パソコンのみサイト向け
デメリット:
- 可変IPの場合使い物にならない=wi-fiでないと動かない
これは本当に本当に推奨できません。というかこの方法でやらないでください。ユーザーに迷惑をかけてしまいますから。(しばらくするとすぐログアウトするようなサイトは皆さんも嫌いでしょう。)
方法2 JSも活用
今度は、phpだけでなくjavascriptも使用しやりましょう。今回は、localstorageを使用します。
index.php(ファイル名は何でも)
<?php
session_start();
session_id();
$script="";
$storageSaveName="sessioniddata";
if(!isset($_SESSION["siddata"])){
$_SESSION["siddata"]=session_id();
$script='if(!localstorage.getItem("'.$storageSaveName.'")){
localstorage.setItem("'.$storageSaveName.'","'.session_id().'");
}else{
if(!localstorage.getItem("'.$storageSaveName.'")==="'.session_id().'"){
//ここは各自変更
location.href="https://example.com/session_id_unset.php";
}
}'
}
?>
<script><?=$script?></script>
session_id_unset.php
//sessionを処理するスクリプトは各自で作成お願いします。
一番手っ取り早い方法
これが一番と言えるものです。
session_regenerate_id();
これは、セッションIDを新しいものに変更する関数で、たったこの関数一つでできてしまうのが利点です。
しかも、(PHP5.1以降)現在のセッション情報は持続されます。また、引数「delete_old_session」をTRUEに設定することにより、古いセッションを削除してくれるという強力な利点があります(デフォルトFALSE)
最後に
この記事でサイトを見直していただくと嬉しいです!
セッションIDはもれそうにないところで漏れることがよくあります!そのためにも、自分のサイトを閲覧者目線で、侵入者目線?で覗いてみるといいかもしれません。
不適切な点、追記したいことなどがありましたらコメント等よろしくお願いします!