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.

While looking up methods for creating secure session cookies I came across this publication: A Secure Cookie Protocol. It proposes the following formula for a session cookie:

cookie = user | expiration | data_k | mac

where

  • | denotes concatenation.
  • user is the user-name of the client.
  • expiration is the expiration time of the cookie.
  • data_k is encrypted data that's associated with the client (such as a session ID or shopping cart information) encrypted using key k.
    • k is derived from a private server key sk; k = HMAC(user | expiration, sk).
    • data_k could be encrypted using AES using the key k.
  • mac is an HMAC of the cookie to verify the authenticity of the cookie; mac = HMAC(user | expiration | data | session-key, k).
    • data is the unencrypted data associated with the client.
    • session-key is the SSL session key.
  • HMAC is HMAC-MD5 or HMAC-SHA1.

According to the paper, it provides cookie confidentiality, and prevents against replay and volume attacks. To me (being an amateur in security/cryptography) this looks pretty good. How good is this method for session cookies or cookies in general?

share|improve this question

6 Answers 6

up vote 14 down vote accepted

Yes, this does look like a pretty good scheme for protecting cookies.

Another more recent scheme in this area is SCS: Secure Cookie Sessions for HTTP, which is a solid scheme, very well thought-out. I recommend reading the security discussion of that document to get a good sense of what the security threats may be.

To help understand the purpose and role of the cookie scheme you mention, let me back up and provide some context. It is common that web applications need to maintain session state: i.e., some state whose lifetime is limited to the current session, and that is bound to the current session. There are two ways to maintain session state:

  1. Store session state on the server. The web server feeds the browser a session cookie: a cookie whose only purpose is to hold a large, unguessable bit-string that serves as the session identifier. The server keeps a lookup table, with one entry per open session, that maps from the session identifier to all of the session state associated with this session. This makes it easy for web application code to retrieve and update the session state associated with a particular HTTP/HTTPS request. Most web application frameworks provide built-in support for storing session state on the server side.

    This is the most secure way to store session state. Because the session state is stored on the server, the client has no direct access to it. Therefore, there is no way for attackers to read or tamper with session state (or replay old values). It does require some extra work to keep session state synchronized across all servers, if your web application is distributed across multiple back-end compute nodes.

  2. Store session state on the client. The other approach is to put session state in a cookie and send the cookie to the browser. Now each subsequent request from the browser will include the session state. If the web application wants to modify the session state, it can send an updated cookie to the browser.

    If done naively, this is a massive security hole, because it allows a malicious client to view and modify the session state. The former is a problem if there is any confidential data included in the session state. The latter is a problem if the server trusts or relies upon the session state in any way (for example, consider if the session state includes the username of the logged-in user, and a bit indicating whether that user is an administrator or not; then a malicious client could bypass the web application's authentication mechanism).

    The proposal you mention, and the SCS scheme, are intended to defend against these risks as well as possible. They can do so in a way that is mostly successful. However, they cannot prevent a malicious client from deleting the cookie (and thus clearing the session state). Also, they cannot prevent a malicious client from replaying an older value of the cookie (and thus resetting the session state to an older value), if the older version came from within the same session. Therefore, the developer of the web application needs to be aware of these risks and take care about what values are stored in session state.

For this reason, storing session state in cookies is a bit riskier than storing it on the server, even if you use one of these cryptographic schemes to protect cookies. (However, if you are going to store session state in cookies, I definitely recommend you use one of these two schemes to protect the values in the cookies.)

Why would anyone store session state in cookies, given that it can just as easily be stored on the server side? Most of the time, there is no reason to. However, in some exceptional cases -- such as a HTTP server that is extremely constrained in the amount of storage it has, or in load-balanced web applications that are distributed across multiple machines without good support for synchronized session state -- there might be justifiable reasons to consider storing session state in cookies, and then using one of these schemes is a good idea.

P.S. A related topic: if you use ASP.NET View State, make sure you configure it to be encrypted and authenticated: i.e., configure ViewStateEncryptionMode to Always and EnableViewStateMac to true; if you use multiple server nodes, generate a strong cryptographic key and configure each server's machineKey to use that key. Finally, make sure you have an up-to-date version of the ASP.NET framework; older versions had a serious security flaw in the ViewState crypto.

share|improve this answer
    
There are some major issues with SCS - not least that it relies on transaction counting to authenticate - and that's just not going to work with split sessions nor caching –  symcbean Sep 22 '11 at 14:15
    
@symcbean, thanks for the comment. Can you elaborate more about what you mean by transaction counting? I didn't notice any transaction counters in the Internet-Draft specification for SCS. –  D.W. Sep 23 '11 at 16:48
    
It's not incrementing a counter - but it does use the timestamp of the last operation as a validator (which changes for each transaction). Browsers vary in whether they manage cookies in a central store / one per window / one per tab - and this varies by the cookie type too. –  symcbean Sep 30 '11 at 8:07
3  
@symcbean: Yes, SCS includes a timestamp in the validator, but I wonder if you may have misunderstood what it is used for. The timestamp is used to expire sessions after they are (say) more than a day old. It is not used to count transactions, and it does not cause problems for split sessions or caching. You have not stated why this is a major issue. –  D.W. Sep 30 '11 at 15:46
2  
OK - read it all - I had assumed it was there for limiting replay attacks - but I see "SCS doesn't address replay of old cookie values" –  symcbean Oct 4 '11 at 14:15

What problem are you trying to solve?

There are two things I can think of:

  1. You want to setup secure user sessions. In this case, you most likely don't even need to generate your own session cookies - they can be generated over an SSL session with your server and are generally secure for any website needs. Just make sure the site implements SSL correctly, and you use a well known session generation method such as can be found in common languages like PHP or ASP.
  2. You want to store secure data in the cookie for retrieval later. This is much harder to make secure, due to many issues with cookies. Better to store server-side instead, and associate the data with the user using another method. If you must do this, the method you describe looks pretty good overall, though I am not clear how it prevents replay attacks, or other attacks like man in the middle the way SSL does.

Feel free to contact me directly if you want to discuss more.

share|improve this answer

Part of the method they propose is to use the SSL session key as part of the encrypted payload - but this only lasts as long as the SSL session - i.e. you can't use this method for cookies intended to span more than one browser session. It's also no exactly trivial; to get hold of the SSL session key, particularly of the SSL termination is somewhere other than on the http server.

In practice it's a whole lot simpler to use a random value for the cookie as a handle to data stored serverside. This can be tied to stuff like a hash of the browser user agent and the netname (not IP address) of the client. And/or, if you must, the SSL session key on the server. There's no need to encrypt all this data and push it out to the client.

share|improve this answer

This is a reasonable implementation as it solves the issues of:

  • Non-repudiation (verifying the value was not changed)
  • Confidentiality (that the encrypted content cannot be read)

However, the user information is a bit weak and if not incorporated inside the encrypted information for later comparison could be compromised.

The biggest problems with cookies or any client-accessible data is that the client (hacker) can modify or copy it. Session hijacking is easily accomplished despite SSL (as previously commented as being sufficient - which it isn't). Various forms of malware, man-in-the-middle, man-in-the-browser and other attacks can capture the session-cookie, copy it to another machine and now they can 'own' that session. For a card-on-file system like Amazon this can be problematic.

To close the loop on this proposal, the client identification must be reasonably unique and then tied to data in the encrypted section to prevent another computer from stealing the session cookie. Other than that, the components of the proposal seem sound.

share|improve this answer
    
I think you are confusing "Non-repudiation" and integrity. –  curiousguy Aug 8 '13 at 23:36
    
Inter-related terms in this context (from Wiki): "Regarding digital security, the cryptological meaning and application of non-repudiation shifts to mean:[1] A service that provides proof of the integrity and origin of data. An authentication that can be asserted to be genuine with high assurance." –  Darrell Teague Sep 5 '13 at 15:54

Well, if you pass the cookie in clear-text, it isn't secure at all.

But if you are trying to create a cookie that cannot be guessed, then it's perfectly adequate.

share|improve this answer

I'm assuming the HMAC would change with each request to prevent the replay attacks?

You would need to make sure the requests occur synchronously otherwise the HMAC would fail on multiple requests if the user happens to have multiple pages open at once.

If the HMAC doesn't change, I'm not sure how it prevents replay attacks?

share|improve this answer
    
Section 2.3 of the paper linked to by @cpburnz describes how they prevent replay attacks and what kind of replay attacks it defends against. The security property they provide is a bit less than one might initially guess. –  D.W. Sep 22 '11 at 7:02

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.