我想弄清楚cookie /会话变量如何交互以验证用户会话

时间:2015-03-28 08:23:24

标签: authentication php cookies session-management secure-coding

---我一直在尝试使用cookies / session ID,并且在概念中消化有点麻烦。  我正在使用Debian发行版。使用Burp捕获/更改请求/响应。我所知道的是下面的内容。

一个。 Cookie存储在客户端计算机数据库/root/.mozilla/firefox/pya18ecc.default/cookies.sqlite中。在moz_cookies表中。我使用sqlite3来访问数据库。

湾会话变量存储在服务器上的/ var / lib / PHP5中。

SERVER上的PHP代码位于

之下
<?php
require_once 'login.php';

$connection = new mysqli($db_hostname,$db_username,$db_password,$db_database);
if($connection->connect_error) die ($connect->connect_error);

if (isset($_SERVER['PHP_AUTH_USER']) &&
   isset($_SERVER['PHP_AUTH_PW']))
    {
        $username = mysql_entities_fix($connection,$_SERVER['PHP_AUTH_USER']);
        $password = mysql_entities_fix($connection,$_SERVER['PHP_AUTH_PW']);

        $query = "SELECT * FROM user WHERE username = '$username'";

        $result = $connection->query($query);

        if(!$result) die ($connection->error);
        elseif ($result->num_rows) 
        {
            $row = $result->fetch_array(MYSQLI_NUM);    
            $result->close();
            $salt1="!@#$";
            $salt2="$#@!";
            $token = hash('ripemd128',"$salt1$password$salt2"); 

            if($token == $row[3])
                {
                    session_start();
                    $_SESSION['username'] = $username;
                    $_SESSION['password'] = $password;
                    $_SESSION['forename'] = $row[0];
                    $_SESSION['surname'] = $row[1];
                        echo "$row[0] $row[1] : Hi '$row[0]' you are logged
                            in as '$row[2]'";
                    die("<p><a href = continue.php> CLICK HERE TO CONTINUE</a></p>");
                }
            else    {die("Invalid Username/ Password Combination");}            
        }
        else
            {
                die("Invalid Username/ Password Combination");
            }
    }
else
    {
            header('WWW-Authenticate: Basic realm="Restricted Section"');
                header('HTTP/1.0 401 Unauthorized');
                die("Please enter your username and password to Login");
    }
    $connection->close();
function mysql_entities_fix($connection,$var)
    {
        return htmlentities(mysql_entities_string($connection,$var));
    }
function mysql_entities_string($connection,$var)
    {
        if (get_magic_quotes_gpc()) $var = stripslahes($var);
        return $connection->real_escape_string($var);

    }
?>
  1. 当我发送请求(1)时,它看起来像这样。
  2. 请求(1)

     GET /ses3.php HTTP/1.1
     Host: 127.0.0.1
    User-Agent: Mozilla/5.0 (X11; Linux i686;      rv:31.0) Gecko/20100101 Firefox/31.0 Iceweasel/31.5.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-US,en;q=0.5
    Accept-Encoding: gzip, deflate
    Connection: keep-alive
    
    1. 响应(1)是登录页面(基本HTTP身份验证)
    2. 响应(1)

      HTTP/1.0 401 Unauthorized
      Date: Sat, 28 Mar 2015 07:27:44 GMT
      Server: Apache/2.2.22 (Debian)
      X-Powered-By: PHP/5.4.36-0+deb7u3
      WWW-Authenticate: Basic realm="Restricted Section"
      Vary: Accept-Encoding
      Content-Length: 48
      Connection: close
      Content-Type: text/html
      
      Please enter your username and password to Login
      

      ----直到这里没有会话ID或cookie的交换。 (如果我错了,请提示我?)

      1. 我回复了用户名和密码,请求(2)是
      2. 请求(2)

        GET /ses3.php HTTP/1.1
        Host: 127.0.0.1
        User-Agent: Mozilla/5.0 (X11; Linux i686; rv:31.0) Gecko/20100101 Firefox/31.0     Iceweasel/31.5.0
        Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
        Accept-Language: en-US,en;q=0.5
        Accept-Encoding: gzip, deflate
        Connection: keep-alive
        Authorization: Basic YnNtaXRoOm15c2VjcmV0
        

        ----在转发上述请求时,我观察到的是,即使在转发响应(2)之前,我还是在/ var / lib / PHP5中收到了会话ID:cl5mi7tbhdnobpv8kkau7thjo6。这是因为服务器 已创建相同的,并准备在响应(2)

        中发现它
        1. 响应(2)是
        2. 响应(2)

          HTTP/1.1 200 OK
          Date: Sat, 28 Mar 2015 07:36:13 GMT
          Server: Apache/2.2.22 (Debian)
          X-Powered-By: PHP/5.4.36-0+deb7u3
          Set-Cookie: PHPSESSID=cl5mi7tbhdnobpv8kkau7thjo6; 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
          Vary: Accept-Encoding
          Content-Length: 117
          Keep-Alive: timeout=5, max=100
          Connection: Keep-Alive
          Content-Type: text/html
          
          Bill Smith : Hi 'Bill' you are logged
                                       in as 'bsmith'<p><a href = continue.php> CLICK HERE TO CONTINUE</a></p>
          

          ----现在检查SELECT * FROM moz_cookies,我没有看到任何在客户端m / c上保存的cookie。那么他们在哪里得救了? (这是我的第一个问题)

          1. 接下来我删除了会话变量&#34; cl5mi7tbhdnobpv8kkau7thjo6&#34;从服务器再次打击了 客户端浏览器上的刷新按钮。请求(3)/响应(3)在
          2. 之下

            请求(3)

            GET /ses3.php HTTP/1.1
            Host: 127.0.0.1
            User-Agent: Mozilla/5.0 (X11; Linux i686; rv:31.0) Gecko/20100101 Firefox/31.0 Iceweasel/31.5.0
            Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
            Accept-Language: en-US,en;q=0.5
            Accept-Encoding: gzip, deflate
            Cookie: PHPSESSID=cl5mi7tbhdnobpv8kkau7thjo6
            Authorization: Basic YnNtaXRoOm15c2VjcmV0
            Connection: keep-alive
            Cache-Control: max-age=0
            

            回应(3)

            HTTP/1.1 200 OK
            Date: Sat, 28 Mar 2015 07:50:01 GMT
            Server: Apache/2.2.22 (Debian)
            X-Powered-By: PHP/5.4.36-0+deb7u3
            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
            Vary: Accept-Encoding
            Content-Length: 117
            Keep-Alive: timeout=5, max=100
            Connection: Keep-Alive
            Content-Type: text/html
            
            Bill Smith : Hi 'Bill' you are logged
                                        in as 'bsmith'<p><a href = continue.php> CLICK   HERE TO CONTINUE</a></p>
            

            -----现在,服务器再次在/ var / lib / PHP5下设置了相同的会话变量。服务器不应该识别会话变量吗?如果由于保存的Cookies而发生这种情况,那么为什么我无法在moz_cookies表下看到它们.....请解释一下?(这是我的第二个问题)

2 个答案:

答案 0 :(得分:2)

需要考虑的几个方面:

  1. Cookie可以存储在磁盘或内存中。它们的存储方式取决于浏览器设置(例如Firefox中的私人浏览模式)和服务器设置(请参阅PHP docs on session handling)。

  2. 可以使用Keep-Alive标头缓存HTTP连接。

  3. 看起来您设置为在文件中将服务器上的会话ID存储,但浏览器cookie存储在内存而不是文件中,这就是您看到PHP文件而不是Firefox cookie的原因文件。

    至于为什么服务器正在识别会话ID,即使你删除了文件,看起来发生的事情是PHP知道会话已经过身份验证,这意味着它必须缓存在服务器上的RAM中。 (PHP大师可能能够填写会话机制的细节)。

    收到请求3后,PHP查找会话ID文件,当它没有看到它时,它再次写入文件,因为它知道会话有效。这是预期的行为,因为如果要删除会话,那么作为PHP程序员应该在PHP中执行此操作,而不是在后台删除会话ID文件。

    您会注意到客户端发送了带有请求3的会话ID。客户端将为每个请求发送会话ID cookie,但服务器不应在此会话期间再次使用Set-Cookie指令进行响应。浏览器现在具有会话ID cookie,并且可以随每个请求发送它,因此不需要进一步的身份验证。

    这种策略的弱点在于它可能会留下会话劫持的可能性。如果攻击者可以从您的浏览器获取会话ID cookie,他们可以使用您的凭据对服务器执行命令。

    根据许多因素,获取会话ID对攻击者来说可能是也可能不是一项微不足道的任务。例如,如果受害者的计算机受到攻击者控制的病毒或其他恶意软件的攻击,则攻击者可能会在此时关闭受害者的计算机,并可以执行他们想要的任何操作,包括获取会话ID。其他攻击使用跨站点脚本(XSS)攻击来欺骗受害者的浏览器泄露会话ID。

    对XSS和会话劫持有特定的防御,同样主题相当复杂,值得详细研究。例如,一个更安全的会话可能会使用随每个响应而更改的一次性令牌,尽管使用异步HTTP调用可能会使该策略变得复杂。

答案 1 :(得分:1)

  

直到这里没有会话ID或cookie的交换。 (如果我错了,请提示我?)

不,那是对的。在此之前,session_start尚未被调用,因此没有会​​话cookie可供交换。

  

现在,服务器再次在/ var / lib / PHP5下设置了相同的会话变量。服务器不应该识别会话变量吗?

它可能应该,但它不是。我认为发生了什么:当客户端发送会话ID时,服务器很乐意使用它,即使它还不知道它。这可以(理论上)用于session fixation,这就是为什么建议每次会话中的某些内容发生更改时重新生成ID(实际上,session.use_trans_sid默认设置为0 ,这使得会话固定不再是一个问题。)

我觉得奇怪的是数据仍然存在(我无法复制此行为)。我的猜测是你实际上是在重新提交表格吗?

  

如果因为保存的Cookies而发生这种情况,那么为什么我无法在moz_cookies表下看到它们

我的猜测是cookie仍在浏览器内存中。您是否尝试过相同的操作,但是通过浏览器界面删除了cookie?

<强>其它

我知道这只是一个测试脚本,但仍然是:

    建议使用
  • 准备好的语句而不是简单的转义。
  • 不要在会话中存储明文密码。
  • 不要回复用户输入未经过清理。
  • 哈希应该是特定于用户的,而不是特定于站点的。
  • htmlentities可以防止XSS,而不是SQL注入,因此应该在回显数据时应用,而不是在将数据插入数据库时​​应用。