Why is ASP.NET accepting externally created session identifiers? - asp.net

I have an ASP.NET 3.5 Web Site using the standard SQL Membership Provider.
The application has to pass the IBM Rational AppScan before we can push to production.
I am getting the error:
Severity: High
Test Type: Application
Vulnerable URL: http://mytestserver/myapp/login.aspx
Remediation Tasks: Do not accept externally created session identifiers
What can I do to fix this?
I am using SQL Membership Provider. Is this related? I am using the standard login controls too. I have the "Remember Me" turned off, and hidden.
Thanks.

This isn't a vulnerability (and I really don't like AppScan because of its false positives - the number of times I've had to explain CSRF cookies need not be linked to a session on my little open source project is getting annoying).
All that will happen in this case is the first time anything is stored in session state with a created session identifier a new session will be opened on the server, with nothing in it. If you're worried about session fixation then you can clear the cookie after authentication.
Session.Abandon();
Response.Cookies.Add(new HttpCookie("ASP.NET_SessionId", ""));
But with forms authentication the authentication details are not held in the session and so fixation is not a problem at all.
Frankly if you must pass security scans without anyone evaluating if the results are not false positives then that's a whole different problem.

You might need to change the default cookie settings to be unique to you app
Try setting a unique cookie path:
<forms name="YourAppName"
path="/FormsAuth" ... />
http://msdn.microsoft.com/en-us/library/ms998310.aspx#paght000012_additionalconsiderations
More reading...
http://msdn.microsoft.com/en-us/library/ms998258.aspx

It would seem RegenerateExpiredSessionId property is controlling this.
Do set it to true. Also keep time-out to a and low value, the tightest acceptable by users (e.g. 10 - 15 minutes).

Related

Forms Authentication SSO - Why does User.Identity.IsAuthenticated == false

I'm trying to set up SSO on two separate IIS web sites (with a common domain) using Forms Authentication. I'm using the common approach of setting the auth cookie to the common domain and using matching machine key to enable decryption.
This works with no issues on test sites that I created. However, when trying to implement this in a legacy Web Forms site, I'm running into something that I don't understand.
When I log into one site, the test code on the second site has the following results:
var cookie = FormsAuthentication.GetAuthCookie("username", false); // works
var ft = FormsAuthentication.Decrypt(cookie.Value); // returns correct info
var isAuthentication = User.Identity.IsAuthenticated; // false
As an added bonus, whenever I sign in one site the other gets signed out (happens both ways.)
There must be something fundamental that I'm missing here.
Why is User.Identity.IsAuthenticated set to false, even though the FormsAuthentication ticket seems to be decrypting with no issues?
UPDATE: as pointed out below - FormsAuthentication.GetAuthCookie is not a valid way to obtain the existing auth cookie. Which brings me to this: I can see the top domain cookie in the browser, but it doesn't show up in the request. I suspect this is where the problem is occuring.
Solution: Both sites were not targeting the same version of .Net Framework as specified by the web.config:
<httpRuntime targetFramework="4.5" />
<compilation debug="true" targetFramework="4.5" />
Updating both sites to target the same framework fixed the problem.
The GetAuthCookie creates a new cookie:
http://msdn.microsoft.com/en-us/library/vstudio/3fay1e4k(v=vs.100).aspx
Creates an authentication cookie for a given user name. This does not set the cookie as part of the outgoing response, so that an application can have more control over how the cookie is issued.
No wonder it works, it doesn't look into the existing cookie.
My theory is that you have your new sites on an x64 machine and the legacy website sits in an x86. The encryption differs in such scenario even if keys are the same. Another possible reason is a different version of .net as the encryption algorithm has been changed in .net 4.

ASP.NET session has expired or could not be found -> Because the Session.SessionID changes (Reporting Services)

1.-I'm using reporting services and sometimes I get this error ASP.NET session has expired or could not be found when I try to load a report.
2.-I realized that I get this error when the Session.SessionID property changes even though the user is the same. If it does not change, the report is loaded. I mean, if I refresh the report a number of times, whenever the Session.SessionID is the same than the last one, the report is loaded.
3.-Microsoft Documentation says:
When using cookie-based session state, ASP.NET does not allocate
storage for session data until the Session object is used. As a
result, a new session ID is generated for each page request until the
session object is accessed. If your application requires a static
session ID for the entire session, you can either implement the
Session_Start method in the application's Global.asax file and store
data in the Session object to fix the session ID, or you can use code
in another part of your application to explicitly store data in the
Session object.
If your application uses cookieless session state, the
session ID is generated on the first page view and is maintained for
the entire session.
The point is that I can not use a cookieless session state because I need cookies.
What could I do to avoid this error? Or What could I do to avoid the Session.SessionID to change on every request?
You are probably storing your session InProcess. Try changing it to session state server. You can find more details here.
I'm using report viewer 11.0.0; in your web config on system.web section, put the next configuration:
<sessionState timeout ="120" mode="InProc" cookieless="false" />
When you are generating the report (C# code bellow) in the reportviewer object change the KeepSessionAlive property to false and the AsynkRendering property to false, and that's all
this.rvReporte.KeepSessionAlive = false;
this.rvReporte.AsyncRendering = false;
(rvReporte) is a ReportViewer control located on my asp.net Form
This solution work for me, i hope that work for other people.
Regards
<httpCookies httpOnlyCookies="false" requireSSL="false"/>
Solved the problem.
Thanks to :
http://www.c-sharpcorner.com/Blogs/8786/reportviewer-Asp-Net-session-has-expired.aspx
I had the same issue on report viewer page when the web site was accessed from outside intranet. hardvin's suggestion saved the day for me which is to set
this.rvReporte.KeepSessionAlive = false;
this.rvReporte.AsyncRendering = false;
I changed the property on the control itself. I am using report viewer on a user control which raises a custom event for supplying parameters programmatically at the host page instead of prompting the users.
I solved this issue by setting AsyncRendering to false on reportviewer server control
Having the reportviewer being displayed in iframe was giving us this error. If displayed outside of iframe it works nice.
The reportviewer object has this configuration, AsyncRendering = false and KeepSessionAlive = true.
The webapp that has the reportviewer and set the session cookie in the browser was compiled with .net framework 4.6.1. We upgrade to 4.8 and put this in web.config
<sessionState cookieSameSite="None" />
<httpCookies requireSSL="true"/>
Só the solution is from https://learn.microsoft.com/en-us/aspnet/samesite/system-web-samesite#:~:text=The%20updated%20standard%20is%20not%20backward%20compatible%20with,SameSite%3DStrict.%20See%20Supporting%20older%20browsers%20in%20this%20document.
The answer given by Alexsandar is just one of the solution to this problem.
This link clearly explains what is the root cause for this problem and possible solutions:
http://blogs.msdn.com/b/brianhartman/archive/2009/02/15/did-your-session-really-expire.aspx
In case of Brian, the way he has descrived the problem, if he had just a single IIS server, using a session object in his code would have solved the problem because in that case, the SessionID which is passed in the request from browser to the server will get mapped to a corresponding sessionID on the server and hence the session expiry message will not come.
Setting the mode may only work in case of a server cluster where Brian had multiple IIS servers handling the same request. In that case an out of process mode will help to retrieve the session object from the Session Store irrespective of the server hit.
So based on this observation, I would conclude that Brian's problem was not related to cookies but to a server cluster. The information provided by Brian in his question and the subsequent solution misled me and hence this clarification. Hope it helps anyone looking for a similar problem.
Thanks,
Vipul
I have added the below-mentioned line on the web config file and it is working fine for me.
<sessionState mode="InProc" cookieless="true" timeout="3000" />
<pages enableSessionState="false" />
<customErrors mode="Off" />
Try removing SessionState="somevalue" tag from the top of your calling ASPX page. I'm using a custom SessionState and refuse to use InProc since I have multiple instances on Azure. You can even use AsyncRendering=True if you desire. Let me know if this did the trick for you.
For me, it turned out to be having more than one worker process for the app pool.
For me Azure hosted web app turning ON - ARR Affinity fixed the issue.
ARR Affinity ON

How to properly handle Forms Authentication Ticket when using a Cookie-less Session

I am pretty sure I do not have a unique problem, but I have searched all over google and this site and I haven't found a solid answer for what I am looking for. So I wanted to explain myself to see if I could get any help on this issue:
We (my co-workers and I) determined that we need have cookie-less Sessions because our users require multiple sessions to get their work done in a more productive fashion.
Example
Bob the user could have initiated a long running process in window A and in order to continue working Bob will open window B which spawns a new session. This is necessary in order to not disturb what is going on in window A. Every time Bob opens a new window, he has to log in again.
The Problem
I am not really sure if this is a real problem or not, hence my reason for asking. The problem I think I have discovered is that each time Bob logs in, the current Forms Authentication Ticket (and Cookie) are over-written. Now I do not understand how this is okay or why the previous Session/Window combo is still valid after Bob logs in a second time. Since the ticket was over-written doesn't that mean the first Session/Window combo should end because the ticket is no longer valid? This is with respect to:
Request.IsAuthenticated //Making sure the supplied ticket is valid
Questions
So since the Forms Authentication Ticket (and Cookie) are being over written, what does this mean?
Should I be concerned that the ticket (and Cookie) are being over written?
During login, should I be intercepting the ticket (if any) and checking for its expiration? If it is not expired should I try to renew the ticket or just make a new one?
FormsAuthentication.RenewTicketIfOld(ticket) //Just an example
If I am using a cookie-less session should I just use cookie-less Forms Authentication too? The point of doing this would be to make each Session/Window 100% independent of each other. No over-writing would occur anymore. Is there a draw back to this? I can't think of any.
PS: I know the cookie is just a container for what ever is being stored in it, like a Key Value pair.
Additonal Info...
Forms Authentication Ticket:
IsPersistent set to true
Ticket Version 2
Forms Cookie:
Key = FormsCookieName (from web.config tag)
Value = Hashed Ticket
Web.Config:
<sessionState
cookieless="true"
mode="SQLServer"
sqlConnectionString="..."
timeout="300"
regenerateExpiredSessionId="true" />
<forms name="FormsCookieName"
path="../"
loginUrl="Login.aspx"
protection="All"
timeout="300"
slidingExpiration="true" >
</forms>

Why might my users be being logged out after a minute or so?

I have a Asp Mvc 2 site using forms authentication. When I run it locally I can log in and stay logged in indefinitely.
However when I put it on the server I seem to only stay logged in for a few minutes and then seems to be logged out. I have looked at the cookies and there are 2 which seem relevant:
.ASPXAUTH which is a session cookie
.ASPXANONYMOUS which expires in 3 months.
When I refresh the page the cookies stay the same until I get logged out, when I seem to get a new .ASPXANONYMOUS cookie, but the .ASPXAUTH seems to be the same.
It seems that I might be able to stay logged in until I do something after a certain amount of time. If I submit a form as soon as I am logged in then it works ok, but if I keep submitting data again and again then after a minute or so, one of the submits will happen as a logged out user and not as the user who was logged in, which all the other submits worked as.
What might cause this behaviour and how can I track down what is different & change it so that I can stay logged in indefinitely?
EDIT,
its a single server, but after some more investigation and searching the likely candidate seems to be that I am using more than 100mb on the server and the application pool is getting recycled. I suppose now i need to know
How can I check how much memory I'm using.
What advice there is to reduce that.
Could it be that the ASP.NET application is being re-cycled or shutdown (e.g. due to idle timeout, or newly built/changed assemblies)?
When an ASP.NET web application starts up it will, by default, generate encryption keys for view state and session cookies. This will invalidate any such data originally served from an earlier run of the application (or from a different system).
To have sessions survive ASP.NET application cycles (and multi-server farms) you can specify the keys in your web.config:
<system.web>
...
<machineKey
decryption="AES"
validation="SHA1"
decryptionKey="..."
validationKey="..."
/>
where decryptionKey and validationKey are hex strings of length depending on the algorithm (with AES: 64 digits and SHA1: 128, for other algorithms check MSDN).
These keys should be cryptographically generated, and .NET has the types to do this which can be used from PowerShell:
$rng = New-Object "System.Security.Cryptography.RNGCryptoServiceProvider"
$bytes = [Array]::CreateInstance([byte], 16)
$rng.GetBytes($bytes)
$bytes | ForEach-Object -begin { $s = "" } -process { $s = $s + ("{0:X2}" -f $_) } -end { $s}
For AES use the above array length, for SHA1 use a length of 64.
It is quite likely that Session Timeout on the web server is configured to a much smaller timespan than you have set in your Form Authentication configuration in web.config.
The default Session Timeout is 20 minutes for IIS6 and IIS7.
If you have access to the web server's admin interface, you can raise the timeout via the GUI, but it can also be set from the config file if your IIS7 using the <sessionState> and <sessionPageState> sections:
http://msdn.microsoft.com/en-us/library/cc725820(v=ws.10).aspx
Check the webconfig authentication section
<authentication mode="Forms">
<forms name="UniqueName" loginUrl="login.aspx" path="/" >
</forms>
</authentication>
Ensure that the authentication cookie name for each hosted site is unique.
Came here with a similar issue, following the suggestion by #Richard, I looked at the Application Pools' recycling settings. What I found was the settings were changed and the Regular time intervals (in minutes) value was set to 1 minute. This meant that the app pool was being recycled each minute.
To change that, Right-click on the application pool, select the Recycling option, change the value under Regular time intervals (in minutes). I set it to the same value as the other Application Pools were using.
This change fixed the issue, turns out it was set to a low value a while back while during some misguided troubleshooting with an expired SSL certificate.
If none of these work, check in the Application Pools and ensure that the Idle Timeout is set to 20+ minutes. Click on the application pool, select the Advanced Settings link to the right, find the Process Model section, and increase the Idle Timeout value there.

<machineKey decryptionKey="AutoGenerate"... being ignored by IIS. Won't invalidate previous session's cookies

(See question below for more context):
Are there any situations in which
<machineKey
validationKey="AutoGenerate,IsolateApps"
decryptionKey="AutoGenerate,IsolateApps"/>
in web.config would fail to AutoGenerate a new machineKey on App Pool recycle? This is the behavior I'm seeing...
I'm using standard ASP.NET FormsAuthentication in an MVC app. If I log a user in using FormsAuthentication.GetAuthCookie and don't use a persistent cookie (relying on the browser's session to remember my authorized state), I would expect recycling the IIS App Pool to invalidate the session's knowledge of this cookie...and thus logout all users who don't have persistent cookies.
This DOES happen on one of my IIS installs (XP), but on a different IIS configuration (Server 2K3) the FormsAuthentication cookie (under the standard name ".ASPXAUTH") remains valid and continues to authorize the user.
Does anyone know why this is happening or what configuration controls this behavior?
Obviously recycling the app pool has no control over whether or not the browser still sends the .ASPXAUTH cookie (as long as I haven't closed my browser and the cookie hasn't expired).
In the case of the IIS install that properly denies authentication after a recycle, I can see the incoming cookie in Request.Cookies during the Application_BeginRequest event...but once control moves to the next event available in Global.asax.cs (Application_AuthenticateRequest), the cookie has been removed from the Request.Cookies collection.
Why does this not happen for both IIS/ASP.NET configurations?
In case this isn't clear, a simpler way of forming the question is:
Why does HttpContext.Current.Request.Cookies[".ASPXAUTH"] change from {System.Web.HttpCookie} to null when I step, in a single request, from Application_BeginRequest to Application_AuthenticateRequest?
More debugging information:
If I attach the following code to Global.asax.cs's FormsAuthentication_OnAuthenticate event...
var cookie = Request.Cookies[FormsAuthentication.FormsCookieName];
if (cookie != null)
{
var val = cookie.Value;
try
{
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(val);
}
catch (Exception)
{
}
}
...then during a request before I recycle the IIS App Pool, no exception will be caught. After recycling the IIS App Pool, when the exact same .ASPXAUTH cookie is sent from the browser, a Cryptographic exception is caught ("Padding is invalid and cannot be removed.")
Why is this?
Our application is stateless (no session required), yet we had a situation where an app pool recycle caused invalidation of all machinekey-encrypted cookies on a server environment (above described issue). This was caused because the machinekey changes with every recycle, which should not be the case.
The AutoGenerate modifier specifies that ASP.NET generates a random key and stores it in the Local Security Authority (LSA)
https://msdn.microsoft.com/en-us/library/w8h3skw9%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
"Local Security Authority (LSA)" means the user assigned to app pool, see below for more details as this turned out to be the problem.
The issue lied in the fact that we are using a dedicated user account for running the application pool, and simply creating the user and then assigning it to the app pool did not seem to trigger the creation of the registry section where the machine key is then stored. You can verify this yourself by checking registry
HKLM/SOFTWARE/Microsoft/Windows NT/CurrentVersion/ProfileList (for getting the SID of the user you just created; if the user is not there, then this is already a bad sign)
HKU/[UserSIDFromBefore]/Software/Microsoft/ASP.NET/... (a machine key should be stored there)
The solution was to logon as that user once on the computer (normal Windows logon screen) so that the relevant registry sections are created. There might be quicker or more subtle ways to establish the registry sections though.
Internet Information Services (IIS) 7.0 (Windows Vista, Windows Server 2008) introduced application pool identity, a new isolation mechanism that helps provide increased security for servers that run ASP.NET applications. However, sites that are running under the application pool identity do not have access to the HKCU registry. This is where the ASP.NET runtime stores its auto-generated keys. The result is that ASP.NET cannot persist the auto-generated key when the application pool is reset. Therefore, every time w3wp.exe is reset, a new temporary key is generated.
Note This is not an issue in IIS 7.5 (Windows 7, Windows Server 2008 R2) and later versions. On these versions of IIS, ASP.NET can persist its auto-generated keys in a different location that survives application pool resets.
https://support.microsoft.com/en-us/help/2915218/resolving-view-state-message-authentication-code-mac-errors
Forms Authentication cookies have nothing to do with Session state.

Resources