19

I am developing my own application which requires user login. All users and passwords (encrypted) are stored in a database. When a user tries to login, then it search in the database the username and password. If all is ok, then I store username in $_SESSION["username"], user role (admin, author etc) in $_SESSION["role"] and user website in $_SESSION["website"] (I need website to be stored because the application is like "multisite" - my applicaton is hosted on client hosting but the administration is on my server).

I read this Can a user alter the value of $_SESSION in PHP? and I don't understand. Is this method secure (of storing data and if user is logged in) in a $_SESSION?

Can the user change the session content? (for example, if user is logged in and $_SESSION["website"] is "example.com", can the user change the session $_SESSION["website"] to "example.org" to ruin another website? If yes, how to avoid or what's the secure alternative of session?).

And please tell me what is session hijacking and how can this affect my site and also, how to make session_id dinamically to change?

Thank you so much!

Community
  • 1
  • 1
MM PP
  • 4,050
  • 9
  • 35
  • 61
  • 1
    No .. $_SESSION is saved in the server.. and $_COOKIE is saved at browser end. – kd0807 Jun 11 '15 at 05:44
  • 1
    Re session hijacking: http://stackoverflow.com/questions/12233406/preventing-session-hijacking – Drakes Jun 11 '15 at 05:45
  • 1
    Wait, you are storing encrypted passwords? – Ismael Miguel Jun 11 '15 at 08:21
  • @IsmaelMiguel I am not storing passwords in session. All passwords are stored encrypted in DB. – MM PP Jun 11 '15 at 08:21
  • 1
    But you are storing encrypted passwords in a database? – Ismael Miguel Jun 11 '15 at 08:22
  • 1
    That's what I meant. Please, take down the encryption and use an hash function, like `sha1`, with a salt. You may want to look at the `password_hash` function (http://php.net/manual/en/function.password-hash.php). You then either verify if the hash is the same (by re-hashing and checking with `===`) or, depending on your PHP version and what hash function you used, you can use the function `password_verify` (http://php.net/manual/en/function.password-verify.php) – Ismael Miguel Jun 11 '15 at 08:25
  • 1
    @IsmaelMiguel can you tell me if is unsecure what I am using: the password is stored in database by making md5(sha1("here comes the password")); . Then, when the user tries to login, the password from the password field is verified in db, by md5(sha1()) too – MM PP Jun 11 '15 at 08:29
  • 1
    You shouldn't use `md5()` to hash your passwords, since it has some collisions (different passwords would generate the same hash, that could give access to a used who doesn't know the "real" password, for example: `md5('fake pass') === md5('real pass')` could return true). Also, you need a salt your hash (salt is simply a random string, unique to each user, that is added to the password to generate different hashes even if 2 users have the same password). – Ismael Miguel Jun 11 '15 at 08:33
  • Ok. Where should I store the salt? – MM PP Jun 11 '15 at 08:34
  • 1
    Depending on your model, you can store it in the same table as the hash. The salt isn't meant to be secret, it just **must** be unique. You can read a whole more at http://security.stackexchange.com/questions/211/how-to-securely-hash-passwords (Seriously, read it. It's worth your time.) – Ismael Miguel Jun 11 '15 at 08:38
  • Ok, thank you so much for holping me. +1 to all your comments. – MM PP Jun 11 '15 at 08:42
  • 1
    You're welcome. Just helping to make the web a safer place. Any other question about safety, you can ask there (or in their chat, they are nice people). They will always be ready to help. – Ismael Miguel Jun 11 '15 at 08:45
  • @IsmaelMiguel Could one use the username as the salt, or should it be a "properly" generated random string? – Petzku Jun 11 '15 at 11:37
  • 1
    @Petzku It **must** be a properly random string. Please, don't use the username as an hash. Salts must be random and unpredictible. Also, they must change between password changes. Now, imagine this: You have a user `ad` with password `abc`, and an user `ada` with pass `bc`. These will generate the same hash. Imagine the damage this can cause... – Ismael Miguel Jun 11 '15 at 11:42

7 Answers7

10

$_SESSION is saved in the server, so the user cannot modify it ( Except the case of session hijacking)

kd0807
  • 660
  • 6
  • 14
  • But the session is not stored in broser, as a cookie? – MM PP Jun 11 '15 at 05:44
  • 2
    @MMPP A cookie is stored on the browser, but it is used as a link to the session (so I guess you could "change" to a different session"). The data itself is stored on the server. – Los Frijoles Jun 11 '15 at 05:44
  • I understand, thank you! But what is the session hijacking? How to avoid? – MM PP Jun 11 '15 at 05:45
  • 1
    @MM PP For example, avoid displaying $_SESSION['password;'] anywhere in your code or if your code exposes PHPSESSID as it is stored in browser cookie – kd0807 Jun 11 '15 at 05:50
  • 1
    @MMPP Session hijacking is if a user manages to see another user's cookie, then they can change their own session cookie to match the other user's session cookie, and use that user's session. – user253751 Jun 11 '15 at 08:52
  • @immibis - thank you. – MM PP Jun 11 '15 at 09:18
5

Session() is server side as @kd0807 noted. For more info on Session Hijacking && Fixation:

Side note... With the amount of variables I recommend an array for session['user']. example....

$_SESSION['user'] => Array(
'userid'=> '123',
'username'=> 'some_joe',
'role' => 'customer', // user, customer, admin, moderator etc.
'website' => 'http://www.example.com'
);

// reading variables from array
$userid = $_SESSION['user']['userid'];
$username = $_SESSION['user']['username'];
// etc. etc.

Here are 3 very simplified functions I use.

// determine if session has started
Function HasSessionStarted() {

    $result = false; // default to false

    // Check if session has started
    IF ((session_status() == PHP_SESSION_NONE) || (session_id() == '')) { 
        $result = true; 
    }

    return $result;

}

// Set a session value
Function Set_Session($name, $value) {
    /* @params value: can be a string or an array */
    $new_session = HasSessionStarted(); // Check Session Status

    IF ((isset($name)) && (isset($value))) {
        IF ($new_session) { session_start(); }
        $_SESSION[$name] = $value;
        IF ($new_session) { session_write_close(); }
    }

}

Function Unset_Session($name) {

    $new_session = HasSessionStarted(); // Check Session Status

    IF (isset($_SESSION[$name])) {
        IF ($new_session) { session_start(); }
        unset($_SESSION[$name]);
        IF ($new_session) { session_write_close(); }
    }

}
Brian
  • 1,035
  • 7
  • 14
3

There is a cookie stored in the browser usually PHPSESSID which identifies which server session the user is using. If a user were able to steal it (this usually happens through XSS vulnerabilities) the user could potentially take control of another users session.

The session data itself is stored on the server and could only be modified if a user were somehow able to upload and execute a malicious script in the server

andrew
  • 9,313
  • 7
  • 30
  • 61
  • 1
    This is blocked via DB entry (session id and IP). Compare cookie with session and db. If not a match ... new session id. – Brian Jun 11 '15 at 06:10
  • 1
    @Brian A neat idea, I like it – andrew Jun 11 '15 at 06:12
  • @Brian can you please tell me more about this? Should I need to store the user session id and the user ip in database and block if the IP is changed? – MM PP Jun 11 '15 at 07:29
  • 1
    To answer you questions straight forward ... If an Session id does not match the IP I delete the session() and the DB record and start fresh. My session tables are similar to (id[auto increment/primary], userid[medium int 15], ip[varchar 16], time[varchar 25]). On page load I assign session id to $sessid and ip to $uip, then search the db for matching session id and IP... SELECT * FROM sessions WHERE id = '$sessid && ip = $uip LIMIT 1" ... If result (true) I then compare the time stamp. Do what you wil with the time stamp. Persistent login etc. – Brian Jun 11 '15 at 07:42
  • @Brian Sorry for wasting your time with me... but I have an idea which I think can do the same thing, but without needing DB [ I am very severe regarding application optimization (and most on DB queries) ]. This is my idea: When the user log in, then the session is storing: username, website and the IP (of him). This will happen only when the user login. On every page, where commonly i check if the session exists, now i would make it to check if the current IP (which opens the page) is the same IP as stored in the session. Can there be any other security problem to be afraid if I do this? – MM PP Jun 11 '15 at 08:00
  • Thank you so much! (I said that, because, as I understand, even if the user have a session id, he couldn't change session stored data) – MM PP Jun 11 '15 at 08:05
2

Can the user change the session content? (for example, if user is logged in and $_SESSION["username"] is "example.com", can the user change the session $_SESSION["username"] to "example.org" to ruin another website?

No. Sessions are stored on your server thus it would be impossible to directly change the session. On the other side, it all depends on the developer and how the interprets the client requests. For example, making

$_SESSION['last_website'] = isset($_SERVER['HTTP_REFERER']) 
    ? $_SERVER['HTTP_REFERER'] 
    : $_SERVER['REQUEST_URI'];

would eventually override the $_SESSION['last_website'].

ʰᵈˑ
  • 11,279
  • 3
  • 26
  • 49
sitilge
  • 3,687
  • 4
  • 30
  • 56
2

No, Until and unless the php code itself reveals the PHP session, which can be used to session stealing, and the session could not be changed from the user end until and unless the there is some functionality given by you yourself to change the session from the front end.

Sourabh Kumar Sharma
  • 2,864
  • 3
  • 25
  • 33
2
`$_SESSION` variables are stored in the server and hence cannot be modified by the user.

One of the best practices is that we must keep changing the session id from our end.

Thats why we use a function called session_regenerate_id().

This function that will replace the current session ID with a new one, and keep the current session information, so the use will not be logged out.

To answer your question in comment:

Whenever you start a session, server will send back a cookie which will contain the session id, the cookie name will be PHPSESSID which is the default name. You can also choose to change it. So this id is what that keeps changing when you use the session_regenerate_id function.

REASON WHY TO USE IT:

This mainly helps in preventing session fixation attacks.In this attack a malicious user will try to fix the session ID (SID) of another user. If he gets successful,the user will get all the access of the original user and will be able to do anything that the legitimate user can do.

So if you regenerate the session id the previous old session id will be no longer valid

You can get more info about session fixation IN OWASP WEBSITE

Abhinav
  • 8,028
  • 12
  • 48
  • 89
1

Yes user cannot change session Variables...

if it hacked it can changed...

you need to get user id to change the $_SESSION["website"] in your current domain and use strict validation...

Otherwise they can hack it....

Bruce
  • 1,647
  • 4
  • 20
  • 22
  • I don't understand what are you trying to say. – MM PP Jun 11 '15 at 07:30
  • if you need to change the session of user get the user id from url(**user id must be encrypted before passing it**) and get the id and decrypted it and update your **user session** – Bruce Jun 11 '15 at 07:36
  • Ok, I understand. Thank you for the tip. – MM PP Jun 11 '15 at 07:46