Search code examples
authenticationphpcookiessession-managementsecure-coding

I want to figure out how cookies/ session variables interact to validate a user session


---I have been experimenting on cookies/ session ids and have a little trouble digesting in the concepts. I'm working on a Debian distro. Using Burp to capture/alter requests/ responses. What I know is below.

a. Cookies get stored in the client machine database at /root/.mozilla/firefox/pya18ecc.default/cookies.sqlite. In the moz_cookies table. I'm using sqlite3 to access the database.

b. Session variables are getting stored in /var/lib/PHP5 on the server.

The PHP code on the SERVER is below

<?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. When I send in the request(1), it lookes like this.

request(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. The response(1) is a login page (Basic HTTP authentication)

response(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

----Till here there has no exchange of session ids or cookies. (If I'm wrong, prompt me ?)

  1. I responded with the username and password and the request(2) is

request(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

---- On forwarding the above request what I observe is that I've received the Session id: cl5mi7tbhdnobpv8kkau7thjo6 in the /var/lib/PHP5 even before forwarding the response(2). That's because Server has created the same and is ready to fowrward it in the response (2)

  1. The response(2) is

response(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>

----Now on checking SELECT * FROM moz_cookies, I'm not seeing any cookies which are getting saved on the client m/c. So where are they getting saved ? (This is my first question)

  1. Next I've deleted the session variable "cl5mi7tbhdnobpv8kkau7thjo6" from the server and again have hit the refresh button on the client's browser. The request(3)/ response(3) are below

request(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

response(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>

-----Now the Server has again got the same session variable set under the /var/lib/PHP5. Shouldn't the server not recognize the session variable ? Also if this is happening because of the saved Cookies, then why isn't I'm able to see them under moz_cookies table ..... Please explain ?(This is my second question)


Solution

  • Till here there has no exchange of session ids or cookies. (If I'm wrong, prompt me ?)

    No, that's correct. Until here, session_start hasn't been called, so there are no session cookies to exchange.

    Now the Server has again got the same session variable set under the /var/lib/PHP5. Shouldn't the server not recognize the session variable ?

    It probably should, but it isn't. What I think is happening: When a client sends a session id, the server is happy to use it, even if it doesn't know it yet. This can (in theory) be used for session fixation, which is why it is recommended to regenerate ids each time something in the session changes (in practice, session.use_trans_sid is set to 0 by default, which makes session fixation less of an issue).

    What I find odd is that the data is also still there (I couldn't replicate this behavior). My guess would be that you are actually re-submitting the form?

    Also if this is happening because of the saved Cookies, then why isn't I'm able to see them under moz_cookies table

    My guess is that the cookies are still in the browser memory. Did you try the same thing, but deleting the cookie via the browser interface?

    Misc

    I know that this is just a test script, but still:

    • prepared statements are recommended over simple escaping.
    • don't store plaintext passwords in sessions).
    • don't echo user input unsanitized.
    • hashes should be user specific, not site specific.
    • htmlentities protects against XSS, not SQL injection, and should thus be applied when echoing data, not when inserting it into the database.