Image caching, HTTPHandler and FormsAuthentication - c#

The Setup:
I'm working on a website that uses Formsauthentication using cookies to store the login ticket. The site also has an HTTPHandler that manages images stored in the database. The handler caches the images to be public and expire in 20 minutes. We have noticed that since the images have the same lifecycle as a page the images also include the Formsauthentication cookie. The configuration is IIS 6, Win2k server, Content Expiration is not enabled.
The Problem:
What we are experiencing is Person A logs in and hits a couple of pages. Then Person B hits the default page not logging in and get's the cookie for Person A and is able to see all of Person's A data. We have reproduced the problem once by turning on Content Expiration in IIS but have not reproduced consistently so we are not sure if Content Expiration helped us reproduce it. We are assuming since the images are being cached as public and they also contain the cookie with the FormsAuthentication, it's somehow possible for Person B to unintentionally get Person A's cookie. We know this isn't a attack on the website.
Has anyone experienced anything similar to this behavior? If so, can you provide any advice on how to reproduce this issue consistently?

We are assuming the cookie is in the Response Header and is writing out the same cookie that exist on Person A's machine to Person B. Its important to note that this issue occured with Person A in IE 7 and Person B in FireFox. Also when Person A logged out it logged out Person B was logged out as well since the Formsauthentication ticket was no longer valid on the server. So yes they did have differnet cookies but the same formsauthentication ticket within each of thier cookies. One was however generated without logging in.
We also found this article but haven't been able to confirm if this is the cause. http://support.microsoft.com/default.aspx?scid=kb;EN-US;917072
I'll see what LiveHTTP tells me and will report back. Thanks.

Why does Person B get Person A's cookie? I'm assuming you mean Person B's session cookie is being associated with A's login ID. That's the nub of the problem.
It sounds to me that A's login ID is being stored in a place that could cross requests -- such as a temp file or in the DB -- without associating it with a session cookie. (Related issue: Page output is being cached, but not properly associated with or retrieved via the session cookie.) When session information is stored or cached, it must be associated with the cookie. Think in terms of session data belonging to a brower, not a login.
I would install the Firefox extension LiveHTTP and examine the request/response headers. My bet is, you'll see A and B have different cookies, but on the server they're both associated with the same login ID.

Sure, if those images (and CSS and static JS files, etc...) aren't being served as HTTPS, they'll be subject to caching by ISPs or other proxies (well, caches actually), along with their cookies.
There's a caching directive something like this:
Cache-control: no-cache="set-cookie,set-cookie2"
...which is supposed to instruct caches not to cache the "set-cookie" response headers, but I'm not sure how widely supported this is (despite it being standard).
Avoid set-cookie response headers when serving images if you can (might not be easy if you're not in complete control of session management). If a user must be authenticated to see certain images, then those images shouldn't be publicly cached anyway.

Sorry I forgot to mention that all traffic was going through port 443 as SSL. We are planning on removing the set cookie for images. However, we are little confused how this could happen when all traffic is processed through SSL.

All traffic was SSL... reviewing the IIS logs everything was going through port 443. The only caching that was being set was on the images to public as mentioned earlier. Our assumption is this is in result output caching causing the issue.

Are you sure you don't have something like output caching enabled on the page?

It may help to install Fiddler to investigate your http requests as specified above. Also, confirm the cookies are the same. Does your handler, or forms authentication system use a static object reference? You may have a race condition in your code. and aren't properly locking your resources.

Related

How does RememberMe setting work with WebSecurity in an MVC project?

In a sample/default MVC 4 project, I can see that when the User logs in with Remember Me checkbox on, the persistCookie parameter of the WebSecurity.Login method is set to true.
How exactly does that work? Where exactly is the value of persistCookie is saved? I looked through the tables that are created for the Security feature and do not see anywhere that the user is set to persist login.
What mechanism enables the user to log in? Is it simply the presence of the .ASPXAUTH cookie? Or does it actually compare the cookie value to something that I am not seeing.
How exactly does that work?
By creating a persistent cookie.
Where exactly is the value of persistCookie is saved?
As a file on the client machine so that it survives browser restarts.
What mechanism enables the user to log in?
This mechanism is called persistent cookie. A cookie is considered persistent if when being set the Expires property is being set to some date in the future. In this case the browser will store the cookie on the client computer as a file instead of keeping it in memory.
Here's an example of how creating a persistent cookie looks like in terms of the HTTP protocol:
Set-Cookie: CookieName=CookieValue;Path=/;Expires=Wed, 12-Oct-2016 21:47:09 GMT;
And here's how a setting a session cookie looks like which will not survive browser restarts:
Set-Cookie: CookieName=CookieValue;Path=/;
Now go ahead, download Fiddler and inspect the network traffic to see the difference.
The identity is stored in the cookie and decrypted upon each request.
Persistent cookie means that the cookie will be automatically attached to requests by the browser for some period of time.
No magic and also no need to store open sessions at the server side. As long as a cookie decrypts correctly, it is accepted as the server assumes that no one is able to forge a cookie on its own. This requires that the cookie value is encrypted or at least signed.

Cookie safety issues

How can I remember a user that is logged in without having a security issue? Currently, I am storing the id and a guid into two different cookies and compare them when there is no session alive. If it match then I re-create the session. Btw, both id and guid are nore encrypted.
Is this method safe enough, or should I follow a rather distinct way?
Since cookies can be easily stolen by use of XSS, does not matter if you place information in just one cookie or two, because a theft will take them all.
I have solved with a more complex procedure: I place one encrypted cookie divided in 2 parts (but 2 cookies will work as well), one fixed and the other variable each session. Both are saved also on server side to check: they are only session identifiers, no sensible information contained in the cookie, the correspondence with the user id is saved on the server.
If a fake user enters the account with a stolen cookie, the variable part (or cookie) will change, so when real user connects again he will not be able to enter and you will have the proof that an unauthorized access occurred: then you can delete the permanent session on server side (defined by the fixed part or cookie) in order to avoid any further access by the theft. The real user will re-login and create a new permanent session with a new cookie. You can also warn him that you saw a security flaw, suggesting him to reset password (operation that should never be accessible directly from cookie) or to use another browser for unsafe navigation.
If you save additional user information (user-agent, IP by location) you can check cookie validity also on them in order to avoid even the first entrance of the fake user.
I would recommend you using forms authentication for tracking logged in users in an ASP.NET application.

authCookie and relogin the user

Scenario:
I have a tricky situation where need to keep many modules happy [Google Analytics, etc, etc...]. Got a asp.net page in the project which initiates the request on the third party website (after clicking the Process button) and redirects the user to the third party website. Transaction is processed on their website and then the control is returned back to the current page on our site. You can relate this scenario with kind of Paypal processing too, but it's not paypal.
Issue:
If the session is time out, I want the user to be again authenticated when the control reaches our website after the processing is done on the third party website. So I am thinking of passing the authCookie information to the third party website and then when the control reaches our website back, I will have the authCookie information (imagine it is the scenario) and then want to log the user back in. Can I do that by just creating an authCookie again based on the username?
It really depends on the transaction processing system you are using. If you check the result of the transaction by calling their API, then the response usually have a user id or something that you can tie to user id. You can store the user name in the cookie, cookies are per domain or subdomain and it won't get sent to the transaction processing web site if it is in the different domain than yours, which is most likely the case. Get or derive the user name from the transaction result response, compare it to the one you obtain from your cookie. If they match up, sign in the user. Signing the user in just based on the cookie contents is risky in many respects. First of all anyone can set the cookie with any name in it to the browser. Second, if you are signing in a user just based on a cookie, you'll basically get never expiring session. This is not what you want. For added security you can check the transaction time from the transaction result response and refuse to sign in if it was too long ago.
Oh, and in you question you mention that you "need need to keep many modules happy" but you do not expand on as to what you mean by this. So I'm just simply ignoring this bit. Not sure what a happy module look like =)

ASP.NET Cookies

Guys, I am trying to make a website that keeps a cookie active, so long as the user is active in the site. My idea was to create a cookie on the main page of the site, like so:
HttpCookie cookie = new HttpCookie("KeepAlive","1");
cookie.Expires = DateTime.Now.AddMinutes(20);
Request.Cookies.Add(cookie);
If I have this code in my Page_Load event on every page, this should keep refreshing the cookie. If, after 20 minutes, the cookie expires, it will kick them back to the main screen. I just want to make sure I am going about this the right way.
Thanks
I think you should look at using session for that. With Session, you can set a timeout (20 minutes by default), and the rest will occur automatically (updating the active status, etc).
EDIT (more on Session):
By using session, the site user can be identified throughout their experience. This happens automatically, without any need for the developer to code for it or to test that it works.
Session is stored on the server, and is therefore safer (users can modify their cookies)
You can run code at the start, or at the end of any session (using a global.asax file)
Sessions can be setup as cookieless (users may have cookies disabled)
You can store c# objects in session variables so that they are available through the active session (stored in server memory).
I can't think of any more advantages in this case. I invite others to leave comments with their thoughts.
If you really want to use cookies for this, Yes, You are going the right way.
You need to add the cookie to the Response object, not the Request object.

if cookies are disabled, does asp.net store the cookie as a session cookie instead or not?

basically, if cookeis are disabled on the client, im wondering if this...
dim newCookie = New HttpCookie("cookieName", "cookieValue")
newCookie.Expires = DateTime.Now.AddDays(1)
response.cookies.add(newCookie)
notice i set a date, so it should be stored on disk, if cookies are disabled does asp.net automatically store this cookie as a session cookie (which is a cookie that lasts in browser memory until the user closes the browser, if i am not mistaken).... OR does asp.net not add the cookie at all (anywhere) in which case i would have to re-add the cookie to the collection without the date (which stores as a session cookie)... of course, this would require me doing the addition of a cookie twice... perhaps the second time unnecessarily if it is being stored in browsers memory anyway... im just trying not to store it twice as it's just bad code!! any ideas if i need to write another line or not? (which would be)...
response.cookies.add(New HttpCookie("cookieName", "cookieValue") ' session cookie in client browser memory
thanks guys
This MSDN article seems to indicate that there is no built in mechanism for compensating with the user disabling cookies. It also indicates that session state does not work without at least some level of cookies being enabled.
I thought that there was a mechanism for passing a query variable for the session id but skimming the article (quickly) I did not see this.
Hope that helps.
EDIT: It does say that you can use cookieless sessions (I thought you could). They use a separate mechanism to embed session ID in the pages and url links.
To follow up on GrayWizardx's reply, much of what was said is completely accurate.
If you are using a Cookie'd version of Session, and cookies are disabled then you are out of luck. But you have the option to have a cookieless version of the Session, which adds a string to the URL that shows the users session id. This is very ugly looking, and has always concerned me from a security perspective.
So you have three options (that I can think of off the top of my head):
1. Require cookies. This is not a bad thing, especially if your site is one that would have requiring cookies as normal.
2. Use ViewState.
3. Pass information from page to page within the URL. This, again worries me from a security perspective.

Categories

Resources