2016-11-01 33 views
2

はじめ

以外行方不明:セッションは、これらの答えはすべてで私を助けていなかったが、彼らはこの質問時につまずく誰かを助けるかもしれない、私は「安全でない」クッキーを使用


私が破壊されている質問

私のピーナッツは昨日終わってしまった。自分のアプリケーションにログインするのは幸いなことだ。 SOに関するすべての有益な回答は、「セッションを開始しましたか?」の行に沿っています。 - 私は持っています。

私がログインすると、スクリプトが正しいステータスを返し、私に次のヘッダーを与える:

"Expires: Thu, 19 Nov 1981 08:52:00 GMT", 
"Cache-Control: no-store, no-cache, must-revalidate", 
"Pragma: no-cache", 
"Set-Cookie: ADMSESSION=f27n49icvbv0bjfgh4bffojgs0; path=\/; secure; HttpOnly" 

私はこのクッキーは私のブラウザで実際に存在し、クッキーのみときに終了していることを確認することができますブラウザが閉じます。

ここで魔法は起こりません。サーバから進行状況を受信すると、ローカルスクリプトは実際のバックエンドセッションをロードするためにページをリフレッシュします。少なくとも、それはそれがやるべきことです。スクリプトはページを再読み込みし、同じログインプロンプトでもう一度挨拶します。それは私を壁に追いやっている。

注意深い調査の結果、私のセッションクッキーはまったく使用されていないことが分かったので、私はそれを安全でないクッキー(Set-Cookie: ADMSESSION=f27n49icvbv0bjfgh4bffojgs0)に変更しました。このは、ユーザがログインする必要があるすべてのページで、のように動作しますが、ログインページではなく、それらのページでのみ動作します。論理的には同じ軌跡をたどるため、サーバーが処理を完全に完了するまでヘッダーは送信されないため、私は頭の中で頭を囲むことができません。


関連スニペット

は、ここでの設定とセッションを取得するロジック・フローおよび方法を説明するいくつかの関連するスニペットです。一部の情報は、セキュリティ目的のために編集されています。

<?php // index.php 

    /** 
    * just print everything, I want to know when, where, and how 
    * the brown sticky stuff starts hitting the ceiling whirly device. 
    */ 
    error_reporting(E_ALL); 
    ini_set("display_startup_errors", 1); 
    ini_set("display_errors", 1); 

    require_once "path/to/my/config.php"; 

    // session and login manager 
    require_once "path/to/my/SecurityService.php"; 

    use \Namespace\Of\My\SecurityService as LoginManager; 

    // argument false: don't log activity on this page. 
    $loginManager = new LoginManager(false); 

    // start session 
    $loginManager->secureSessionStart(); 

    // @fixme: secureSessionCheck is not fired!? 
    if($loginManager->secureSessionCheck()) { 
     print file_get_contents("path/to/views/main.html"); 
    } else { 
     print file_get_contents("path/to/views/login.html"); 
    } 

<?php // SecurityService.php:51-75 (inside login method called via POST) 
     if($this->verify($credentials["passwordHash"])) { 
      if($this->logger !== null) 
       $this->logger->write("info", "successful login from {$_SERVER["REMOTE_ADDR"]}."); 

      $_SESSION["browser"] = $_SERVER["HTTP_USER_AGENT"]; 
      // redacted 
      // redacted 
      $_SESSION["visitor"] = $_SERVER["REMOTE_ADDR"]; 
      // redacted 
      // redacted 
      // redacted 
      // redacted 
      // redacted 
      // redacted 
      // redacted 
      // redacted 
      // redacted 

      session_commit(); 

      if($this->logger !== null) 
       $this->logger->write("info", "User ({$_SESSION["email"]}) created in session (" . session_id() . ")."); 

      return true; 
     } 

<?php // SecurityService.php:92-127 
    /** 
    * secureSessionStart 
    * Starts a session in a secure way 
    */ 
    public function secureSessionStart() { 
     if(ini_set("session.use_only_cookies", 1) === FALSE) { 
      if($this->logger !== null) 
       $this->logger->write("error", "PHP ini is configured incorrectly. (session.use_only_cookies)"); 

      return; 
     } 

     switch(session_status()) { 
      case PHP_SESSION_DISABLED: 
       if($this->logger !== null) 
        $this->logger->write("error", "Sessions are disabled. Unable to log this user in!"); 
       return; 
      case PHP_SESSION_NONE: 
       session_set_cookie_params(0, "/", "", true, true); 
       session_name("ADMSESSION"); 
       session_start(); 
       break; 
      case PHP_SESSION_ACTIVE: 
       session_set_cookie_params(0, "/", "", true, true); 
       session_name("ADMSESSION"); 
       session_start(); 

       $oldID = session_id(); 

       session_regenerate_id(true); 

       if($this->logger !== null) 
        $this->logger->write("info", "Session ({$oldID}) moved to (" . session_id() . ")."); 
       break; 
     } 
    } 

<?php // SecurityService.php:118-189 
    /** 
    * secureSessionCheck 
    * Checks the current session if it"s valid with current data 
    * 
    * @return boolean 
    */ 
    public function secureSessionCheck() { 
     if(!isset($_SESSION)) { 
      if($this->logger !== null) 
       $this->logger->write("error", "Session is not set."); 

      return false; 
     } 

     if(!isset($_SESSION[/* redacted */]) || !isset($_SESSION["browser"]) || !isset($_SESSION["visitor"])) { 
      if($this->logger !== null) 
       $this->logger->write("error", "Session (" . session_id() . ") does not contain a valid administrator."); 

      return false; 
     } 

     if($_SESSION["browser"] !== $_SERVER["HTTP_USER_AGENT"]) { 
      if($this->logger !== null) 
       $this->logger->write("warning", "Session (" . session_id() . ") browser conflicts with current user agent."); 

      return false; 
     } 

     if($_SESSION["visitor"] !== $_SERVER["REMOTE_ADDR"]) { 
      if($this->logger !== null) 
       $this->logger->write("warning", "Session (" . session_id() . ") visitor conflicts with current visitor IP."); 

      return false; 
     } 

     // redacted (gets $this->data) 

     if(!isset($this->data)) { 
      if($this->logger !== null) 
       $this->logger->write("error", "Data object is not set."); 

      return false; 
     } 

     if(!isset($this->data->/* redacted */) || !isset($this->data->/* redacted */) || !isset($this->data->/* redacted */) || !isset($this->data->/* redacted */)) { 
      if($this->logger !== null) 
       $this->logger->write("error", "Data object does not contain a valid administrator."); 

      return false; 
     } 

     $compare = // redacted 
      // redacted 
      // redacted 
      // redacted 
      // redacted 
      // redacted 
      // redacted 
      // redacted 
     // redacted 

     $isValid = hash_equals($compare, $_SESSION[/* redacted */]); 

     if(!$isValid) { 
      if($this->logger !== null) 
       $this->logger->write("error", "Illegal session presented by {$_SERVER["REMOTE_ADDR"]}."); 

      return false; 
     } 

     return true; 
    } 

私のログのスニペット(一度ログイン後)

2016-11-01 09:18:55 – [info] Session (359hk6v83pc3a82b9tlbn79ch5) moved to (6g05qcg7pocaht66ru5gdq8di6). 
2016-11-01 09:18:55 – [info] successful login from 127.0.0.1. 
2016-11-01 09:18:55 – [info] User ([email protected]) created in session (6g05qcg7pocaht66ru5gdq8di6). 
2016-11-01 09:19:08 – [info] Session (6g05qcg7pocaht66ru5gdq8di6) moved to (jo0etnds61ip2ices59hrg1jl6). 

最後のスニペットの奇妙なことは、セッションを新しいIDに移動した後に何も記録しないということです。私は、少なくとも私のログに、以下の(Iは、ログインせずにアクセスページにしようとする場合のように)期待:2016-11-01 10:08:47 – [error] Session (jo0etnds61ip2ices59hrg1jl6) does not contain a valid administrator. - ログインページの奇妙な行動を...


質問と回答

Q:ブラウザのコンソールを確認しましたか?そこにHTTPSに関する警告がありますか?たぶん混在した内容の警告かそのようなものでしょうか? - CBroe
A:何もありません。ログインページは問題なくロードされ、サーバーにデータが送信され、サーバーは正しく応答します。 HTTPSに関するコンソールメッセージは見つかりません。ネットワーク・タブには、200以外のステータスも表示されません。ログインはPOSTリクエストを介して1回呼び出され、その後にページがリフレッシュされます。セッションクッキーを次のようにトレースすることができます:1(初期ロード) - >送信なし、1受信(071s21bdejg40supml9kamced5)。 2(ログインするPOST) - >送信していない、1を受信しました(813um7v1jjh3jsi57g5k8evm16) - これは問題ではありません。ユーザーは新しいセッションIDにログインする必要があります。 3(リロード) - > 1送信(071s21bdejg40supml9kamced5)、1受信(k5aa0o4k24v2cfc41qbleq04h4)...

実際の問題は送受信されたクッキーをチェックすることによって発見されました。この問題への修正はまだありません。問題

問題の


現在の理解は、私がCBroeさんのコメントを読んだ後に取った手順に基づいて求めました。

サーバーから間違ったセッションクッキーが返ってきたようですが、私はそれをsecureSessionStartの機能と見なすことができます。私はクッキーの設定をテスト目的で削除し、正しくログインしています。しかし、これは、スクリプトによってアクセスできないクッキーと安全なセッションを使用するという目的を全面的に破ってしまいます。私が単にsession_start()を使用すると、すべてがうまくいき、アプリケーションの実際のバックエンドが迎え入れることになります。 session_set_cookie_params(0, "/", "", true, true)を使用するたびに、ログインページが何度もポップアップします。


決勝思考

それはおそらくどこか欠けているセミコロンです。それは常にセミコロンがありません...

+1

ブラウザのコンソールを確認しましたか?そこにHTTPSに関する警告がありますか?たぶん混在した内容の警告かそのようなものでしょうか? – CBroe

+0

私は、犯人を見つけたと信じています。この問題を解決するためのアイデアを実装する際に質問を更新します。 – CytoDev

+0

@CBroe:見つかった実際の問題を反映するために質問を更新しました。 – CytoDev

答えて

1

明らかに、私のサーバーは安全なヘッダーを受信せず、これは再ロード時にログインセッションが失われていたようです。私は現在、セッションを設定する前に接続が保護されているかどうかをチェックすることでこれを修正しています。


免責

私はあなたのログイン要求を処理するために、安全でない接続を使用していないアドバイスをDO !同じ問題が発生している場合は、セッションクッキーで接続を切断する前に、接続が完全に保護されていることを確認してください。


現在修正

二つの小さな追加がセッションクッキーにドメイン名とセキュリティを追加するためにsecureSessionStart方法に行われました。接続が必ずであることを確認してください。これはテストの目的のみにしてください!

/** 
* get's the secure status from _SERVER 
* Also check against HTTP_X_FORWARDED and HTTP_X_FORWARDED_SSL because 
* some servers are behind load balancers. 
*/ 
$secure = (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] === "on") && ((!empty($_SERVER["HTTP_X_FORWARDED_PROTO"]) && $_SERVER["HTTP_X_FORWARDED_PROTO"] === "https") || (!empty($_SERVER["HTTP_X_FORWARDED_SSL"]) && $_SERVER["HTTP_X_FORWARDED_SSL"] === "on")); 

// also use _SERVER["SERVER_NAME"] to set the cookie to this domain only 
session_set_cookie_params(0, "/", $_SERVER["SERVER_NAME"], $secure, true); 

理想的な修正

は理想的な修正はそれを必要とするすべてのページにSSLを使用することです。現在作業しているドメインにはこの設定がありません。これを入力している間に修正しています。私は冗談でもない。ログインシステムを構築する前に、SSLを入手してください。

関連する問題

 関連する問題