Sessions and security

Discussions of secure PHP coding. Security in software is important, so don't be afraid to ask. And when answering: be anal. Nitpick. No security vulnerability is too small.

Moderator: General Moderators

User avatar
MarK (CZ)
Forum Contributor
Posts: 239
Joined: Tue Apr 13, 2004 12:51 am
Location: Prague (CZ) / Vienna (A)
Contact:

Post by MarK (CZ) »

Roja wrote:
MarK (CZ) wrote:
Roja wrote:If your app isnt destroying a session before creating a new one, thats an application/coding error.
How is that done?

Code: Select all

session_destroy();
session_start();
MarK (CZ) wrote: I still don't get the point where can I prevent anyone from getting around the sessions. Sorry about my ignorance of the problem :P
I don't understand your question. What don't you understand?
So the session_destroy() is the thing that puts me out of most of the risk?
Roja
Tutorials Group
Posts: 2692
Joined: Sun Jan 04, 2004 10:30 pm

Post by Roja »

MarK (CZ) wrote: So the session_destroy() is the thing that puts me out of most of the risk?
The question, specifically, was how to make new tabs not share authentication tokens with parent tabs - a totally different question from yours, and from the original post.

This thread has gone in completely different directions. The original question related to how to prevent session hijacking, and numerous people have asked how to prevent child-tab-session sharing, discussed security v. usability, and even WHAT to store once authentication occurs. All of which are related, but not truly relevant to answering the original question ;).

But to answer your latest question, imagine a chain, made up of multiple links. Then imagine trying to pick which of the links is "the important one" that prevents the chain from being undone.

No one link is "the thing that puts me out of most of the risk".

Good login designs include:

1. Strong password requirements
2. No cleartext passing of authentication tokens
3. No cleartext storage of authentication tokens
4. One-time pad/hashing
5. Unique user checking
6. Session ID regeneration for key events (password change, etc)

And so on..

Any one of those not being present, and there is a specific attack that can be used to lower the overall security.
User avatar
MarK (CZ)
Forum Contributor
Posts: 239
Joined: Tue Apr 13, 2004 12:51 am
Location: Prague (CZ) / Vienna (A)
Contact:

Post by MarK (CZ) »

Roja wrote:Good login designs include:

1. Strong password requirements
2. No cleartext passing of authentication tokens
3. No cleartext storage of authentication tokens
4. One-time pad/hashing
5. Unique user checking
6. Session ID regeneration for key events (password change, etc)

And so on..
I must be totally ignorant of the things or I don't know these terms. Either way it's not very good :( I always thought that my scripts are somehow secure with all the user-input checking etc but this makes me doubt...
Do you know about some well-made tutorial on these? Thanks again
Roja
Tutorials Group
Posts: 2692
Joined: Sun Jan 04, 2004 10:30 pm

Post by Roja »

MarK (CZ) wrote:I must be totally ignorant of the things or I don't know these terms.
You may already know them, but have different terms for them. Vocabulary is often tricky in technology. I generally use Information Security phrasing, since its my day job.

But I'll explain each a tiny bit:

1. Strong password requirements - More than 6 characters, use non-alpha-chars, etc. Passwords change regularly.

2. No cleartext passing of authentication tokens - For a login box, use javascript to hash (sha256) the password before sending it. (ie, don't send "password" in cleartext to the server).

3. No cleartext storage of authentication tokens - For logins, don't have a db column named "password" that in fact stores the plain-text version of the password. Ideally, use a hash of it instead (like sha256).

4. One-time pad/hashing - When a user goes to login, send him a one-time random number. Thats called a one-time pad. Hash that pad AND the hash of their password and send THAT. The server can do the same thing, and then that same token can't be reused later (because its only used once - one-time).

5. Unique user checking - make sure you dont have two identical users. Easier than it sounds, and it sounds pretty darned easy. Sadly, few systems check for it.

6. Session ID regeneration for key events (password change, etc) - Make sure to regenerate a session_id when the user status changes. This helps reduce brute-force session attacks, and session replay attacks.
MarK (CZ) wrote: Either way it's not very good :( I always thought that my scripts are somehow secure with all the user-input checking etc but this makes me doubt...
Secure is 100% relative. There is no "absolutely secure" in any sense. So, it may be "secure enough" for a simple website, or "secure enough" for a simple shopping cart online, or it might even be "secure enough" for an international bank routing system.

It just depends on the definition and the needs.
MarK (CZ) wrote:Do you know about some well-made tutorial on these? Thanks again
As a matter of fact, I've been working on one for Sitepoint, which I haven't submitted yet. When I do, I'll post about it, for sure.
User avatar
Buddha443556
Forum Regular
Posts: 873
Joined: Fri Mar 19, 2004 1:51 pm

Post by Buddha443556 »

Roja wrote: 3. No cleartext storage of authentication tokens - For logins, don't have a db column named "password" that in fact stores the plain-text version of the password. Ideally, use a hash of it instead (like sha256).
A hash of the password and the (unique) username is better. This way no two user's passwords should ever equal one another. Harder to brute force and eliminates certain social engineering attacks.
Roja
Tutorials Group
Posts: 2692
Joined: Sun Jan 04, 2004 10:30 pm

Post by Roja »

Buddha443556 wrote:
Roja wrote: 3. No cleartext storage of authentication tokens - For logins, don't have a db column named "password" that in fact stores the plain-text version of the password. Ideally, use a hash of it instead (like sha256).
A hash of the password and the (unique) username is better. This way no two user's passwords should ever equal one another. Harder to brute force and eliminates certain social engineering attacks.
That presents a problem: If the user misspells *either* their username or their password, they cant get a password reset/resend to email. By storing the username seperately, you leave that possibility.

I'm not sure what social engineering attacks you mean, but the passwords that are sent are already different due to the one-time hash. Did I misunderstand your idea?
User avatar
Buddha443556
Forum Regular
Posts: 873
Joined: Fri Mar 19, 2004 1:51 pm

Post by Buddha443556 »

Roja wrote:
Buddha443556 wrote:
Roja wrote: 3. No cleartext storage of authentication tokens - For logins, don't have a db column named "password" that in fact stores the plain-text version of the password. Ideally, use a hash of it instead (like sha256).
A hash of the password and the (unique) username is better. This way no two user's passwords should ever equal one another. Harder to brute force and eliminates certain social engineering attacks.
That presents a problem: If the user misspells *either* their username or their password, they cant get a password reset/resend to email. By storing the username seperately, you leave that possibility.

I'm not sure what social engineering attacks you mean, but the passwords that are sent are already different due to the one-time hash. Did I misunderstand your idea?
I think you did misunderstand me. I'm just saying a password = hash(username . password) is stronger than password = hash(password) for storing the password in a database. Yes, of course, the username should be store separately.

Social engineering attack against password = hash(password) is possible when you can find two users with the same hash(password) and one has higher privileges. If the CEO and Janitor both used the same password which would you target?
User avatar
MarK (CZ)
Forum Contributor
Posts: 239
Joined: Tue Apr 13, 2004 12:51 am
Location: Prague (CZ) / Vienna (A)
Contact:

Post by MarK (CZ) »

Roja wrote:
MarK (CZ) wrote:Do you know about some well-made tutorial on these? Thanks again
As a matter of fact, I've been working on one for Sitepoint, which I haven't submitted yet. When I do, I'll post about it, for sure.
Sorry to dig out old topic but I'd like to ask Roja whether he has finished the tutorial. I couldn't find it and I'd very much like to see it.
Thanks! :D
Roja
Tutorials Group
Posts: 2692
Joined: Sun Jan 04, 2004 10:30 pm

Post by Roja »

MarK (CZ) wrote: Sorry to dig out old topic but I'd like to ask Roja whether he has finished the tutorial. I couldn't find it and I'd very much like to see it.
Thanks! :D
Its not published there yet, but I'll explain the background to it in a pm.

To answer the question for the forum, no, its not published yet.
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post by Maugrim_The_Reaper »

But not necessarily the most convenient or efficient. Foremost, in order to prevent our "Cookie Monster" from stealing the cookie of the password hash, you'd need to type in the password EVERY TIME.

Security is always a balance between usability and security.
Yay and Nay... If you dilute security, it may be simpler, but not always. Depends on how far your entire security process goes. Some people promote using only concrete security measures and no "obscuring" measures. I prefer to use both to whatever extent is necessary.

On some other point I can't quite find the ref to - IPs are not unique. I have seen people show same IPs with one in Florida and the other in Texas (don't ask me how!) and same goes for library networks and schools. Besides ISPs don't always assign the same IP either when you dial up.

I know some might find it complex - but Roja's suggestions are rock solid. Pay attention class...
User avatar
Jenk
DevNet Master
Posts: 3587
Joined: Mon Sep 19, 2005 6:24 am
Location: London

Post by Jenk »

regenerating the session id on each page is also a help.

Code: Select all

<?php
session_start();
$old_session = $_SESSION;
$old_sessid = session_id();
session_regenerate_id();
$new_sessid = session_id();
session_id($old_sessid);
session_destroy();
session_id($new_sessid);
session_start();
$_SESSION = $old_session;
?>
As taken from "Nicolas dot Chachereau at Infomaniak dot ch" comment on php.net session_regenerate_id() manual page.
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post by Maugrim_The_Reaper »

Is it necessary to do so on every page (or am I befuddling myself with an obscure useability issue)?

<shrugs> Still works...

At the moment I keep it down to whenever there are changes in access levels, logins, etc. Just seems a little OTT on every single page...
User avatar
Jenk
DevNet Master
Posts: 3587
Joined: Mon Sep 19, 2005 6:24 am
Location: London

Post by Jenk »

It's not ott at all.

If a session is stolen, and then used prior to it being regenerated, they will be able to have it changed, if you understand what I mean?

It's like cloning someone's door key. You can open the door with it and if you go to the locksmith's and say "Hi, I have this key which fits this lock, I would like them both changed please"

Which actually does more harm as the original owner won't be able to get in at all.

Where as if you already changed the key and locks, the person with the cloned (old) key is as useful as not having a key.

Regenerating the session ID on each page is good practice.
Roja
Tutorials Group
Posts: 2692
Joined: Sun Jan 04, 2004 10:30 pm

Post by Roja »

Jenk wrote:It's not ott at all.
Sorry, I disagree. It is over the top, and can be harmful.
Jenk wrote:Regenerating the session ID on each page is good practice.
Regenerating the session ID on every page load can cause significant problems with back button behavior in web apps. Ilia posted about it, and its appeared on multiple mailing lists.

The current best practice is to regen the id on authentication or priveledge change, as you can see at Chris Shifflet's blog:
http://shiflett.org/articles/security-corner-feb2004
call session_regenerate_id() whenever a user successfully logs in, since this is the moment the session data becomes sensitive for most applications
(Many other sites echo that suggestion).

To use your analogy, instead of changing the locks everytime you unlock the door, you suggest changing the locks everytime someone USES the door - lock or not. Since doing so can break back button behavior in many cases, its harmful AND it gains you little extra security.

Overall, I'd say that fits the description of over the top.
User avatar
CoderGoblin
DevNet Resident
Posts: 1425
Joined: Tue Mar 16, 2004 10:03 am
Location: Aachen, Germany

Post by CoderGoblin »

I tend to agree it is over the top. We tend to use the session_id to track a user through the system (so we can tell what it has done in case of a user support request). We can tell if the error has been caused by a potential back button problem or whatever from this information. Regenerating the session_id on every page would mean this would not be possible.
Post Reply