OWASP Application Security Verification Standard - V3 and using with JSF - security

At the moment I'm dealing with implementing everything is to be safe against the security risks of the Top 10 Project
For #4 of the Top 10 - Insecure Direct Object References the OWASP refers to the OWASP Application Security Verification Standard
So I was reading all the suff in V3, but I have now some questions implementing it.
I'm using JBoss-AS 7.0.1 with Java EE6 and JSF 2.0
V3.4 Verify that the session id is never disclosed other than in cookie headers; particularly in URLs, error messages, or logs. This includes verifying that the application does not support URL rewriting of session cookies.
I read some articles here on stackoverflow how to avoid that the jesssion is in the URL for the first time a user is visiting the side...
But many answers are like: use the URL rewriting ... what does this means in contrast to the does not support URL rewriting of session cookies
What is the normal way to deal with jsessions on the first entry? What is a save way to handle it?
V3.10: Verify that only session ids generated by the application framework are recognized as valid by the application.
How you do this in JSF2.0 / JavaEE?
V3.12: Verify that cookies which contain authenticated session tokens/ids have their domain and path set to an appropriately restrictive value for that site.
What does this mean? When i look with my Firebug into the the cookie, I run the webapp from the URL http://localhost:8080/projectname/
and in the cookie i get: Path: /projectname
is this what the OWASP means with have their domain and path set to an appropriately restrictive value for that site. ?
Thank you!

V3.4 Verify that the session id is never disclosed other than in cookie headers; particularly in URLs, error messages, or logs. This includes verifying that the application does not support URL rewriting of session cookies.
The servlet container is by default configured to support session tracking by cookies and URLs. The session tracking by URL is also known as "URL rewriting" wherein you see the ;jsessionid=[session id] to appear in URLs. This will be triggered automatically when the client has cookies disabled. To disable tracking by URL, you need to explicitly specify a tracking mode by cookie only. Add this to the webapp's web.xml:
<session-config>
<tracking-mode>COOKIE</tracking-mode>
</session-config>
Further you need to make sure that the JSF code is nowhere printing the session ID to the HTML output by among others <h:outputText value="#{session.id}" />.
V3.10: Verify that only session ids generated by the application framework are recognized as valid by the application.
The servlet container will by default already do that. Only Tomcat 6.x (and inherently thus also JBoss 5.x) had the security issue that when the server-wide session sharing is been enabled, then the server will use exactly the session ID as supplied by the client in the Cookie request header. Tomcat 7.x (and inherently thus also JBoss 6.x/7.x) will not do that anymore. See also among others the Tomcat 6.x <Connector> documentation for some more background information (check the emptySessionPath attribute description).
V3.12: Verify that cookies which contain authenticated session tokens/ids have their domain and path set to an appropriately restrictive value for that site.
The servlet container will by default already do that. Only when you configure the servlet container to use server-wide session sharing (thus, the same session is been shared between all deployed applications), then it violates the rule. See also the previous point.
Please note that most of those rules have very little to do with JSF. They have more to do with general server and webapp configuration. JSF is merely a component based MVC framework.

Related

Web Security: Preventing CSRF attack

I am following this tutorial for an application based in spring framework 3.2.4
http://springdiaries.blogspot.be/2012/12/web-security-preventing-csrf-attack.html#comment-form
The point is that I've checked all the objects in the session and I haven't found any object with the Key OWASP_CSRFTOKEN, and that is susposius that in not working well ?
This is not exactly an answer to your question, which is unfortunately too vague to answer without a magical crystal ball ^^, but here are some things you should try:
Check out your request is not coming from an URL matching one of the
the unprotected patterns defined in the
Owasp.CsrfGuard.properties configuration file (These values are
from the OWASP docs; you should have set up different ones):
.
org.owasp.csrfguard.unprotected.Tag=/Owasp.CsrfGuard.Test/tag.jsp
org.owasp.csrfguard.unprotected.JavaScriptServlet=/Owasp.CsrfGuard.Test/JavaScriptServlet
org.owasp.csrfguard.unprotected.Html=*.html
org.owasp.csrfguard.unprotected.Public=/MySite/Public/*
Check your web server / servlet container log for errors, both on startup / application load and upon receiving a client request.
Set breakpoints here and here and launch the application in
debug mode to make sure your class is being loaded and the token is
being requested.
Review one by one all the configuration parameters.
Read the project wiki and the docs carefully:
Configuration
Installation
User Manual
You won't have to modify your DB schema in anyway. That's not how OWASP CRSF guard works (the generated tokens are stored in-session, not persisted in the database).
It's also worth mention that you are following an outdated blog post: If you are using Spring you don't need to be using OWASP CSRF guard at all. You should be using spring-security authentication which has built in CSRF protection, which is much easier to set-up.
Check out the tutorial on this page on how to set up HTML form + SQL database based authentication with CSRF protection (Also, don't miss out the bcrypt password hashing one; It is very easy to set up and at some point you'll be glad you are storing safe hashes instead of clear text passwords).
You'll see you also won't have to modify the db at all to add CSRF protection using spring-security because the CSRF protection token is session-stored.
The set up takes 5-15 minutes; 30 minutes tops for a Spring neophite. In a nutshell, the framework takes care of generating and validating the token and returning an authentication error on invalid requests.
You just have to include the <csrf /> tag inside your spring-security.xml configuration file <http> tag.
If you are using html form based authentication, you'll also have to include the following hidden input inside the form:
<input type="hidden" name="${_csrf.parameterName}"
value="${_csrf.token}" />

URL Rewriting vulnerability

We modified our Session handling from cookie based to URL Rewriting. By doing this the session id gets transmitted as part of the URL.
Now there is a vulnerability issue, where whoever uses this URL will be able to log in into the system.
To resolve this issue we have done the following
[1] A HTTP Session Listener has been created to maintain list of HTTP sessions.
Listener reacts on the events when session are created or destroyed.
[2] A Session Filter has been created to verify HTTP Session and check its integrity against HTTP Request attributes
Session will be invalidated in case Request attributes (identifying the client origin) do not match original attributes stored with session. (to block the session hijack attempt)
However i think that this has a gap, when you are trying to access over a proxy etc.
Is there any other effective solution for this?
Also we cannot use third party libraries to resolve this because of the nature of the produce.
So you need to be doubly careful with session ID likes this: users share URLs! The definitive advice on the subject comes from OWASP:
https://www.owasp.org/index.php/Session_Management_Cheat_Sheet
But I think you should consider the following additional controls:
Rotating the session key on each request. This is only practical with simple web applications though. It'll cause problems undoubtedly with AJAX and might be difficult to manage if the user is likely to open a second tab on the application.
Shorter timeouts.
I am presuming that in the 'HTTP Request Attributes' you mention you are already picking up the User-agent, source IP address and invalidating the session if these are inconsistent.
If you are using SSL it might be possible to do a great solution where the session ID is tied to the SSL connection (Apache, for example, exposes this in a SSL_SESSION_ID environment variable). But this information might not be available to your application.

Creating a new JSESSIONID after authentication

When a user hits login page of a Portal (it could be Liferay, Jboss Portal..), JSESSIONID cookieis created by the container. After entering credentials in the login page, same JSESSIONID gets carried over.
Here, end user will come to know the JSESSIONIDbefore he could get authenticated (by checking the JSESSIONID in the login page). This will increase vulnerability of the site for hacking because one can know the JSESSIONID before one gets authenticated.
This post advices to have a different JSESSIONID after authentication.
So, creating a new JSESSIOND can be achieved by Portal server being used (am using Liferay CE 6.0) or it has to be handled by web application developer? If it has to be handled by web application developer what is the best way to do? request.getSession(true) is the only option?? If I need to instruct Liferay to create a new JSESSIONID after authentication how it can be done?
This looks a lot like the session fixation problem I solved for Liferay 5.2.5 a long time ago. The solution consists of creating a custom Tomcat Valve that will force a new session ID. So the solution isn't really specific for Liferay and is dependent on if you use Tomcat or not.
I suspect it shouldn't be too difficult to adapt my old solution to a newer Liferay/Tomcat combination. You can find the necessary information about my solution in my old and currently unmaintained blog (if I only had more time...): Fixing session fixation in Liferay
The problem here is not that the user knows the session ID (the user always knows it, it is sent by his browser). The attack scenario is that the user, while logged out, clicks on the link that already has JSESSIONID embedded, then authenticates and this session becomes a logged-in session. Now someone who initially created the link can use the same session to act as the user. More details at https://en.wikipedia.org/wiki/Session_fixation
So yes, use the web or app server to re-set session ID after a user authenticates. You do not need to write it yourself. For Tomcat 7: http://www.tomcatexpert.com/blog/2011/04/25/session-fixation-protection
You can fix this issue by setting the following property to true like Liferay has as default.
#
# Set this to true to invalidate the session when a user logs into the
# portal. This helps prevents phishing. Set this to false if you need the
# guest user and the authenticated user to have the same session.
#
# Set this to false if the property "company.security.auth.requires.https"
# is set to true and you want to maintain the same credentials across HTTP
# and HTTPS sessions.
#
session.enable.phishing.protection=true
#Thiago:
This session.enable.phishing.protection=true is by default true in portal.properties. Anyhow, I have added this entry in portal-ext.properties. But, even then JSESSIONID remains same before and after login.
I have implemented a filter as per this link. After implementing this filter, when I hit login page of Liferay, one JSESSIONID gets created. After I enter the credentials and login, the same JSESSIONID is retained.
I have implemented this filter in a Servlet and not in any of my Portlets or in Liferay's ROOT application. My Servlet is deployed in LR + Jboss AS bundle. Am first hitting the Servlet and from here I have a link which will redirect to Liferay's login page. I have implemented this filter in my Servlet because Container will append JSESSIONID for first time request as it doesn't know if cookies are enabled or not. Since, JSESSIONID is getting appended, am not able to retrieve my images in Servlet (because url is myImage.jpg;jsessionid=). Hence, I have implemented this filter.
Is this filter conflicting with Liferay's configuration? Even after setting session.enable.phishing.protection=true same JSESSIONID is retained means what else could be the problem?
Put this code inside the portal-ext.properties.
It will fix the problem, each and every time logged in, new session id will be generated.
session.enable.phishing.protection=true
com.liferay.util.servlet.SessionParameters=true

socialauth - can you use same session across a redirect?

I'm trying to use socialauth to login with google, facebook et al (I'll assume google here) and have a question about how it works. I'm using JSF 2 without Seam. The basic idea is that you:
make a few API calls indicating that you want to login with google.
make another API call which returns a URL for google.
supply a result URL which will be used by google to redirect back to your site.
redirect to the google URL.
then google will either immediately redirect back to your site or first ask for login details.
My confusion is about linking together the data from the outbound and inbound sides. In the getting started page (linked above) they suggest this:
Outbound
SocialAuthManager manager = new SocialAuthManager();
String successUrl = "http://my.domain.com/socialauthd/successAction.xhtml";
String url = manager.getAuthenticationUrl(id, successUrl);
// Store in session
session.setAttribute("authManager", manager);
Inbound
// get the auth provider manager from session
SocialAuthManager manager = (SocialAuthManager)session.getAttribute("authManager");
The problem I have is that I don't see how this can work, and it doesn't in testing. They suggest storing a reference to an instance of SocialAuthManager in the session, however when the request is received from google a new session is created. It doesn't have the JSESSIONID cookie and so isn't part of the session that sent the request to google in the first place.
To work around this I got a unique per-request id from the socialauth api (openid.assoc_handle - it's sent as a query param), put it in a concurrentHashMap in an app scoped bean, and retrieve the reference in a preRenderView listener in the completion page (successUrl - badly named in the example as it is called either way).
This all seems like a lot of hassle for something that isn't included in the documentation. I've tried this with #RequestScoped CDI beans, although I usually use CODI #ViewAccessScoped. With CODI I've tried adding the windowId to the success URL, and also adding the JSESSIONID cookie to the redirect, but neither approaches work. I don't think the bean scope is relevant but the more information the better.
I could dive into the spring, seam and struts examples but for a pure EE 6 developer it's a lot of overhead, and with a better understanding of this issue I can produce a simple, working, JSF only example which I will make available to the socialauth team for use on google code.
Am I missing something obvious or does this just have to be complicated? and if so why did they document an approach that simply doesn't work?
Edit: I think that the successUrl may be named more appropriately than I thought, because in testing with Yahoo I realise that you won't be redirected back to your own site unless correct login details are provided. I expect this is the same for all providers. I have added some comments regarding this solution to the socialauth site, and also to an issue I logged about this problem (neither of which have received any response from anyone involved in the socialauth project).
Include the jsessionid path parameter in the callback URL.
String successUrl = "http://my.domain.com/socialauthd/successAction.xhtml"
+ ";jsessionid=" + session.getId();
Note that this is not specific to JSF API, but to Servlet API (chapter 7.1.3, URL rewriting).

cookie storing strategies and tabbed browsing of different JSF applications giving "View could not be restored"

I launched two different instances of JBoss AS 7.1 on my machine on two different ports and deployed the same application (with the same root context) to both of them. This configuration gave me, deterministically, the following exception as I was doing tabbed browsing with the same browser (either Chrome or Firefox or Conkeror):
javax.servlet.ServletException: viewId:/whatever.xhtml - View /whatever.xhtml could not be restored.
javax.faces.webapp.FacesServlet.service(FacesServlet.java:606)
org.jboss.weld.servlet.ConversationPropagationFilter.doFilter(ConversationPropagationFilter.java:62)
When I was browsing with different browsers things were ok.
Upon further investigation on how different browsers store cookies I discovered that the combination (IP / path) has to be unique to avoid such tabbed browsing problems and that the port does not come into play. I.e. cookies are stored per IP and per path but not per port. So doing tabbed browsing with the same browser on two different applications deployed on the same IP and path (but obviously on separate ports) will result in expired views as the browser mixes up the two sessions. I recognize that my setting is unlikely to arise in a production environment but I would like to ask:
is there any standard that defines this cookie organizing behavior?
are there any best practices one must be aware of in order to avoid session mixups when doing tabbed browsing in multiple JSF applications?
does the javax.faces.STATE_SAVING_METHOD have any bearing on this (in my setting it was set to "server") ?
is there any standard that defines this cookie organizing behavior?
Version 0 cookies (Netscape spec cookies) do not support ports in any way.
Version 1 cookies (RFC2965 spec cookies) supports the Port attribute. If this is absent, then version 0 behavior is used.
The average servletcontainer sets the JSESSIONID cookie as a version 0 cookie. You could theoretically override this by providing a custom "Session Manager" in the servletcontainer. Note that MSIE 9 does still not support version 1 cookies.
are there any best practices one must be aware of in order to avoid session mixups when doing tabbed browsing in multiple JSF applications?
The canonical approach in real world projects is to use a different subdomain (on same port!). E.g. beta.example.com, dev.example.com, update.example.com, test.example.com, etc.
does the javax.faces.STATE_SAVING_METHOD have any bearing on this (in my setting it was set to "server") ?
If you set it to client, then the ViewExpiredException will indeed disappear as the view is not stored in the session anymore, but instead in a hidden field of the form. But you might still face other session-related trouble, for sure if you're storing some stuff in the session, such as session scoped managed beans and the logged-in user.

Resources