A hybrid webforms/mvc asp.net application using .Net Framework 4.7 has been tagged with the "Session Fixation" vulnerability in a Veracode dynamic scan. What this means is that Veracode gets the login page, alters the SessionId cookie (ASP.NET_SessionId), and then posts with a valid userid and password to do the login. ASP.Net logs in the user, but takes this altered SessionId cookie and continues to use it; that behavior of using that injected SessionId value is the flaw.
In other words, when Veracode gets the page the SessionId cookie might be "abc123". Veracode changes that cookie to "def456" and posts back. ASP.Net logs in the user and uses "def456" as the SessionId henceforth.
Per Veracode I must invalidate the ASP.Net_SessionID cookie created prior to a successful login. This is easy to do of course, I can simply reset the ASP.NET_SessionId cookie when the user successfully logs in. The problem is, this causes the user to be redirected right back to the login page. So what happens is this:
User submits the login page.
Server-side, if the login is successful, I reset the ASP.NET_SessionId to some new value (by calling SessionIDManager.SaveSessionID(), which in turn simply resets the ASP.Net_SessionID cookie).
The user is redirected to the application home page, and then immediately redirected back to the login page
The application uses forms authentication, with a webforms login page. The login page uses the asp.net Login control. In the "OnAuthenticate" event of this control I have code like this:
protected void Login1_Authenticate(object sender, AuthenticateEventArgs e)
{
bool b = Membership.Validateuser(Login1.UserName, Login1.Password);
if(b)
{
e.Authenticated = true;
SessionIDManager mgr = new SessionIDManager();
string newId = mgr.CreateSessionID(Context);
mgr.SaveSessionID(Context, newId, out bool redirected, out bool cookieAdded);
}
}
This runs without error. ASP.net redirects the user to the application home page. But then asp.net immediately redirects the user from the application home page back to the login page.
Is there any way to alter that SessionId cookie so that
Veracode's injected SessionId cookie value is abandoned.
The user stays authenticated and is not simply redirected back to the login page.
I've attempted running the code that alters the SessionId in various page events (PreInit, Load, etc) and all of them have the same result--the user is redirected back to the login page.
Please do not mark this question as already answered. There are several answers to this question on SO, all of which advise re-setting the SessionId cookie as I do above, and all of which have comments pointing out that this does not actually work.
After considerable back-and-forth the final reply from a Veracode consultant was the following, basically saying "don't worry about it." This is the reply from Veracode:
I also looked further into the dynamic findings from your application. The session ID that we are finding session fixation on, is not the ID you are using for authentication, and so the risk for your application is low. An attacker would not be able to gain access to an authenticated session of a user by controlling just the ASP.NET_SessionId cookie. By protecting the .ssoIIMAuth cookie your application is already preventing this sort of attack.
Related
Is there any solution for redirect user to login page, when cookie expires?
I create formsauthenticationticket and cookie. Expiration is set on 10minutes.
When expiration is over, and user doesn't make any request 20-minutes, and after that,
clicks he on some link, he would be redirected to login page and log in again.
I have HttpModule in assembly, which is referenced in web project.
In this module I have PreRequestHandlerExecute() event,
where I control on every request, if the user is authenticated and refresh timeout for cookie.
But If the user is not authenticated, he would be redirect to login page.
Is there any solution for this? I know about AuthorizeAttribute, but is there any other way to do this?
THANKS
Once the user's cookie has expired it won't be sent in the request, so you have no way of knowing who is a new user and who is a user who's cookie has expired because neither user will send a cookie with their page request.
One workaround is to set the cookie to 10 mins, but use the Meta Refresh tag to redirect to the login page after 9 mins 50 seconds. Note: the login page would need to log the user out too, otherwise it would refresh the session again.
When a user logs in through my login page, I authenticate them using FormsAuthentication, and set some Sessions that holds user specific info, like UserID and RoleID. I set site content based on these values.
The problem is when the session expires and the user is still signed in - things are messed up, because the session is null but the user is still signed in.
How can I keep them in sync with each other, so the session only expires if they're signed out or vs.
Thank you.
When the session has ended (Session_OnEnd) in global.asax, you can kill the forms authentication cookie. Doing so will redirect the user to the default page (or login page depending on how you set it up) upon any subsequent requests. You should also kill the authentication cookie when user has manually logged out - same effect.
To kill the authentication cookie:
FormsAuthentication.SignOut();
Our ASP.NET 4.0 application's forms authentication is set to cookieless="AutoDetect." I've noticed that if a user bookmarks our login page, the bookmark link is set to https://hostname.com/Login.aspx?AspxAutoDetectCookieSupport=1. If a user navigates to this directly from a new browser session and performs a valid login, the cookie is not set. If I navigate directly to that page, bu remove AspxAutoDetectCookieSupport from the query string, the cookie is created correctly.
If a user navigates directly to Default.aspx or the root directory, login functions correctly, even with AspxAutoDetectCookieSupport=1 tacked on to the query string.
When the user clicks the login button, we do a postback to the login page and manually check the users credentials against our database. If successful, we do:
FormsAuthentication.RedirectFromLoginPage(userName, false);
I've spent many hours debugging this, including looking at the ASP.NET forms authentication code in the reference source, and haven't been able to determine what is causing this. The only solution we have at the moment is telling users to remove the Login page from their bookmark URL and adding a bookmark button on our Login page for users to click.
Is there another solution to fix this forms authentication issue? Is it a but in forms authentication?
The problem here is that you are always using the RedirectFromLoginPage, whether or not the redirect location is provided. If it is not provided, then the redirect will fail. A proper solution to this would be to check the redirect url and redirect to the default.aspx if it is not available (source example borrowed from this blog article):
// Once the user's entered credentials are verified //
if(Request.Params["ReturnUrl"] != null)
{
FormsAuthentication.RedirectFromLoginPage(txtUserName.text, false);
}
else
{
FormsAuthentication.SetAuthcookie(txtUserName.text, false);
Response.Redirect("Default.aspx");
}
I use a ASP.Net login control in a straightforward manor however I have spotted that the ASPXAUTH cookie has an expiry date of {01/01/0001 00:00:00}. Should this not get to something to prevent hacker manipulation? I am not issuing the cookie myself I am letting .Net create it.
I have run a scan on my web app and it is able to store the ASPX cookie information, go to the log out page and then go to a page without a need to login I assume using the stored cookie information.
Using the application manually I am unable to do this, it always sends me to the login page when trying to access the page.
The logout page calls FormsAuthentication.SignOut()
EDIT: Turns out this is a known problem! Who knew! http://support.microsoft.com/kb/900111
You cannot read the cookies expiration date and time. The browser uses the cookies expiration date to determine whether or not to send the cookie to the server. If a cookie has expired, the browser does not send that cookie to the server with the page request, the cookie is deleted.
If the cookie has not expired the cookie is sent to the sever sans expiration information, since this information is utilized by the browser to determine if the cookie should be sent or not. You can read the expiration date from the request, but as you have discovered it returns a date time value of zero.
Try checking the expiry date of Response.Cookies collection in the LoggedIn event. This should yield the correct expiry date of the cookie.
protected void Login1_LoggedIn(object sender, System.EventArgs e)
{
HttpCookie cookie = Response.Cookies(".ASPXAUTH");
DateTime expires = cookie.Expires;
}
See Basics of Cookies in ASP.NET for more information.
If you save the value of the cookie, log out, and then re-present that cookie to the server, it will just log you in automatically as if you had never logged out.
This is because you can also tell the .NET framework to set a persistent authentication cookie (by default you can present this option to the user with the "Remember Me?" checkbox exposed with the DisplayRememberMe property of the Login control) so the expiry date would be a value in the future.
When the user comes back to the site and their browser sends the cookie, they are automatically logged in - so the behaviour you're seeing is be design.
If you need to be more secure, the easiest thing to do is add a method to the OnLoggedIn event of the login control, and set a session value (i.e. Session.Add("HasLoggedIn", true)) that you can then check elsewhere, and if it's not true, redirect to the login page:
if (null == Session["HasLoggedIn"] || !(bool)Session["HasLoggedIn"]) {
FormsAuthentication.RedirectToLoginPage();
}
Edit to respond to comment:
Which is why you're seeing the expiry date of 01/01/0001 00:00:00 - this will be deleted at the end of your session - or when you close the browser - but there's nothing fundamentally wrong with what you're seeing - just because you're not setting a persistent cookie doesn't mean that if you send a copy of an old cookie back to the server it won't log you in with it.
As I said, if you want to ensure that users have to log in each time (or to "resolve" this issue), add a session variable that you set when the user actually logs in, and reject all requests without it.
Further edit for second comment
From Explained: Forms Authentication:
Each time a subsequent request is received after authentication, the FormsAuthenticationModule class retrieves the authentication ticket from the authentication cookie, decrypts it, computes the hash value, and compares the MAC value to help ensure that the cookie has not been tampered with. Finally, the expiration time contained inside of the forms authentication ticket is verified.
Note ASP.NET does not depend on the expiration date of the cookie because this date could be easily forged.
So the cookie has to sent back to the server before the ticket has expired.
I have a ASP.Net application in my login page I call
FormsAuthentication.SignOut
Session.Abandon()
Session.Clear()
however the Appscan is taking the ASPXAUTH cookie value then after logout is able to re-inject the cookie value to gain access to protected pages.
Microsoft has acknowledged a problem but only offers advice not a fix - http://support.microsoft.com/kb/900111
Can someone provide examples how to fix this issue
One option is to have a UserSession table and insert a record into this table when the user logs in. When you logout either delete the entry or mark it invalid. On the secure pages, verify that a UserSession exists for the logged in user and redirect to a login page if it does not.
set a session value on login, clear it on log out and check it on each access to a secure page. The session value is not sent to the client and as such the client/attacker can not manipulate it.
walkthrough without session value cleared on exit :
user visits login page - generates viewstate
man-in-the-middle-hacker collects viewstate
user submits login form - generates auth cookies
man-in-the-middle-hacker collects auth cookies
user logs out - server clears users cookies
man-in-the-middle-hacker continues to use previous credentials completely unhindered
game over
walkthrough wit session value cleared on exit :
user visits login page - generates viewstate
man-in-the-middle-hacker collects viewstate
user submits login form - generates auth cookies
man-in-the-middle-hacker collects auth cookies
user logs out - server clears users cookies and sets its internal session flag value to null
man-in-the-middle-hacker continues to use previous credentials but because the session he is working with now has the value null server redirects to login page.
win!