What security considerations are to be taken when developing a system similar to ASP.NET session?
Edit: Some follow up to input received,
Does encrypting the token actually offer real security? The ASP.NET session token is not encrypted, if they steal the entire cookie it doesn't matter whether it's encrypted or not the end result is the same.
I do see if the token is encrypted and/or signed that it becomes harder to attempt to guess a valid token. Assuming the tokens are short lived, 24 hrs max or perhaps with a sliding expiration with some cap on overall duration does signing the token offer any additional security past rendering very random unique tokens?
I would be considering using something along the lines of a 512byte value generated by the RNGCryptoServiceProvider
.
Is generating a long random token as secure as signing a smaller token? Or should I be more concerned in using a smaller token and signing it? Part of the problems relevant to the system this is to replace is the fact it generates cookies too large for some browsers so my goal is to开发者_开发问答 have very lightweight cookies.
An interesting idea.... I guess the first thing that comes to mind is don't. Not because its been done, but because it was a bad idea to begin with. But I won't debate the pros and cons of sessions with you, so here is my answer...
Let's break this down by the 'type' of token:
- Random identifier tokens
Anyone can simply 'guess' one of these, yet they are fast and easy to use. Since the session is usually short-lived this is not generally a major problem. Also a great solution because they are small in size (22 bytes base64 encoded guid, or 32 bytes as hex)
You wrote: "I would be considering using something along the lines of a 512byte value generated by the RNGCryptoServiceProvider."
Yea OK it seems like 512 byte id's would be cool; however, even 128 bit values (16 bytes) have an absurd number of possibilities (more requests than your server can handle in a year). Don't make this your primary defense, instead assume that the id is not a secret.
- PKI Encrypted and signed data
This works well to 'hide' the information flowing through the transport. Do you need to? Is it worth the considerable overhead? There is also cost in the amount of data flowing in addition to computation/verification overhead. Is it more secure? probably, but in the end it's just as easy to steal as the random id.
Always assume someone else can obtain the session id/token
This is where you should focus your energy because if I can give someone else my cookie and my account is still safe, then and ONLY then is the session secured. That being said I don't know of a 100% way of doing this without client certificates, and even that has issues.
In the web request world there are two pieces of client identifiable information included with a request. The client IP address and the User-Agent. The problem is these values can change for a session. So an approach is to either re-prompt for verification every time these change, or for each distinct value.
Yes, I'm aware that a User-Agent is very easy to fake, and a client IP address can also be spoofed; however, at the end of the day you've made it harder for someone to attack. That is the point of security for nothing is absolutely secure.
More advice
For highly sensitive data you should timeout sessions quickly (< 5 min).
Obviously SSL is a must for numerous reasons
SSL has support for 'secure cookies' which are never written to disk or persisted. This can make the session id harder to obtain.
Key cycling can be used effectively enough, if you generate a new session key on each visit as Cris Lively suggests, you need to keep the last N number of session id's alive. So if N=5, after 5 requests my original session id is no longer valid.
Learn from others, read, and hack around on your existing accounts with other major sites.
finally...
I'll again say that sessions don't scale well and should be avoided in all but a very few places.
UPDATED:
So I've thought some about this since my last post, thought I'd update my thoughts with another answer...
Generating an id of 16 bytes or larger should be sufficient to effectively eliminate an attacker guessing session ids. Assuming this and the use of SSL + secure cookies you should be about as secure as you can be. Why?
SSL will effectively prevent someone from obtaining a session key during transit. Thus, if someone does have a session key that does not belong to them, it's because they are doing one of two things: A) they are running code on the client (maybe in the browser), or B) they are running code on your server. So basically if they can compromise an endpoint you've already lost the security game and their is likely to be very little gained by any additional work.
If your not using SSL, you have no security anyway. A simple man-in-the-middle attack will let an attacker do anything I want on the client's behalf. Any work to secure the use of HTTP without SSL (or some form of securely negotiated session key) is simply a pretense of security. Yes you can make it more difficult, but you can't make it secure.
So in the end, simply trust SSL to do it's job of securing the transport and get on with life :)
- Is it needed at all. You can't attack something that isn't there, and a large number of session-using systems don't need to be.
- What is the implication of attack? (If someone can see someone else's preferred colour scheme I don't care) What could be the implication in the future? (Could I tomorrow end up extending the same skin-choosing code to also deal with more sensitive data).
- Am I already protected from many attacks by SSL?
- Can key generation be predicted? Do I need to change keys regularly? How often? How shall I do so? How shall I deal with out of sequence requests (genuine request for img1.png comes after request for img2.png has changed the key).
- Cookies, or something else?
- Do I need a "sign-out" to clear the server state as well as the client's cookie?
- Where will the session "bag" live? On the webserver, or somewhere else. How do I deal with a webfarm situation (if I don't need to now, could I?)
- Can I split off some information into session state, and base some other on authentication?
- Can I use client-side code to add a challenge-response to the cookie handling, or must I assume no-js environments?
- Can I detect people trying to guess IDs? How should I respond?
- How do I avoid reuse of keys (that is, my "honestly" assigning a key that was used before) and/or avoid it being a problem?
The weak point in the session handling is the recognition by the server of a designated session, because it must be part of the informations, the client is giving to the server.
Therefore, I would encourage some crypting of the key, and a time out of its validity.
It is up to you to store the key then in the cookie, in the url, or wherever might suits your needs.
How ASP.net store the identification on the client side
Taking these one at a time:
What are the security considerations of rebuilding .Net's session handling:
.Net's session handling only offers very limited security for most situations and none for others. If the goal is to prevent the data from going to the browser, that it does. However, if the goal is to ensure only the authorized user can leverage that data.. well, it doesn't. Rebuilding this as is is trivial and leads us to your other questions.Does encrypting the token actually offer real security?
No. It doesn't. Anything you send to the browser can be compromised. If that data can be intercepted and replayed then it doesn't matter. There are solutions though...Is generating a long random token as secure as signing a smaller token?
Considering neither offer any level of security, then yes they are equivalent.
If I was to go about rebuilding asp.net's session handling then I'd add one thing: A randomly changing value indicating the next accepted "request token". This should be as non-guessable as possible.
This key would be sent to the browser on each response, and sent back by each request. The site would validate that the key was valid for this request and generate a new one for the response.
This would ensure that even if the data stream between the browser and server was recorded, it couldn't be replayed. For example:
- Browser makes initial request to server. Server responds with session ID ABC and Request Token 1
- Browser makes second request to server passing ABC and 1. Server validates the combination, performs the request and responds with Token 453.
- Browser makes third request to server passing ABC and 453. Server validates the combination, performs the request and responds with Token 23
- Bad guy replays step 2, passing ABC and 1. Server sees invalid request, alerts site owner and responds with a security violation error.
In this scenario the ONLY way for the bad guys to replay is if they send a brand new request with the last token received. However, as soon as the real browser sends a new request they'll receive a nice security violation notice and you'll be notified.
There are many other things you can do from here to lock it down further. This was only one idea to mitigate a particular type of attack.
UPDATE
One question in the comments was about concurrent requests. Generally speaking, a browser will issue multiple GET requests for artifacts like CSS, Images, Javascript, etc. These should be not be included in the security test. However, every POST request, which a browser will only make one of at a time, should trigger the validation and have a new value sent back to the browser.
精彩评论