PHP & MySQL site login, security concepts

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
batfastad
Forum Contributor
Posts: 433
Joined: Tue Mar 30, 2004 4:24 am
Location: London, UK

PHP & MySQL site login, security concepts

Post by batfastad »

Hi everyone
I've been using/learning PHP and MySQL for 2/3 years now, but I've never had to create a login system before. Now's the time :D

I've been reading up on a whole bunch of stuff and here's a very very simple framework I found... http://insanesecurity.wordpress.com/200 ... in-script/
I won't be using the obfuscated MySQL table/column names.

But it seems the main things to consider are that you should hash the password ASAP, and store it hashed in the DB.
Escape all data, both incoming and outgoing... which I do anyway.
Then on every page of the site, I will require() a file auth.php, which will have the code checking whether a session variable has been set which indicates whether the user is logged in or not.

But that all seems quite simple really, not much PHP code needed.
Are there any other best-practice pointers I should do to ensure maximum security?

Thanks, B
alex.barylski
DevNet Evangelist
Posts: 6267
Joined: Tue Dec 21, 2004 5:00 pm
Location: Winnipeg

Re: PHP & MySQL site login, security concepts

Post by alex.barylski »

1. Hash using sha256 not md5
2. Escape and validate passwords (minimum length, character entropy, etc)

Don't forget password reset, etc.
User avatar
VladSun
DevNet Master
Posts: 4313
Joined: Wed Jun 27, 2007 9:44 am
Location: Sofia, Bulgaria

Re: PHP & MySQL site login, security concepts

Post by VladSun »

Generate a new SID after a successful login to avoid session fixation attacks.
There are 10 types of people in this world, those who understand binary and those who don't
User avatar
Eran
DevNet Master
Posts: 3549
Joined: Fri Jan 18, 2008 12:36 am
Location: Israel, ME

Re: PHP & MySQL site login, security concepts

Post by Eran »

I would even say, regenerate the session ID on every page, especially if you use session cookies with a long TTL. Also, never store the password in either a session or a cookie.
Throttle log-in attempts to prevent brute-force attacks.
alex.barylski
DevNet Evangelist
Posts: 6267
Joined: Tue Dec 21, 2004 5:00 pm
Location: Winnipeg

Re: PHP & MySQL site login, security concepts

Post by alex.barylski »

Also, never store the password in either a session or a cookie.
Or leave it hardcoded in the FORM or written on white board in your home or office.

Get it tattoo'ed on your left index finger using Indian ink so the password can expire. :P
User avatar
VladSun
DevNet Master
Posts: 4313
Joined: Wed Jun 27, 2007 9:44 am
Location: Sofia, Bulgaria

Re: PHP & MySQL site login, security concepts

Post by VladSun »

pytrin wrote:Throttle log-in attempts to prevent brute-force attacks.
Just a notice - it should be done per IP basis, otherwise it may be used as a DoS attack.
Personally I prefer mod-evasive Apache module to do this.
Last edited by VladSun on Tue Feb 17, 2009 3:27 pm, edited 1 time in total.
There are 10 types of people in this world, those who understand binary and those who don't
André D
Forum Commoner
Posts: 55
Joined: Thu Aug 28, 2008 7:03 pm

Re: PHP & MySQL site login, security concepts

Post by André D »

pytrin wrote:I would even say, regenerate the session ID on every page
I have tried this approach before, but found it to be problematic. A user will get logged out if he sends two requests before the first response is received, or if he hits cancel immediately after clicking a link. Follow this:

1. User is logged in and has his session ID cookie.
2. User clicks a link to request another page.
3. Server processes request, assigns a different session ID, and returns the response.
4. User's browser receives the response, overwrites the session ID cookie with the new value, and renders the HTML.

Now what happens if the user hits the escape key while step 3 is happening? Or if he changes his mind and clicks a different link before step 4 happens? He enters a state where the server has reassigned his session ID but the browser never updated the cookie; the user is effectively logged out and probably frustrated. This can also happen sometimes when non-tech-savvy users double-click on hyperlinks.

For this reason, I only regenerate the session ID when the user's permission level changes (especially when he logs in, but I do it on log out too).
User avatar
batfastad
Forum Contributor
Posts: 433
Joined: Tue Mar 30, 2004 4:24 am
Location: London, UK

Re: PHP & MySQL site login, security concepts

Post by batfastad »

This is all excellent info!

I will hash the passwords using the sha1 function, I can't find sha256 in the PHP manual.
EDIT: Found it, the 1st parameter of the hash() function will do the job nicely ;)

I will also look into installing mod_evasive to prevent brute forcing.

A further few points I'd like some clarification on if possible...

1) I found the following article (http://phpsec.org/articles/2005/password-hashing.html) which goes on to discuss adding a salt to the hashed password... is that something I should look into?

2) Also, if the user password hash matches the database hash, then I just add a session variable. Something like

Code: Select all

$_SESSION['auth'] = 1;
Then check the value of $_SESSION['auth'] on each page, and if it's not 1 or not set then redirect to the login page.
Is that correct?

3) Should I change it to $_SESSION['jfkjsdayuyrth'] or something else random, to add a little bit of security by obscurity?
Or is SESSION['auth'] good enough?

Cheers, B
Last edited by batfastad on Thu Feb 26, 2009 8:58 am, edited 1 time in total.
User avatar
batfastad
Forum Contributor
Posts: 433
Joined: Tue Mar 30, 2004 4:24 am
Location: London, UK

Re: PHP & MySQL site login, security concepts

Post by batfastad »

Hi everyone
Any comments/suggestions on the 3 points I raised above?

Cheers, B
User avatar
VladSun
DevNet Master
Posts: 4313
Joined: Wed Jun 27, 2007 9:44 am
Location: Sofia, Bulgaria

Re: PHP & MySQL site login, security concepts

Post by VladSun »

Or is SESSION['auth'] good enough?
I think it's good enough.
There are 10 types of people in this world, those who understand binary and those who don't
User avatar
kaisellgren
DevNet Resident
Posts: 1675
Joined: Sat Jan 07, 2006 5:52 am
Location: Lahti, Finland.

Re: PHP & MySQL site login, security concepts

Post by kaisellgren »

If you ask for security, you should put a thread on the security forum, as some security experts are not reading topics located here - at least not very often. ;)

First of all, that kind of obfuscation is almost useless in terms of security.
PCSpectra wrote:2. Escape and validate passwords
Why to escape a password that will be hashed? Also, I do not think there is a reason to tell him to escape hash values, is there?
pytrin wrote:I would even say, regenerate the session ID on every page, especially if you use session cookies with a long TTL. Also, never store the password in either a session or a cookie.
Throttle log-in attempts to prevent brute-force attacks.
If you really want to have a high security application, regenerating the identifier on every page load, is not the way to do it. The proper way is to regenerate it after certain amount of time. The smaller the interval, the better. A user may write a blog post for thirty minutes, in which case the regeneration of the identifier will never occur even if it is supposed to happen on every page load. Also, session cookies may never have a high TTL value. Never. A value of 20-30 minutes is definitely maximum for any project. You are certainly right about not storing usernames or passwords in cookies. Usernames and passwords cannot ever be stored in sessions or cookies.
André D wrote:Now what happens if the user hits the escape key while step 3 is happening? Or if he changes his mind and clicks a different link before step 4 happens? He enters a state where the server has reassigned his session ID but the browser never updated the cookie; the user is effectively logged out and probably frustrated. This can also happen sometimes when non-tech-savvy users double-click on hyperlinks.
Transactions. Commit changes to the database (the new identifier) after the new cookie identifier value has been sent to the browser.
batfastad wrote:which goes on to discuss adding a salt to the hashed password... is that something I should look into?
Yes, salting (and peppering, having a global salt) is something you should look into.
batfastad wrote:Then check the value of $_SESSION['auth'] on each page, and if it's not 1 or not set then redirect to the login page.
Is that correct?
You can do that. Do also change the location of the session engine or someone on the same server can just locate to the temp directory and change values to 1 (Session Storage attacks).
batfastad wrote:3) Should I change it to $_SESSION['jfkjsdayuyrth'] or something else random, to add a little bit of security by obscurity?
No.
André D
Forum Commoner
Posts: 55
Joined: Thu Aug 28, 2008 7:03 pm

Re: PHP & MySQL site login, security concepts

Post by André D »

kaisellgren wrote:If you really want to have a high security application, regenerating the identifier on every page load, is not the way to do it. The proper way is to regenerate it after certain amount of time. The smaller the interval, the better. A user may write a blog post for thirty minutes, in which case the regeneration of the identifier will never occur even if it is supposed to happen on every page load. Also, session cookies may never have a high TTL value. Never. A value of 20-30 minutes is definitely maximum for any project.
Whether you regenerate the session ID on every page load, every five page loads, or do it based on time, for example every 15 minutes, you still have to wait until the next page load before you can actually change it. So if someone spends 30 minutes writing a blog post, then you have to keep the same session identifier for those thirty minutes because until he submits the post or requests another page, you won't have an opportunity to reset the cookie with the new session ID.
kaisellgren wrote:Transactions. Commit changes to the database (the new identifier) after the new cookie identifier value has been sent to the browser.
That won't work reliably, which is exactly my point. Even if the script executes completely and sends the response headers to the browser, you have no way of confirming that the browser actually received the response and updated the cookie. There are several things that could happen, including the user hitting the escape key or the stop button.
User avatar
kaisellgren
DevNet Resident
Posts: 1675
Joined: Sat Jan 07, 2006 5:52 am
Location: Lahti, Finland.

Re: PHP & MySQL site login, security concepts

Post by kaisellgren »

André D wrote:if someone spends 30 minutes writing a blog post, then you have to keep the same session identifier for those thirty minutes because until he submits the post or requests another page, you won't have an opportunity to reset the cookie with the new session ID.
You do not have to keep the same session identifier for those thirty minutes provided that you carefully designed your application.
André D wrote:That won't work reliably, which is exactly my point. Even if the script executes completely and sends the response headers to the browser, you have no way of confirming that the browser actually received the response and updated the cookie. There are several things that could happen, including the user hitting the escape key or the stop button.
If new cookie details have been submitted to the browser, the browser is responsible for changing the cookie data. With that attitude, you could also say that sessions will never work if the browser never accepts the cookies. Of course it requires browser interaction. If the browser follows standards, then we will be fine. If it does not, then it is user's fault of using a weird web browser. I think even IE5 will handle this properly.
André D
Forum Commoner
Posts: 55
Joined: Thu Aug 28, 2008 7:03 pm

Re: PHP & MySQL site login, security concepts

Post by André D »

kaisellgren wrote:You do not have to keep the same session identifier for those thirty minutes provided that you carefully designed your application.
Please elaborate, because it sounds like you're suggesting that it's possible to design a web application that circumvents the fact that you cannot set a cookie on the client without an HTTP request and response. That's what it comes down to; if the client does not send any HTTP requests for thirty minutes, you cannot send any HTTP response headers that tell the client to update the cookie. Therefore, the server must remember that session ID for those thirty minutes, unless you want the user to be logged out and lose his blog post.

Having said that, it's a good idea to have sessions time out after a period of innactivity, but that's seperate from the lifetime of the session identifier, which is what we're talking about here.
kaisellgren wrote:If new cookie details have been submitted to the browser, the browser is responsible for changing the cookie data. With that attitude, you could also say that sessions will never work if the browser never accepts the cookies. Of course it requires browser interaction. If the browser follows standards, then we will be fine. If it does not, then it is user's fault of using a weird web browser. I think even IE5 will handle this properly.
It's not a matter of standards, it's a matter of timing and the HTTP protocol. Going back to the problem I brought up in my first post in this thread, the more often you change the session identifier cookie, then the more users you will have that see this problem, no matter what browser they use. It's the good ole security vs. convenience tradeoff. My point is that if you change the identifier too often, then people are bound to run into this, and when they do they will perceive it as a bug in your application.
User avatar
kaisellgren
DevNet Resident
Posts: 1675
Joined: Sat Jan 07, 2006 5:52 am
Location: Lahti, Finland.

Re: PHP & MySQL site login, security concepts

Post by kaisellgren »

What kind of applications often need to update their already strong identifier? Banks, military sites, government sites, etc. If that is so, do you not think it is modest to ask for having JavaScript turned on?

Just create a JavaScript that calls after certain amount of inactivity. If the JavaScript is turned off, then there is no problems - "just" a degraded security.
André D wrote:unless you want the user to be logged out and lose his blog post.
You are thinking simplistically. Why to lose the content? A log out does not mean you lose anything. Use your imagination to "save" the content.
André D wrote:It's not a matter of standards, it's a matter of timing and the HTTP protocol. Going back to the problem I brought up in my first post in this thread, the more often you change the session identifier cookie, then the more users you will have that see this problem, no matter what browser they use. It's the good ole security vs. convenience tradeoff. My point is that if you change the identifier too often, then people are bound to run into this, and when they do they will perceive it as a bug in your application.
If they use a typical web browser with JavaScript turned on, no problems would occur except in really rare cases.

For instance, look at this:

Code: Select all

$data = str_repeat('1234567890',128);
echo "<script>document.cookie='session_id=new_id'</script>";
for ($a = 0;$a < 9;$a++)
 {
  echo $data;
  flush();
  sleep(1);
 }
Now if you press the stop button on purpose, you will still have your cookies created. I even tried pressing the button quickly, but the cookies were still created, because the timing has to be so damn precise. How long does it take to send 20 bytes of data to the client? With a 512 kBps connection it takes around 0.0003 seconds (of course there are other things affecting it, but the number will not change much). And now, you have to press the stop button within that time and the button has to deliver the signal and actually stop the download. This is hard to achieve even on purpose not to mention by accident, but that is the price you pay for your high security bank website. You must tell your user that this bank site requires JavaScript, which I do not think is much to ask for. Actually we could almost assume the user has JavaScript. We are in 2009, simple JavaScript calls should be possible. If not, then the user has to enable them as it is the requirement for this very high secure site.

Obviously there are always situations where the cookies may not be updated. This also applies to the case you said earlier: regenerating the identifier after a password change. If I change my password and press then stop and go back, I have to login unless we are using my simply-demonstrated JavaScript method which can make this practically impossible.

And yes, ultimately there is no way to be 100% sure the cookie was updated.

I can see your point, but I assumed that the client has JavaScript turned on as very high secure websites rarely work in a limited environment.
Post Reply