0

After a user logs in I am setting their $_SESSION['id'] to their id from the MySql database. This id auto increments so the first user to sign up will have the user id of 1.

Is this a secure way to handle this? Wouldn't an adversary be able to just set their $_SESSION['id'] to a random integer and potentially be logged in under someone else's account?

Here is my login.php file:

<?php
    require_once 'includes/header.php';

    if(isset($_POST['submit'])) {
        //  get the POST variables
        $username = $_POST['username'];
        $password = $_POST['password'];

        //  query the database
        $statement = $db->prepare('SELECT * FROM users WHERE username=?');
        $statement->execute(array($username));

        if($user = $statement->fetch()) {
            //  compare password hashes
            if(password_verify($password, $user['password'])) {
                //  successful authentication
                $_SESSION['id']
            }
        }
    }
?>
Samuel Cole
  • 521
  • 6
  • 24
  • See [here](https://stackoverflow.com/questions/29121112/how-to-implement-token-based-authentication-securely-for-accessing-the-website) and [here](https://coderwall.com/p/8wrxfw/goodbye-php-sessions-hello-json-web-tokens) – Henry Jun 26 '17 at 20:14
  • 1
    "Wouldn't an adversary be able to just set their $_SESSION['id'] to a random integer and potentially be logged in under someone else's account?" How do you envision they have control over it? The user's browser doesn't have any of the session data. – ceejayoz Jun 26 '17 at 20:16
  • 1
    To piggyback on ceejayoz, check https://stackoverflow.com/questions/5121766/can-a-user-alter-the-value-of-session-in-php to see how sessions work. It's not impossible but it's really hard to make sessions editable – J_D Jun 26 '17 at 20:18

2 Answers2

0

Your assumption is correct, using an incremental number to link to a security session is not secure. Instead of relying on predictable values, use something truly random and unguessable such as a UUID (aka GUID), which you can call from this function or use the function in the comments to generate your own UUID without relying on a COM object, which is usually Windows only.

http://php.net/manual/en/function.com-create-guid.php

If you generate this in your PHP code and then insert it into your database, you'll never have a collision.

TravisO
  • 9,406
  • 4
  • 36
  • 44
  • You didn't read the question carefully. He is not setting the session id, just a session variable. There is no problem with doing that. – gview Jun 26 '17 at 20:28
0

There are some security and scalability concerns regarding to sessions.

Focusing only on security:

  • Sessions managed by PHP, by default consist on an arbitrary identifier (sent via cookie) and information linked to that cookie (stored in the server) so you are not coding user information into that cookie (good).
  • $_SESSION map will store information only in server side, so that information is private and safe (unless you explicitly do something like print_r($_SESSION) ). Storing a user_id is correct.
  • Check that your query is returning 1 and only 1 record in the resultset: some SQL injection attacks could manipulate your query to match several users.
  • The first row in your users table, should be a user without privileges: if someone can inject SQL code, the query could match all users and the statement 'SELECT * FROM users WHERE username=?' tipically will return the first user inserted and you DONT want that user to be the admin.
  • Setup a reasonable expiration time for that cookie (by default PHP expiration time is 24min)
  • Your code should call session_start() before manipulating $_SESSION
  • Since PHP7 session_start() accept the parameter options to control lots of sessions configurations: http://php.net/manual/es/session.configuration.php
  • Do not pass session id (the cookie content) via GET query param
  • Try to generate session ids as impredecible as possible
  • Configure cookie as restrictive as possible (http only, current domain only, etc)
  • By default, session information is stored in files, so if you deploy your service in several machines, you should take that into account.

Other important points:

  • Send user and password via POST (GET method will leave your user and passwords in Apache logs, http load balancers, http proxies, etc)
  • Use HTTPS to create sessions but also the rest of the navigation (at least until logout)
  • Validate input variables length.
  • If you store information in $_SESSION building the key with user input: validate user input.
  • Always: validate user input.
Fulldump
  • 783
  • 5
  • 10
  • Do I need to worry about SQL injection if I use prepared statements? I thought the whole point is that they can't escape from a prepared statement. – Samuel Cole Jun 27 '17 at 16:38