セッションのワンタイムチケット法とは?

このQ&Aのポイント
  • セッションのワンタイムチケット法は、ウェブアプリケーションのセキュリティ強化のために使用される方法です。
  • この方法では、ユーザーごとに一意のチケットを生成し、セッションに保存します。
  • フォームなどでデータを送信する際には、このチケットをhiddenフィールドなどで送信し、受け取った側でチケットの正当性を検証します。
回答を見る
  • ベストアンサー

セッションのワンタイムチケット法について

ある本に、セッションのワンタイムチケット法として以下のように書かれていました。 $ticket = md5(uniqid(mt_rand(), TRUE)); $_SESSION['ticket'] = $ticket; <input type="hidden" name="ticket" value="<?php echo$ticket; ?>" /> $ticket = $_POST['ticket']; $halfticket = $_SESSION['ticket']; if (!isset($ticket)) { die("不正な操作が行われました。"); } elseif ($ticket != $halfticket) { die("不正な操作が行われました。"); } そこで教えて頂きたいのですが、hiddenで渡したとしても、ソースコードを確認すれば$ticketの値は分かってしまいます。 むしろ逆に相手に教えてしまっているのではと思うのですが、これはどういう事なのでしょうか? 何かこの他に処理をして実装する必要があるのでしょうか?

  • PHP
  • 回答数3
  • ありがとう数0

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

ソースコードを見るかぎり、$ticketの値は暗号的な強度のある乱数なのでソースコードをいくら確認した所でその値はわかりません。mt_randとuniqidのマニュアルを確認してみてください。 PHPのversion 4.2.0以降だとmt_randは自動的にシードされます。よって、mt_randの結果はたとえ初めて実行したとしても毎回違う値が返ってきます。また、uniqidでマイクロ秒単位の現在時刻に基づき、mt_randが作った乱数を頭に持つユニークなIDを作っています。つまり、この時点でmt_randの乱数+その他のエントロピーが入ったマイクロ秒を元にしたIDとなっており、予測が難しい値になっています。これをMD5でハッシュ値をとっているので次にどんな値が$ticketに入るかを推測することは非常に困難です。 というわけで、ソースコードを読んだら暗号強度のある乱数値が$ticketに入っていることはわかりますが、具体的に何の値が入っているかはまず予測できないことがわかります。惜しむらくは強衝突耐性が疑われているMD5ではなく、SHA256あたりを使うと更に強い$ticketになると思います。

その他の回答 (2)

  • shimix
  • ベストアンサー率54% (865/1590)
回答No.3

ANo.1さんに補足 ブラウザからticketとセッションID(Cookie)が送られますよね。受け取ったサーバは、POSTで送られてきたと、セッションIDで紐付いているセッション変数のticketを照合します。 #ここで大事なのは、ticketが「ワンタイム」ということです.。 照合して処理が終わったら、$_SESSION['ticket']はクリアしますし、次にticketが必要な局面では別の値が再発行されます。 なのでticketだけを取り出して悪用しようとしても、その時点でのセッション変数のticketはすでに存在しないか他の値になっているので照合で不一致になります。

  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.1

>hiddenで渡したとしても そのチケット自体は公開キーみたいなもんでしょ。 かりにhiddenのデータを取得して、別のところで使おうとしても その時には別のチケットが発行されているので問題ないのでは? かりそめにセッションのチケットと、ポストされたチケットが その時だけあえばいいのだから 結局セッションidだってクッキーやなにやらで読もうとすれば よめるのだから、同じことでしょ?

関連するQ&A

  • FireFoxでのセッションの挙動がおかしい

    PHP Version 5.1.6を使っています。 以下のようにして、ticketを作成して登録作業をするために フォームを作り実際に送信しました。 ですが$_SESSION['ticket']と$_REQUEST['ticket']の値が FireFox2.0だと違う値になって返ってきます。 IE6だと同じ値で正常に作動します。 そこでuniqid().mt_rand()の代わりに、固定の文字("kotei")など をセットしたらFireFox2.0でも同じ値で正常に動作しました。 time()だと同じ値の時と、違う値の時があってうまくいきませんでした。 これは何が原因なのでしょうか? session_start(); $_SESSION['ticket'] = md5(uniqid().mt_rand()); $ticket = htmlspecialchars($_SESSION['ticket'], ENT_QUOTES); print "<form method=post action=\"regist.php\">\n"; print "<input type=hidden name=\"action\" value=\"exec\">\n"; print "<input type=hidden name=\"ticket\" value=\"".$ticket."\">\n"; print "<input type=submit name=\"submit_button\" value=\"登録\">\n"; print "</form>\n";

    • 締切済み
    • PHP
  • php $_SESSIONで値が消える。

    いつもお世話になり誠にありがとうございます。 標記の件。 インプット画面ー>確認画面ー>戻るー>インプット画面 インプット画面に戻った時、どうしても最初のインプット画面で打った内容が消えてしまいます。 プログラムを診て、誤りを指摘して頂けないでしょうか? どうぞよろしくお願い致します。           記 <?php session_start(); $mode = 'input'; if( isset($_POST['back']) && $_POST['back'] ){ //何もしない } else if( isset($_POST['confirm']) && $_POST['confirm'] ){ $_SESSION['name'] = $_POST['name']; $_SESSION['email'] = $_POST['email']; $_SESSION['category']= $_POST['category']; $_SESSION['message'] = $_POST['message']; $mode = 'confirm'; } else if( isset($_POST['send']) && $_POST['send'] ){ $mode = 'send'; } else { $_SESSION['name'] =""; $_SESSION['email'] =""; $_SESSION['category']=""; $_SESSION['message'] =""; } ?> <!DOCTYPE html> <html lang="ja"> <head> </head> <body> <div class="v_line_fix"> <h1>Blog K・T</h1> <h2><a href="index.html">トップページ</a></h2> <?php if( $mode=='input'){ ?> <form method=post> お名前(ニックネーム)<br> <input type="text" name="name" value="<?php echo $_SESSION['name'] ?>"><br> Eメール<br> <input type="email" name="email" value="<?php echo $_SESSION['email'] ?>"><br> カテゴリー<br> <input type="text" name="category" value="<?php echo $_SESSION['category'] ?>"><br> 本文<br> <textarea style="font-size:1.5em;" cols="30" rows="80" name="message"><?php echo $_SESSION['message'] ?></textarea><br> <input type="submit" name="confirm" value="確認" /> </form> <?php }else if( $mode=='confirm'){ ?> <!--確認画面--> <form method="post"> <?php echo $_SESSION['name']?><br> <?php echo $_SESSION['email']?><br> <?php echo $_SESSION['category']?><br> <br> <?php echo nl2br($_SESSION['message'])?><br> <input type="submit" name="back" value="戻る"/> <input type="submit" name="send" value="送信"/> } </form> <?php } else { ?> <!--完了画面--> <?php } ?> </body> </html>

    • ベストアンサー
    • PHP
  • PHPセッションIDの変更

    お世話になります。 phpでのセッションIDの変更の処理(セッションの中身も初期化する)がうまくいかず困っております。 以下のようなコードでセッションの管理をしているのですが。。 現象としては、最初に発行したセッションIDを保持したクッキーが削除されていない。 下記のコードの中の2度目にsession_start()を実行している 部分の後のセッションIDを見ると 新しいIDになっているがブラウザのクッキーのセッションIDは 古いIDのまま。 という現状です。 どなたか、原因が判る方、ご教示頂ければ幸いです。 宜しくお願いします。 ------------------------------ session_start(); //セッションクッキーを破棄・ if (isset($_COOKIE[session_name()])) {   setcookie(session_name(), '',time()-42000, '/'); } //セッションを完全に破棄・ if('' != ($myid = session_id())){   $_SESSION = array(); //セッション変数を初期化・   session_destroy(); } session_id(md5(uniqid(rand(), true))); //新しいセッションID session_start(); $_SESSION['userid'] = 'hoge'; -------------------------------------------------

    • 締切済み
    • PHP
  • セッションについて教えてください。

    PHPを独学で勉強中の初心者です。(HTMLとCSSくらいしか分からない所からのスタートです) ログインフォーム→パスワード処理→コンテンツ表示というながれで作っています。 質問は、セッションの有効期限はデフォルトではブラウザを閉じるまでと聞いたのですが、それはウインドウを閉じるではなく、アプリケーションを終了するまでということでよいのでしょうか?ウインドウを閉じただけだと、コンテンツを表示できてしまいます。 また、コードがこんなんでよいものかアドバイスよろしくお願い致します。 --パスワード処理-- <?php session_start(); $id =p; $password =11; $n_id = $_POST["n_id"]; $n_password = $_POST["n_password"]; if(($n_id == $id ) && ($n_password == $password)){ $_SESSION['pass'] = 1; header("Location: page1.php"); }else{echo "IDまたはパスワードが違います。"; } ?> ----コンテンツページ----- <?php session_start(); if(isset($_SESSION["pass"]) && $_SESSION["pass"] == 1){ echo "コンテンツ"; echo "<html><head> <meta http-equiv=Content-type content=text/html; charset=EUC-JP> </head><body>"; echo "<form action =logout.php method=post>"; echo "<input type=submit name=sbm value=ログアウト>"; echo "</form></body></html>"; }else{ header("Location:login1.php"); } ?>

    • 締切済み
    • PHP
  • sessionが分かりにくいです

    try4.html <html xmlns="http://www.w3.org/1999/xhtml" lang="ja" xml:lang="ja"> <head> <title>カンタンアンケート</title> </head> <body> <form action='try4-2.php' method='GET'> 性別:<br> <input type="radio" name="gender" value=0>男性 <input type="radio" name="gender" value=1>女性<br><br> 趣味(複数選択可):<br> <input type="checkbox" name="movies" value=1>映画  <input type="checkbox" name="music" value=1>音楽  <input type="checkbox" name="books" value=1>読書  <input type="checkbox" name="sports" value=1>スポーツ<br><br> ご意見をお書きください:<br> <textarea name="comment" rows="4" cols="40"></textarea><br><br> <input type="submit" value="送信"> <input type="reset" value="リセット"><br><br> </form> </body> </html> ////////////////////////////////////////////////////// try4-1.php <?php session_start(); ?> <html> <head><title>try4-1.php</title></head> <body> <?php $_SESSION = array(total_cnt => 0, male => 0, female => 0, movies => 0, music => 0, books => 0, sports => 0, comment => array("")); ?> //////////////////////////////////////////////////////////////// try4-2.php <?php session_start(); ?> <html> <head><title>try4-2.php</title></head> <body> <?php if ($_GET['gender'] == 0) ++$_SESSION['male']; elseif ($_GET['gender'] == 1) ++$_SESSION['female']; if ($_GET['movies']) ++$_SESSION['movies']; if ($_GET['music']) ++$_SESSION['music']; if ($_GET['books']) ++$_SESSION['books']; if ($_GET['sports']) ++$_SESSION['sports']; $_SESSION['comment'][] = $_GET['comment']; ++$_SESSION['total_cnt']; ?> 登録しました。さらに<A href="try4.html">入力する</A><br> これまでの集計結果を<A href="try4-3.php">表示する</A><br> </body> </html> ////////////////////////////////////////////////////////// try4-3.php <?php session_start(); ?> <html> <head><title>try4-3.php</title></head> <body> <?php echo "これまでにアンケートに応えたのは{$_SESSION['total_cnt']}人です。そのうち<br>"; if ($_SESSION['total_cnt']){ $male_rate = (int)($_SESSION['male'] / $_SESSION['total_cnt'] * 100); $female_rate = (int)($_SESSION['female'] / $_SESSION['total_cnt'] * 100); } else { $male_rate = 0; $female_rate = 0; } echo "男性:{$_SESSION['male']}人 $male_rate %<br>"; echo "女性:{$_SESSION['female']}人 $female_rate %<br><br>"; echo "趣味は映画:{$_SESSION['movies']}人、音楽:{$_SESSION['music']}人、読書:{$_SESSION['books']}人、" . "スポーツ:{$_SESSION['sports']}人<br><br>"; echo "意見:<br>"; foreach ($_SESSION['comment'] as $comment) echo $comment . "<br>"; ?> 集計を<A href="try4-1.php">初期化する</A><br> さらに<A href="try4.html">入力する</A><br> </body> </html> //////////////////////////////////////////////////////// とファイルが4つあるのですがセッション情報はどこに格納されているのでしょうか。TXTファイルでもなさそうなので教えて下さい。

    • ベストアンサー
    • PHP
  • PHPのセッションについて

    PHPのセッションについて 現在ログインフォームを作成しているのですが、 ログインフォームからIDとパスワードを送信して、合っていれば セッションを発行してロケーションで飛ばそうと思っているのですが、 初回時にIDとパスワードを入力して送信しても、セッションが引き継がれず 2回目以降だとセッションが引き継がれる症状に悩んでおります。 どなたかご教授ください。 宜しくお願いいたします。 【login.php】-------------------------------- <?php session_name("stock"); session_start(); $error_flag = 0; if(isset($_POST["login"])){ $id = htmlentities($_POST["id"],ENT_COMPAT); $password = trim(htmlentities($_POST["password"],ENT_COMPAT)); if($login_id == $id && $login_pass == $password){ $_SESSION["id"] = $id; $_SESSION["password"] = $password; header("Location:stock.php"); exit; }else{ $error_flag = 1; } } echo <<<EOD <form method="post" action="login.php" id="login"> <input type="text" name="id" id="id" > <input type="password" name="password" id="password"> <input type="submit" name="login" value="ログイン" /> </form> EOD; 【stock.php】--------------------------------- <?php session_name("stock"); session_start(); echo $_SESSION["id"]; echo $_SESSION["password"]; ?>

    • ベストアンサー
    • PHP
  • php $_SESSIONでデータが残らない。

    いつもお世話になり誠にありがとうございます。 標記の件。 インプット画面ー>確認画面ー>戻るー>インプット画面 インプット画面に戻った時、どうしても最初のインプット画面で打った内容が消えてしまいます。 プログラムを診て、誤りを指摘して頂けないでしょうか? 今度はCSSなども書きます。 どうぞよろしくお願い致します。 記 <?php session_start(); $mode = 'input'; if( isset($_POST['back']) && $_POST['back'] ){ //何もしない } else if( isset($_POST['confirm']) && $_POST['confirm'] ){ $_SESSION['name'] = $_POST['name']; $_SESSION['email'] = $_POST['email']; $_SESSION['category']= $_POST['category']; $_SESSION['message'] = $_POST['message']; $mode = 'confirm'; } else if( isset($_POST['send']) && $_POST['send'] ){ $mode = 'send'; } else { $_SESSION['name'] =""; $_SESSION['email'] =""; $_SESSION['category']=""; $_SESSION['message'] =""; } ?> <!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <meta http-equiv="content-type" content="text/html" charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>ブログ</title> <meta name="description" content="このWebサイトは、初めてHTMLで作るブログページです。"> <link rel="stylesheet" href="./css/style.css"> <style> body{ width: 100%; max-width: 800px; margin-top: auto; margin-left: auto; margin-right: auto; background-color: rgb(71, 133, 157); padding: 10px; text-align: center; } div{ background-color: rgb(247, 248, 245); padding: 2em; } script{ margin-top: 12em; } p { margin-left: 2em; text-align: left; font-size: 25px; font-weight: bold; color: rgb(10, 10, 10); } form { font-size: 25px; font-weight: bold; color: blue; } input { font-size: 25px; margin:auto; } </style> </head> <body> <div class="v_line_fix"> <h1>Blog K・T</h1> <h2><a href="index.html">トップページ</a></h2> <?php if( $mode=='input'){ ?> <form method=post> お名前(ニックネーム)<br> <input type="text" name="name" value="<?php echo $_SESSION['name'] ?>"><br> Eメール<br> <input type="email" name="email" value="<?php echo $_SESSION['email'] ?>"><br> カテゴリー<br> <input type="text" name="category" value="<?php echo $_SESSION['category'] ?>"><br> 本文<br> <textarea style="font-size:1.5em;" cols="30" rows="80" name="message"><?php echo $_SESSION['message'] ?></textarea><br> <input type="submit" name="confirm" value="確認" /> </form> <?php }else if( $mode=='confirm'){ ?> <!--確認画面--> <form method="post"> <?php echo $_SESSION['name']?><br> <?php echo $_SESSION['email']?><br> <?php echo $_SESSION['category']?><br> <br> <?php echo nl2br($_SESSION['message'])?><br> <input type="submit" name="back" value="戻る"/> <input type="submit" name="send" value="送信"/> } </form> <?php } else { ?> <!--完了画面--> <?php } ?> </body> </html>

    • ベストアンサー
    • PHP
  • hiddenによるセッション管理について。

    hiddenによるセッション管理について。 セッション管理にクッキー利用、URLライティング、hiddenによる3つの方法があると聞きました。 今まではクッキー利用によるセッション管理だったのですが、使えない場合も出てくることを考えて他の方法を試してみようと思いました。 質問1. URLライティングはリンクによる実行時のみ有効という認識でよいのでしょうか。submitによる実行はクッキーまたはhiddenによる方法しか使えないと考えてよいのでしょうか。 質問2. 下記のようにセッションIDをhiddenでサーバに送信しようとしたのですが、サーバ側でも何か処理が必要なのでしょうか。 <input type="hidden" name="jsessionid" value="<%=session.getId()%>" /> 想定ではクッキーの場合と同じくサーバ側でよろしくやってくれるのかと思ったのですが、実際に実行してみるとうまくセッションが引き継がれません。 そこでサイトを探していたところ下記のような記述を見つけました。 「HttpSessionとは異なり、HIDDENパラメータの埋め込みやパラメータの解析などの処理を、開発者が実装する必要があります。」 「HIDDENパラメータの埋め込み」というのは上記の記述になると思うのですが、パラメータの解析というのをサーバ側のプログラム(strutsを利用していますので、アクションやサーブレット?)で何か処理が必要なのでしょうか。 いまはクッキー利用と同じく下記のようにしてしまっていますが、たぶんこの記述を何かに変えないといけないのかなと思っています。 HttpSession session = req.getSession(); hiddenによる実際のサンプルコードをいま探しているところなのですが、いまのところ見つかっていません。 もしよろしければアドバイスをいただけると助かります。

    • ベストアンサー
    • Java
  • クッキーを使わないセッションPHP

    を作ったのですがまずい点があったら教えて下さい 入力を一行ずつ並べるものです <?php session_name('asdsddzddzfssd'); session_start(); session_register('lines'); $self=$_SERVER['PHP_SELF'].'?'.htmlspecialchars(SID); $line=isset($_POST['line'])?htmlspecialchars($_POST['line']):''; if($line!='')$_SESSION['lines'] .= $line.'<br/>'; echo' <form action="'.$self.'" method="post"> <p>1行: <input name="line"/></p> </form> 過去の全行:<br/>'.$_SESSION['lines']; ?>

    • ベストアンサー
    • PHP
  • セッションを使ったログインページでのエラー

    前にもセッションを使ったログインページについて質問したものです。 上記の通りセッションを使ったログインページを作っております。 前回このソースを載せたときセキュリティー的にとても危険だというご意見をいただきました。何分まだ初心者ですのでどうかご了承ください。 ソース /*ログインのページは省略しました。ログイン後ID・パスワードが正しいか、そして訪問者がログインせずにこのページに直接アクセスした際にログインページにジャンプするようにするようにするプログラムです*/ <?PHP if (!isset($user) || !isset($pass)) { header( "Location: loginPage.php" ); } elseif (empty($user) || empty($pass)) { header( "Location: loginPage.php" ); } else { $user = addslashes($_POST['username']); $pass = md5($_POST['password']); $dbHost = "localhost"; $dbUser = "*****"; $dbPass = "*****"; $dbDatabase = "mysql"; $db = mysql_connect("$dbHost", "$dbUser", "$dbPass") or die ("Error connecting to database."); mysql_select_db("$dbDatabase", $db) or die ("Couldn't select the database."); $result=mysql_query("select * from users where username='$user' AND password='$pass'", $db); $rowCheck = mysql_num_rows($result); if($rowCheck > 0){ while($row = mysql_fetch_array($result)){ session_start(); session_register('username'); echo 'Success!'; header( "Location: checkLogin.php" ); } } else { echo 'Incorrect login name or password. Please try again.'; } } ?> このようなプログラムを作ったのですが、ちゃんとパスワードをいれても、ちゃんと認証されずに、ログインのページ戻されてしまいます。 おそらく if (!isset($user) || !isset($pass)) { header( "Location: loginPage.php" ); } elseif (empty($user) || empty($pass)) { header( "Location: loginPage.php" ); } の部分がおかしいのかと思いますがどう変えたら良いのかよく分かりません。また、おかしいと思った部分を削除したら普通にログインはできるのですが、今度は一度ログインしても他のページに移動した後もう一度このページに行くと、もう一度ログインしないとアクセスできなくなりました。 まとめると、お聞きしたいことは、2つです。 (1)紹介したのプログラムでログインしてもちゃんとログインが認証されない。これを解消するにはどうすればいいのか? (2)ユーザーがログインした後もう一度このページにアクセスした場合もう一度ログインさせなくてもいいようにすればどうすればよいのか。 もし可能でしたら、解決するためのプログラムを(さらに可能でしたら紹介したプログラムを生かした形で)添えてアドバイスしていただけないでしょうか?よろしくお願いいたします。

    • ベストアンサー
    • PHP

専門家に質問してみよう