4
3

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 3 years have passed since last update.

【PHP】SESSIONも危ない!セキュリティを見直そう。

Last updated at Posted at 2019-11-16

初めに

みなさんは、

session_start();

だけでセッションを利用していませんか?もし、この一行だけでsessionを使用しているのなら、直ちに変更したほうがいいでしょう。

どこが危ないのか

セッションの仕組みをもう一度確認してみましょう。
まず、サーバーが初アクセスのプレイヤーにクッキーでIDを作成し保存します。
そのあと、セッションIDをアクセス毎に確認し、保存データからHTML等を生成します。

ここで注意する点が、Cookieでsessionidを保存するということです。
Cookieとは、クライアント側で変更可能(ほとんどのブラウザで可能)なため、友人のsessionidを盗めばログインもできてしまいますし保存データもすべてアクセスできてしまいます。

つまり、ほとんどのサイトがsessionにログインデータを保存しているので、ユーザーを識別するためのsessinidが盗まれてしまえば保存されているデータも盗まれるということになりますし、メモサイトであればメモのデータを変更さえ削除さえできてしまいます。

簡単な事例としては、パソコンを教えに来た(ミラサポのようなサービス)人がデータを盗むのは簡単でしょう(そこまでの悪事を働く人はそういないと思いますけども)。

対策しているサイト/していないサイト

対策しているサイト/していないサイトを独自で調べたのでまとめます。

サイト/サービス名 ドメイン名 対策
Google 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はもれそうにないところで漏れることがよくあります!そのためにも、自分のサイトを閲覧者目線で、侵入者目線?で覗いてみるといいかもしれません。
不適切な点、追記したいことなどがありましたらコメント等よろしくお願いします!

4
3
0

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
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?