10

So, I've created an authentication system. Poured over it for any kind of security flaws and tested the crap out of it. I think it's fairly secure, but there is one "different" by-design aspect of it that's not usual of a web authentication system.

Basically, I wanted to make it so that authentication could be done without keeping track of each user's session. This means less load on the database, and trivial to scale and cache. Here are the "secrets" kept by the server:

  • A private-key is kept in the source code of the application
  • A randomly generated salt is kept for each user

To make it sessionless, but making forging cookies not easy, this is the format of my cookies

expires=expiretimestamp
secret=hash(privatekey + otherinfo + username + hashedpassword + expires)
username=username

(with otherinfo being things like IP address, browser info, etc and with hashedpassword=hash(username + salt + password + privatekey)

My understanding is that forging login cookies (not cracking the passwords) requires:

  1. Source code access to the application, or a way to trick it to spit out the private key
  2. Read-only access to the database to get the salt and hashedpassword

Whereas the traditional session method requires:

  1. Write and read access to the database (to inject the session, or trick the web app into doing it for you)
  2. Possibly source code access depending on how it works

Anyway, does this seem overly insecure to anyone? Are there any ways for me to improve on it and make it more secure(while keeping with the stateless/sessionless model)? Are there any existing authentication systems which use this stateless model?

Also, the hashing method can be basically anything, ranging from SHA256 to Blowfish

3 Answers 3

14

Your basic concept is not new: you want to have some state associated with the user, but you do not want to store that state yourself. Instead, you store it on the client (in a cookie). Since you want to protect against alterations of such a state (e.g. a client building a cookie from scratch), you need an integrity check, such as a Message Authentication Code. Your construction with a hash function is a crude MAC. It so happens that it is a weak MAC with the usual hash functions, because of the length extension attack.

If you want a MAC, use a strong one, and that means HMAC. It is standard and widespread.

Of course, storage of the secret key (for MAC computations) is a tricky point. Something embedded in the "source code" of the application exists as a file, which (by nature) the application can read, making it vulnerable to exploits which obtain illegal read access to arbitrary files. It would be better (but harder) to arrange for the MAC key to be obtained dynamically by the application through some local communication protocol (the application contacts a local server, which gives the key only to the application); that way, the key would only exist in the RAM of the application, not as a file readable with the access rights of the application. It would not be absolute protection (if your server gets thoroughly hacked, well, that's it) but it would be stronger in practice.

I see that you include the hashed password in the data which is MACed. This is a bit weird; you already have the MAC as authentication: the MAC proves that the cookie data is genuine, thus there is no need for further authentication.

Blowfish is not a hash function; it is a block cipher (or a type of fish) and, as such, cannot be used for hashing unless it is considerably modified, which would mean homemade cryptography, and that's not a good idea.


If you are offloading state on the client, you might want to offload state which the client himself should not know. This means that you may also need encryption. Combining encryption and MAC securely is not as easy as it seems; there are modes for that. I recommend EAX.


Be warned that not maintaining state makes you inherently weak against replay attacks. That's unavoidable. You can minimize the damage by using short validity ranges (e.g. a cookie expires within 15 minutes).

3
  • 4
    +1 for actually analysing the solution (and for HMAC). My guess is the inclusion of the password in the hash is to cause the old tokens to be invalidated when the user does 'change password'. Another way of doing this is to include a password generation number or random ID (maybe the salt) rather than the password itself, which causes the tokens still to be invalidated if the same password is re-used.
    – bobince
    Nov 30, 2012 at 14:59
  • Well, maybe I meant BCrypt instead of Blowfish. Either way, the hash function that's considered very secure and with an adjustable workload. Thanks for the thorough analysis though. I'll have to research length extension attacks more. Also, good note about the file vulnerability bit. The only time I've ever seen this type of key-fetching used though has been with coprocessors dedicated for signing certificates. Could you give more information about how that could be done securely?
    – Earlz
    Nov 30, 2012 at 15:24
  • 1
    You might also want to take a look at JWT (JSON Web Tokens)
    – Rob Evans
    May 3, 2018 at 9:57
2

This proposed system is a session handler used to maintain an authenticated state and your method of building session tokens is insecure.

For example, using SQL Injection you can read most of the secret data from the database. If you are using MySQL SQL Injection can be used to read files using the load_file() function which could be used to read the secret from a config file.

In general you should not reinvent the wheel when building a system. I am sure your platform comes with a secure session handler because just about every web application will need one.

Session ID's should be purely random values and an entropy pool like /dev/urandom is an excellent choice. Just because you are using the platform's session handler doesn't mean its configured properly. I recommend reading the OWASP Session Management Cheat Sheet.

17
  • 1
    Also, wouldn't it be arguable that if you find a SQL injection flaw, then write access to the database is almost a sure thing anyway? (making sessions not fair any better)
    – Earlz
    Nov 29, 2012 at 21:24
  • 2
    "with otherinfo being things like IP address, browser info, etc" - that sounds like if you have the same public IP as an identified user, you only need to sniff the cookie to assume their identity. Since a session id is just a cookie anyway - why create a new way to store a session cookie.
    – AD7six
    Nov 29, 2012 at 23:19
  • 4
    @Earlz Except that's only true in cases where the reinvention provides quantifiable benefit. In this case you're reinventing session handling on a platform that already has a working, well-tested, strong, in-built session handler. In fact, your solution is inferior to the default, which is a bad thing. Security is hard - don't try to do it yourself if someone already produced an ideal solution, especially just because you think implementation of their system is hard. In fact, attempting to roll your own when you struggle with the existing implementation is a sign you shouldn't be touching it.
    – Polynomial
    Nov 29, 2012 at 23:37
  • 3
    I think it's stupid that this place hasn't escaped the "never implement your own authentication" mindset. Yes, it's not a good idea usually because it's hard to get right. If a researcher came here to solicit advice for a crypto algorithm he's been working on would you tell him "no use AES256 because it's proven". I came here for expert advice, not to be told I don't know what I'm doing.
    – Earlz
    Nov 30, 2012 at 2:14
  • 2
    @Earlz You aren't getting a pat on the back and now you're all upset. You don't have to take advice, and furthermore, nobody said "you don't know what you're doing." All they're saying is that your method is no more secure than the already proven methods. You said "If some people hadn't 'reinvented the wheel', we'd still be stuck with all the programming languages and algorithms of the 60s." They didn't reinvent the wheel, they improved it, or else they wouldn't have been adopted. The consensus is that nobody sees improvement in your method over what's already available, take it or leave it.
    – Purge
    Nov 30, 2012 at 5:13
2

To make it sessionless, but making forging cookies not easy, this is the format of my cookies

What you describe is not sessionless - it's just that the authentication state is held on the browser rather than the server.

Even for an SSL only site it's a good idea to try to detect session hijacking and fixation (for fixation the type of exploits available are more restricted since presumably authentication is directly tied to session management) which means storing data server side.

Authentication is not very useful without authorization (please don't tell me your authorization is built directly into your code) which again depends on information held server side.

You still need to regenerate the hash to verify every request or store the hash in a lookup table - which means retrieving data on the server.

Then if you've got any sort of data processing, then in addition to the transactonal data, you should have CSRF prevention - which is usually implemented by storing data serverside.

I don't see how you've reduced the workload compared with using a conventional web session. If you had simply included the username, the expires time and a hash of the username and expiry time, then yes, could rely on the cookie value as providing equivalent evidence of identity as a conventional web session - but this only allows for a very limited authorization/access model.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .