Take the 2-minute tour ×
Information Security Stack Exchange is a question and answer site for Information security professionals. It's 100% free, no registration required.

I have a (hobby) web site that runs only on SSL (i.e., site-wide HTTPS). The site does not deal with finances, social security numbers, or anything of that level of importance. However, I'd like to secure it as much as reasonably possible. When a user logs in, two cookies are written: one cookie stores the user id and a second stores a session id. Cookies are marked Secure and HttpOnly.

I have one directory where I'd like all registered users to be able to access files. It seems to me that one way to accomplish this is to use .htaccess in the key directory to see if there is a valid user-id cookie: If so, grant access, but if not, redirect to the login page. This way, I do not need to keep updating legal values for the cookie or have much overhead in checking access.

I found the following code for .htaccess:

RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_COOKIE} !^.*cookie-name.*$ [NC]
RewriteRule .* /login-error/set-cookie-first.html [NC,L]

and this is all working fine: When logged in as a registered user (i.e., when there is a cookie called cookie-name) I get access to the directory; when not logged in, I'm redirected to the login page.

However, I'm wondering: What security issues have I overlooked? For example, is it possible for an attacker to create a cookie with the correct name in the attacker's browser and then have my system think that's a real cookie?

share|improve this question

2 Answers 2

up vote 0 down vote accepted

If your server grants access only by seeing a cookie with the user ID, then knowledge of the ID of a user is sufficient to obtain access. User ID is thus a valuable secret. But user ID are not really secret; often, the user ID is his name, which can be considered public or at least guessable.

What you need is a user-specific secret, which, when presented, grants access -- something which the normal user can show, but which cannot be guessed by outsiders. This is usually known as a "password". The full setup is then:

  • There are sessions. A session is a server-side state which is "owned" by a user. Sessions are identified by big strings of random bytes (at least 16 bytes, generated with a cryptographically secure PRNG).

  • When a user first connects, he has no cookie to send back. The server redirects the user to a login page.

  • When the user enters his name and password, and the server has verified that the password is correct, then the server creates a new session, with its random session ID, and sends that session ID as a cookie value.

  • For each subsequent page browsing, the user's browser will send back the cookie. Upon receiving such a cookie, the server looks up in its database the corresponding session. If the server does not find a session with that ID, then it redirects the user back to the login page.

  • To keep storage size under control, the server will expire sessions (i.e. forget all about them) which have not been used for some time (so the server should keep in each session a date of last usage).

The security of this scheme hinges on the fact that attackers cannot "guess" a valid session ID: since session ID at random, the only possible guess algorithm is luck (attackers tries some random bytes and hopes to hit an existing session ID); using large enough session ID (the 16 bytes with secure generation) ensures that the probability of success for the attacker is sufficiently low to be neglected.

share|improve this answer
    
Thanks! This gives me what I was looking for. A single token for every user, but one that is not guessable. I should have thought of this, but unfortunately didn't. –  RPW Feb 13 '13 at 17:05

You want to tie to session IDs not user IDs. User IDs don't change and can't expire. They also can be forged if a user ID is known. Since Session IDs are random, not re-used, and expire, it is far more difficult to make a valid session cookie without actually logging in.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.