Secure Session Cookies
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
useris the user-name of the client.
expirationis the expiration time of the cookie.
data_kis encrypted data that's associated with the client (such as a session ID or shopping cart information) encrypted using key
kis derived from a private server key
k = HMAC(user | expiration, sk).
data_kcould be encrypted using
AESusing the key
macis an HMAC of the cookie to verify the authenticity of the cookie;
mac = HMAC(user | expiration | data | session-key, k).
datais the unencrypted data associated with the client.
session-keyis the SSL session key.
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?
what about if the application is deployed on multiple servers (load balancing) ? how can we keep the same SSL key on all servers ?
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:
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.
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
true; if you use multiple server nodes, generate a strong cryptographic key and configure each server's
machineKeyto 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.
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, 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.
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: 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.
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 "_Browsers vary in whether they manage cookies in a central store_" which browsers do not behave as if they used a central cookie store? (Using "private mode" and multiple "profiles" do not count, any functionality intended to change your online identity and session state do not count.)
@D.W., Hmm, you mentioned the use 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". **And,** thus is it right to say that the use cases for SCS is actually pretty very very much limited? I mean wouldn't most servers (99% of population) simply opt for server-side storage?