In Servlet 3.0 complaint application servers I can set the HttpOnly and secure flags for the session cookie (JSESSIONID) by adding the following to the web.xml:
<session-config>
<cookie-config>
<secure>true</secure>
<http-only>true</http-only>
</cookie-config>
</session-config>
However, the application I'm working on is to be deployed in Websphere 7, which is Servlet 2.5 complaint and it fails to start if I add the above to the web.xml
Is there any other declarative way or setting in Websphere 7 configuration to turn on the HttpOnly and secure flags for the session cookie?
If not, what would be the best approach to accomplish that programmatically?
I think in WebSphere 7 you may have to delve into the administrative console. As ever the WebSphere documentation seems poor but seems to suggest setting the com.ibm.ws.security.addHttpOnlyAttributeToCookies property:
Both the Secure flag and the HTTPOnly flag are enabled by setting the WebSphere Application Server property:
com.ibm.ws.security.addHttpOnlyAttributeToCookies.
I found this, which I hope is applicable to WAS7. Can you try please (I only have WAS 8 at the moment on my system):
JSESSIONID cookie:
Secure Flag:
The Secure flag can be set within the WebSphere Application Server
administrative interface by selecting AppServer->[Server Name]->Web
Container Settings->Session Management. Check the checkbox for
“Restrict cookies to HTTPS Sessions”.
HTTPOnly Flag:
The HTTPOnly attribute cannot currently be set on this cookie. This
is registered on the IBM site as APAR PK98436. The fix for this APAR
is currently targeted for inclusion in Fix Packs 6.1.0.31 and 7.0.0.9,
which are not yet available. With this APAR in place, the HTTPOnly
flag can be set on the JSESSIONID cookie by way of the property name:
com.ibm.ws.webcontainer.httpOnlyCookies. Refer to the following
technote for instructions on enabling WebContainer custom properties.
The com.ibm.ws.webcontainer.httpOnlyCookies property is documented on the WAS 7 help site.
To set Secure flag to JSESSIONID cookie (same for WebSphere 7.x and 8.x):
log in log in WebSphere admin console
Navigate to Server > Server types > WebSphere application servers
Click on server name (default is server1)
Click on link Web Container settings > Web Container
Click on link Session Management
Click on link Enable Cookies. This bit a litle bit confusing, you have to
click on text not on the check box
select option (check box) Restrict cookies to HTTPS sessions
Save changes
To set HttpOnly flag in WebSphere 8.x to JSESSIONID cookie
log in log in WebSphere admin console
Navigate to Server > Server types > WebSphere application servers
Click on server name (default is server1)
Click on link Web Container settings > Web Container
Click on link Session Management
Click on link Enable Cookies. This bit a litle bit confusing, you have to click on text not on the check box
select option (check box) Set session cookies to HTTPOnly to help prevent cross-site scripting attacks
Save changes
To set HttpOnly flag in WebSphere 7.x to JSESSIONID cookie
log in log in WebSphere admin console
Navigate to Server > Server types > WebSphere application servers
Click on server name (default is server1)
Click on link Web Container settings > Web Container
Click on link Custom Proprties
Click on button New
Enter name: com.ibm.ws.webcontainer.httpOnlyCookies value:* (HttpOnly will be set on all cookies not only JSESSIONID)
Click on OK button
Save changes
In WebSphere 7, you can find this in the administration console under Servers > WebSphere application servers > [Server Name] > Session management (under "Container Settings") > Enable cookies > Restrict cookies to HTTPS sessions.
Related
I have the following setup:
IIS 8.0
a web handler call it test.ashx
Impersonation & Windows Authentication are both configured. Kerberos is showing as the authentication type.
test.ashx uses the unmanaged API: CreateProcessAsUser() method to run "cmd.exe /c myScript.cmd"
I put statements in myScript.cmd and see that it is running as the requesting user as I need it to. The problem I am experiencing is that the script cannot reference network files (either mapped drives or UNC path)
I need myScript.cmd to run as the requesting user and to be able to access network file resources. How do I get this to work?
I found one item that made a big difference on getting kerberos authentication to work, which is required to do impersonation and delegation. In IIS Manager I had to choose the web site, then run the Configuration Editor. Once it opened I had to choose the as from: DefaultWebSiteWeb.Config, and as the section: system.webServer/security/authentication/windowsAuthentication. Then set: useAppPoolCredentials = True. Note: useKernelMode was already set to true.
Additionally, for the web site I have the following set for Authentication:
ASP.NET: Enabled
Windows Authentication: Enabled, Provider: Negotiate, Kernel mode enabled.
Now my ASHX web handler (in C#) can start a process as the user, run a .cmd file that accesses network resources.
I have four different server and a load balancer. I want to use captcha control. I did something with it this way:
I created a handler.ashx to create the captcha image. This handler is used in the Main page. I keep the captcha control password in session while creating the captcha control. Then I compared password typed by the user with the password in the session. It works very well, but only on one server.
It doesn't run correctly with four servers. Although the user enters the correct password every time, it sometimes matches with the session password and sometimes doesn't match. I think the problem reason is this:
For Example :
A,B,C and D are the four servers. The load balancer routes the first request to A server. Which opens the main page from A server and creates password '123456'. This is stored in session on A server. Then user typed in the password and clicked button. Now the load balancer routes this request to the B server. Because session in B Sever is null, the passwords don't match.
My web.config has this,
<sessionState mode="StateServer" stateConnectionString="tcpip=127.0.0.1:42424"/>
But It still doesnt work.
What should I do ?
So first thing (just to make sure) - I believe that this connection string is just an example because 127.0.0.1 is localhost and it wouldn't have chance to work ;).
Now I will assume that you have chosen server A for you state server. Please check following things:
"ASP.NET State Service" is up and running on the server A (it's disabled by default, you can check that in Administrative Tools --> Services)
the stateConnectionString in servers B, C and D is "tcpip=[Server A IP Address or Network Name]:42424" (it can be 127.0.0.1 only on server A)
servers can communicate between each other using TCP/IP via port 42424 (firewalls etc.)
Please remember that if you have changed configuration of "ASP.NET State Service" on server A to not use default port (42424), you must reflect that in your connection strings.
Sometimes it's easier to configure "SQL Server Mode" instead of "State Server Mode" so you might want to consider that. You can find more details here.
You need to use StateServer or SqlServer for managing the session state and they should be out of your firewall network that is used to balance the load.
http://www.hanselman.com/blog/LoadBalancingAndASPNET.aspx
When using Session State Server, there are few things which need to setup.
Setup ASP.Net State Service on the machine which you want as a StateServer.
net start aspstate
Change Session Mode in Web.Config File for all web applications and point to a StateServer
<system.web>
<!-- ... -->
<sessionState
mode="StateServer"
stateConnectionString="tcpip=your_server_ip:42424"
cookieless="false"
timeout="20" />
<!-- ... -->
</system.web>
3 . All Web Server the use same <machinekey> configuration
<machineKey
validationKey="1234567890123456789012345678901234567890AAAAAAAAAA"
decryptionKey="123456789012345678901234567890123456789012345678"
validation="SHA1"
decryption="Auto"
/>
(Note:To maintain session state across different Web servers in the Web farm, the application path of the Web site (for example, \LM\W3SVC\2) in the Microsoft Internet Information Services (IIS) metabase must be the same for all of the Web servers in the Web farm. The case also needs to be the same because the application path is case-sensitive.
[http://support.microsoft.com/kb/325056])
I have an ASP.NET application that executes a WMI call to a remote system. The application Web.config contains <identity impersonate="true"> and <authentication mode="Windows"> options which, as I understand, should force the application code to be executed on behalf of the application user.
The problem is that I get "Access is denied" error, despite the fact I can successfully execute the my WMI request from PowerShell console on the same host under the same user to the remote server in question.
// this doesn't work
ManagementScope scope = new ManagementScope();
scope.Path.NamespacePath = "root\\virtualization";
scope.Path.Server = "vs01";
scope.Connect(); // <-- here comes exception
# this works just fine
Get-WmiObject -Namespace 'root\virtualization' -Class Msvm_ComputerSystem -ComputerName vs01
Dumping HttpContext.Current.User.Identity.Name, System.Security.Principal.WindowsIdentity.GetCurrent().Name, System.Threading.Thread.CurrentPrincipal.Identity.Name properties suggest that impersonation works as expected.
Ideas? Could the issue be some kind of .NET or IIS security?
You need to have a domain administrator enable Delegation for your web server machine. This is a security feature of Kerberos. By default an intermediate server (in this case your web server) is not allowed to pass the impersonation context of a client to the remote server unless it has been given Delegation permission. If you don't do this the remote target server will see the request coming in as Anonymous User... which if its properly secured will be denied access.
Note its a common policy to only allow an intermediate server to delegate to specific target servers (called constrained delegation), so if your web app needs to be able to call WMI on any server in your network you may have problem. Talk to your domain admin.
Our code relies on checking the Context.User.Identity value in the Global.asax Application_AuthenticateRequest(...) method to retrieve some information about the logged in user. This works fine in classic mode but when I flip IIS to use the Integrated Pipeline "Context.User" comes back as null, but only intermittently. Any ideas why?
I have < authentication mode="Windows"> and only Windows Auth enabled in the Virtual Directory.
Integrated mode means that the pipeline events of ASP.NET run at the same time as the IIS pipeline, what it means is that:
1) In Classic Mode - AuthenticateRequest in ASP.NET runs way after IIS already did the authentication (using Windows auth maybe or basic, etc) and so you will get the User Identity set to it.
2) In IntegratedMode - AuthenticateRequest will run at the "same time" in both which will cause it to have a null there. You should consider using PostAuthenticateRequest if you want to reliably get a User Identity (of course provided you have an authentication module enabled)
(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.