Protecting against XSRF attacks GWTP app - security

I am trying for protecting against XSRF attacks GWTP app. The problem facing like JSESSION easliy get in paroz testing tool, using that tools if user is already logged in and at the same time made same server request by paroz. it execute same transaction with updated value, which is a security problem.
To stop that one, Required to create per request new cookie and send from client to server.
#SecurityCookie
public static final String securityCookieName = getRandomString(); //Not work
For ClientModule
public class ClientModule extends AbstractPresenterModule {
#Override
protected void configure() {
bindConstant().annotatedWith(SecurityCookie.class).to(
NameTokens.securityCookieName);
And in DispatchServletModule
public class DispatchServletModule extends ServletModule {
#Override
public void configureServlets() {
bindConstant().annotatedWith(SecurityCookie.class).to(NameTokens.securityCookieName);
I want to generate cookie randomally instead of 'JSESSIONID'. How/where to do? And what is a proper way to regenerate cookie per request in GWTP?

For generic gwt, see XSRF protection
It's for RPC calls:
RPC XSRF protection is built using RpcToken feature, which lets a
developer set a token on a RPC endpoint using HasRpcToken interface
and have that token included with each RPC call made via that
endpoint.
You have to rewrite your rcp calls to be invoked in the callback that obtained the token but it's not so difficult to implement.
EDIT
I don't understand the need for a randomized cookie name. For the standard GWT protection, you have to specify a set name:
<context-param>
<param-name>gwt.xsrf.session_cookie_name</param-name>
<param-value>JSESSIONID</param-value>
</context-param>
The docs you cited for gwtp state explicitly:
To protect your application against XSRF attacks, as described in
Security for GWT Applications , you have to specify the name of the
security cookie you want to use. Do this by binding a string constant
annotated with #SecurityCookie both on the client and on the server.
I think it doesn't matter if the user is logged in. Malicious code can not read the JSESSIONID cookie (or whatever cookie you specify) and it needs the value of the cookie (sure it can send the cookie but that does nothing because malicious code need the value so it can calculate a unique token that you send every request). This is what the docs say:
Default XSRF protection implementation derives XSRF token from a
session authentication cookie by generating an MD5 hash of the session
cookie value and using the resulting hash as XSRF token. This
stateless XSRF protection implementation relies on the fact that
attacker doesn't have access to the session cookie and thus is unable
to generate valid XSRF token
So you do need to specify your cookie name in order to configure it to work, or GWT can not use the value of that cookie to generate the end point token that you obtain prior to every rpc call and include with every rpc call.
So while I don't think you need to implement your own XSRF protection since you are not using standard gwt, I do think you do need to follow the docs you cite to configure gwtp to use it's implementation of xsrf protection.

Related

Is it necessary to generate anti-XSRF/CSRF token in server side?

Almost all doc about anti-CSRF mechanism states that CSRF token should be generated in server side. However, I'm wondering whether it is necessary.
I want to implement anti-CSRF in these steps:
There is no server-side-generated CSRF token;
In browser side, on every AJAX or form submission, our JavaScript generates a random string as token. This token is written into cookie csrf before actual AJAX or form submission happens; and the token is added to parameter as _csrf.
In server side, each request is supposed to have cookie csrf and submitted argument _csrf. These two values are compared. If they are different, it means it is a CSRF attack.
The server side doesn't need to issue CSRF token, just do the checking; and the token is totally generated in browser side. Of course, this is only for anti-CSRF. There should be authentication process in server side to validate user id.
It sounds a valid solution for CSRF, but I'm not sure why there is no documentation about this approach.
Is there any fault in this anti-CSRF mechanism?
As far as I understood, what you want to do is to create your anti-CSRF on the client side, store it in a cookie and also add it as a request parameter, so when the server reads your request, just verifies that your CSRF token cookie and parameter matches, and it decides if it's a valid request or not.
The reason to generate the anti-forgery token on the server side, is that the server will create that token and only the server will know the correct value, so if that parameter is slightly tampered on the client side, it will not be identical to the one stored in the server, and that will be enough to flag the request as a cross site request forgery attack.
Any client-side generated data can be tampered by an attacker and because of that, you can't rely on that information, for example, in your approach, you create a random value in your client side and you assign that value to your CSRF cookie and to your _csrf parameter, let's say that your value is "h246drvhd4t2cd98", but since you're only verifying that your 2 variables from the client side have the same value, an attacker can easily just create his CSRF cookie and variable with a value like "I'mByPassingThis" on both of them and your server will flag it as a valid request, so you're not getting security at all.
On the other hand, if the token is generated in the server, the attacker has no way to know the expected value, and that value will be different on every request, so the attacker's best approach will be just to try to guess it, which should be virtually impossible, unless you're using a predictable random number generator on the server side.
Also, if you want to create your own anti-forgery token mechanism, you need to take into consideration to use a cryptographically secure pseudo random number generator, but honestly, you should not bother with that, since the current server-generation process is just what you need (assuming that your framework has a built-in mechanism for this, if not, then you still need to make sure that you're using a cryptographically secure pseudo random number generator to generate your anti-forgery tokens).
Remember to never trust user's submitted information. Since it can always can be tampered, you always need to perform a double-check in the server side, and in this case, generating your anti-forgery token in the server is what allows you to double-check to verify the integrity of the submitted anti-forgery token.
I suggest to use this approach, I have used on a large scale project:
From: https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#use-of-custom-request-headers
Use of Custom Request Headers
Adding CSRF tokens, a double submit cookie and value, an encrypted token, or other defense that involves changing the UI can frequently be complex or otherwise problematic. An alternate defense that is particularly well suited for AJAX or API endpoints is the use of a custom request header. This defense relies on the same-origin policy (SOP) restriction that only JavaScript can be used to add a custom header, and only within its origin. By default, browsers do not allow JavaScript to make cross origin requests with custom headers.
If this is the case for your system, you can simply verify the presence of this header and value on all your server side AJAX endpoints in order to protect against CSRF attacks. This approach has the double advantage of usually requiring no UI changes and not introducing any server side state, which is particularly attractive to REST services. You can always add your own custom header and value if that is preferred.
This technique obviously works for AJAX calls and you have to still need protect tags with approaches described in this document such as tokens. Also, CORS configuration should also be robust to make this solution work effectively (as custom headers for requests coming from other domains trigger a pre-flight CORS check).
So, instead of sending the token through a request body parameter, you could store and send to the server with a request header parameter.

GWT Sessions and XSRF - the optimal solution?

Ok, first I was a bit confused when reading
Remember - you must never rely on the sessionID sent to your server in
the cookie header ; look only at the sessionID that your GWT app sends
explicitly in the payload of messages to your server.
at https://code.google.com/p/google-web-toolkit-incubator/wiki/LoginSecurityFAQ because I didn't understand the nature of XSRF completely and thought: why does it matter how the id gets transmitted?
Then I read http://www.gwtproject.org/doc/latest/DevGuideSecurityRpcXsrf.html and now I understand that XSRF works despite NOT knowing the cookie content (your browser just attaches it to the request, so you exploit your browser's knowledge of the cookie's content - although the browser does not tell 'YOU' or the attacker about the content. The cookie content itself remains uncompromised by that attack). So any proof of knowing the cookie's content validates that the request is not part of XSRF.
I don't like the solution as implemented by GWT (http://www.gwtproject.org/doc/latest/DevGuideSecurityRpcXsrf.html) because it needs a separate call to the server. Please tell me if my ansatz is secure and if I understand the XSRF stuff correctly:
To prevent XSRF, I just copy the session ID contained within the cookie into some non-standard HTTP header field, ie. "X-MY-GWT-SESSION-ID: $sessionId", when doing RPC calls.
That way, I do not need to make any additional calls during app startup because session validation is already done during delivery of the gwt app by destroying the cookie if the session is not valid any more (see How can delete information from cookies?).
So here is the complete security implementation:
registration: client submits cleartext credentials via RPC call to the server, which in turn stores the password using a hash during registration in the server's database (How can I hash a password in Java?)
login: client sends cleartext pwd via https+RPC, check password on server, if ok: store and return (via https) random UUID. That UUID is the shared secret stored on server and client that is used to identify the authenticated user over possibly many browser sessions to avoid requiring the user to log in each time he visits the site.
server sets cookie expiry time to 0 if session is not valid any more so that the client clears the session id and the GWT app detects that it needs to re-authenticate.
on server side only accept session UUIDs sent through a special HTTP header field to prevent XSRF
handle invalidated sessions on client side (either no session cookie or RPC request produced auth failure)
to prevent re-authentication shortly after gwt app loading, the server side devlivery mechanism (ie. index.jsp) deletes the cookie some time before the timeout actually happens - delivering a page and asking for authentication a few seconds later is a bit dumb.
Example sources for the GWT part can be found there: https://stackoverflow.com/a/6319911/1050755. The solution bsaically uses GWT XSRF classes, but embeds the MD5-hashed session ID directly into the web page instead of getting the token via a separate RPC call. The client actually never calls any cookie-related code and the server has only embedded a request.getSession().getId() call into the jsp page.
Any comments, suggestions, critique? Do I miss something important?
Disclaimer: I'm not a security expert.
Actually, if you obtain your xsrf token by an RPC call, then you're subject to XSRF, as an attacker could possibly forge both requests (this is very unlikely though, because it would have to read the response of the first call, which is most of the time prohibited by the cross-origin nature of the request and/or the way it has to be executed).
So ideally you'll make your xsrf token available to the GWT app through any mean.
You'll generally want your session cookie to be unaccessible through scripts (HttpOnly flag), so you'll need to find another way of passing the value (e.g. write it in the HTML host page that's delivered to the browser –as a JS variable, or a special HTML attribute on a special HTML element–, and read it there with GWT, either through Dictionary, JSNI or the DOM).
Also, you'll probably want to use both the cookie and the request header to validate the request (they must match), or you might be vulnerable to session fixation attacks (would probably need an XSS vulnerability too to make it truly useful)

Why not use session ID as XSRF token?

Why does Play Framework use [a signed version of the session id] as Cross Site Request Forgery (XSRF/CSRF) prevention token, rather than the session ID itself?
(With XSRF prevention token, I mean a magic value that must be included in a form submission, for the webapp to accept the form.)
If there's an eavesdropper s/he'll find both the XSRF token and the SID cookie anyway (?).
If there's an XSS exploit, then the malicious JavaScript code can read both the XSRF token and the SID cookie (?).
However:
An attacker cannot construct a valid XSRF token, given a SID, since s/he doesn't have the secret key used when signing the SID to obtain the XSRF token. -- But how could it happen that an attacker gets hold of only the SID, not the XSRF token? Is that far-fetched?
If the SID is sent in a HTTP Only cookie, then an attacker wouldn't have the SID even if s/he found the XSRF token, and perhaps the attacker really needs the SID? -- Is this far-fetched?
Code snippets:
Here Play constructs it's XSRF token (getId returns the session ID):
(play/framework/src/play/mvc/Scope.java)
public String getAuthenticityToken() {
return Crypto.sign(getId());
}
Here Play checks that a <form> has a valid XSRF token:
(play/framework/src/play/mvc/Controller.java)
protected static void checkAuthenticity() {
if(Scope.Params.current().get("authenticityToken") == null ||
!Scope.Params.current().get("authenticityToken").equals(
Scope.Session.current().getAuthenticityToken())) {
forbidden("Bad authenticity token");
}
}
Update:
Play has changed the way it generates XSRF tokens, now the SID is no longer used, instead a random value is signed and used! (I just updated my Play Framework Git repo clone from old Play version 1.1 to new 1.2. Perhaps I should have done this ... yesterday, hmm.)
public String getAuthenticityToken() {
if (!data.containsKey(AT_KEY)) {
data.put(AT_KEY, Crypto.sign(UUID.randomUUID().toString()));
}
return data.get(AT_KEY);
}
Well, then why did they do this change?
I found the commit:
[#669] Fix again and apply for Flash and Errors as well
d6e5dc50ea11fa7ef626cbdf01631595cbdda54c
From issue #669:
create session only when absolute necessary
A session cookie is created on every request of a resource. play should only create a session cookie if there is really data to be stored in the session.
So they're using a random value, not the SID, because the SID might not yet have been created. Well that's a reason not to use a derivative of the SID as XSRF token. But doesn't clarify why they signed/hashed the SID, in the past, when they were using it.
The first thing to say is that you can reuse the session ID as the CSRF token, insofar as it will protect you fine against CSRF and does not automatically create any serious security holes. However, for somewhat sound reasons, OWASP used to explicitly recommend against it. (They now don't address the question at all.)
The argument against reusing the session ID as the CSRF token can be summarized as follows (key points in bold, with justification beneath):
The session ID being acquired by an attacker is generally a more serious security breach than the CSRF token being acquired by an attacker.
All that an attacker gains from having the CSRF token (assuming that some other secure piece of information, like the session ID, hasn't been reused as the CSRF token) is the ability to perform CSRF attacks. This gives them two huge limitations that they wouldn't have if they actually acquired a session ID:
They still need to lure the user with the corresponding session token to an attack page (or have them read an attack email, or view an attack ad in an iframe, etc.) to exploit the CSRF token in any way at all. With the session ID, they'd just need to put it in their browser and then use the website as if they were that user.
While they can send requests using the user's credentials, the Same Origin Policy still prevents them from viewing the responses to those requests. This may (or may not, depending on the structure of the API you're protecting and the attacker's ingenuity) mean in practice that while the attacker can perform actions on the user's behalf, they cannot acquire sensitive information that the user is authorized to view. (Which of these you care more about depends upon the context - one assumes that an attacker would tend to prefer taking the contents of your bank account to merely knowing how much that is, but that they'd also rather know your medical history than vandalise it.)
The CSRF token is potentially easier for an attacker to acquire than the session ID
XSS attacks are likely to permit an attacker to acquire the CSRF token, since it's common practice to bake it into the DOM (e.g. as the value of an <input> element in a <form>. Session cookies, on the other hand, can be kept secret even in the face of a successful XSS attack using the HttpOnly flag, demanding more up-front work from an attacker to usefully exploit an XSS vulnerability.
If the CSRF token is being sent back to the server as a request parameter rather than a custom HTTP header (guaranteed to be the case when including it in ordinary HTML <form> submits), then web server access logs will generally log the CSRF token on GET requests (as it's part of the URL). Thus an attacker who manages to view the access log would be able to acquire many CSRF tokens.
Pages or scripts that the CSRF token is baked into may be cached in the user's browser, permitting an attacker to retrieve them from the cache (conceivably relevant after the user has, for example, used a public machine in a library or internet cafe, and then either cleared their cookies but not their cache, or used a 'Log Out' button that removes their session cookie from the browser without invalidating it server-side).
But if you're reusing the session ID as the CSRF token, then any attack that permits them to acquire the CSRF token automatically gives them the session ID as well.
Therefore you should not reuse the CSRF token as the session ID, since it makes the session ID more vulnerable.
To be honest, I kind of regard everything above as more of a theoretical concern than a practical one. The weak point in the argument is point 2; the only realistic vulnerabilities I can think of that could be used for acquiring CSRF tokens but not for acquiring session cookies are still really serious vulnerabilities. If you have an XSS hole on your site, or an attacker has access to your freaking server logs, chances are you're totally fucked anyway. And in most libraries and internet cafes I've been to, the staff were not security-savvy and it'd be pretty easy to install a keylogger undetected and just harvest passwords - there'd be no need for an attacker to go to the effort of waiting for people to use the machine and then ripping the contents of their browser cache.
However, unless your circumstances somehow make it difficult to store an additional random token for CSRF alongside the random session ID, why not just do it anyway for whatever modest security benefit it gives you?
A pure CSRF attack doesn't have access to the browser's cookies so when you say "eavesdropper", that's only going to be achievable if they're sniffing packets (i.e. no SSL, public wifi).
Depending on the configuration of the Play Framework (I'm not familiar with it so take this as general web app advice), the session and authentication cookies will almost certainly be flagged as HttpOnly so they they're unable to be read from the client via XSS.
Ultimately, the idea of using the synchroniser token pattern to protect against XSRF is to use a unique value (preferably cryptographically strong), known only to the server and the client and unique to that session. Based on this goal, Play Framework seems to do just fine.
Perhaps Play Framework doesn't want the SID in the HTML. An end user, Bob, might download a Web page, and if there's a <form> in that Web page, the SID would be included in the downloaded HTML (if the SID itself is used as XSRF token). If Bob then emails his downloaded page to Mallory, then Mallory would find the SID and could impersonate Bob!?
(Another minor reason not to use the SID: As I mentioned in my update, the SID might simply not be available. Perhaps it's generated as late as possible, to save CPU resources.)

Do I need to use a 'nonce' token in ASP.NET WebForms to guard against CSRF?

In an ASP.NET WebForms application which:
Sets the ViewStateUserKey to the session ID via
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
if (User.Identity.IsAuthenticated)
ViewStateUserKey = Session.SessionID;
}
on the derived base page
Uses only POSTbacks to perform any sensitive actions
EnableViewStateMac is always enabled
Do I still need to implement a hidden form field value with a random token that is checked for on subsequent requests to mitigate against CSRF attacks??
This is not a complete method of protection against CSRF. Any non-postback request, such as GET is still vulnerable. Also I haven't used this method and to be honest ViewState manipulation can be a much more serious vulnerability. The idea of giving the viewstate to the client isn't a defense in-depth approach. A Cryptographic Nonce is a very good solution to the problem and thats why its most commonly used. But its not the only solution, you should read the CSRF Prevention Cheat Sheet. For the record a Nonce just means a value that is only used once, a primary key is a nonce, but thats doesn't stop CSRF. You need a cryptographic nonce, which is a value that is only used once, AND its very difficult to guess.

Spring Security RememberMe Services with Session Cookie

I am using Spring Security's RememberMe Services to keep a user authenticated.
I would like to find a simple way to have the RememberMe cookie set as a session cookie rather than with a fixed expiration time. For my application, the cookie should persist until the user closes the browser.
Any suggestions on how to best implement this? Any concerns on this being a potential security problem?
The primary reason for doing so is that with a cookie-based token, any of the servers behind our load balancer can service a protected request without relying on the user's Authentication to be stored in an HttpSession. In fact, I have explicitly told Spring Security to never create sessions using the namespace. Further, we are using Amazon's Elastic Load Balancing, and so sticky sessions are not supported.
NB: Although I am aware that as of Apr. 08, Amazon now supports sticky sessions, I still do not want to use them for a handful of other reasons. Namely that the untimely demise of one server would still cause the loss of sessions for all users associated with it.
http://aws.amazon.com/about-aws/whats-new/2010/04/08/support-for-session-stickiness-in-elastic-load-balancing/
Spring Security 3 does not offer configuration of how the cookie is generated. You have to override the default behaviour:
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices;
/** Cookie expires on session. */
public class PersistentTokenBasedRememberMeServicesCustom extends
PersistentTokenBasedRememberMeServices {
/** only needed because super throws exception. */
public PersistentTokenBasedRememberMeServicesCustom() throws Exception {
super();
}
/** Copy of code of inherited class + setting cookieExpiration, */
#Override
protected void setCookie(String[] tokens, int maxAge,
HttpServletRequest request, HttpServletResponse response) {
String cookieValue = encodeCookie(tokens);
Cookie cookie = new Cookie(getCookieName(), cookieValue);
//cookie.setMaxAge(maxAge);
cookie.setPath("/");
cookie.setSecure(false); // no getter available in super, so always false
response.addCookie(cookie);
}
}
Make sure, you use this customized PersistentTokenBasedRememberMeServices for you're rememberMeService by adding the class name to it's bean configuration:
<beans:bean id="rememberMeServices"
class="my.custom.spring.PersistentTokenBasedRememberMeServicesCustom"/>
To have session work properly with load balancing I would have your session data stored in a sql database.
The cookie should always be a random value that expire. There are cases where you can store state as a cookie value and it not be a secuirty hazard, such as the users preferred language, but this should be avoided as much as possible. Turning HttpOnlyCookies on, is a great idea.
Read A3: "Broken Authentication and Session Management" in the OWASP top 10 for 2010. One important point in this section is that https must be used for the entire session. If the session is lasting for a very long time, then this is even more important.
Also keep in mind that "Remember Me" creates a large window in which an attacker can "ride" on the session. This gives an attacker a very long time (Months?) in which he can deliver a CSRF attack. Even if you have CSRF protection an attacker can still ride on a session with XSS and XmlHttpRequest (HttpOnlyCookies will prevent a full hijack). "Remember Me" makes other threats like xss, csrf, sniffing more serious. As long as these vulnerabilities have been addressed, then you shouldn't have a problem with real world hackers.
The easiest (and secure) approach to implement a "remember me" feature would be to modify the session timeout to make it very large (a few months). If the "remember me" checkbox is unchecked then store a session variable with a new timeout (1 day from login). Keep in mind that even if the cookie is deleted by the browser when it is closed the session still is active on the server side. If the session id stolen, then it can still be used.

Resources