GWT's built-in XSRF protection - gwt

I have a few questions regarding this:
In general, is XSRF still an issue with up-to-date browsers? To my knowledge cross-domain requests have been disabled by default and are now controlled through CORS. And when people are using outdated browsers, there are probably so many security holes in them that XSRF wouldn't matter anyways. BTW the XsrfTokenServlet class is still marked as not-for-production, so the GWT devs seem to consider it not an important issue or don't trust their own implemention.
Secondly, GWT uses a servlet to create the XSRF token. Doesn't that introduce an obvious attack vector by returning the (hashed) JSESSIONID? I thought you do XSRF exactly because the attacker doesn't know JSESSIONID and simply makes your browser send it along with the request. Now that request returns the critical hash of it that he can use to pretend he knows the JSESSIONID. What do I get wrong here? Shouldn't the JSESSIONID be hashed on the client side independently of the server to prove that the client actually can read the JSESSIONID cookie which isn't possible when calling the site from a page loaded from a different site?

Related

Stateless REST API with CSRF and XSS protection

Is it possible to protect stateless REST API from both XSS and CSRF attacks?
Currently, I'm using JWT token stored in secure/httpOnly cookie for stateless authentication. This should protect the API from most common XSS attack: stealing cookies with XSS-injected JavaScript and sending them to the attacker.
However, this doesn't protect the API from CSRF attack, where attacker would trick the authenticated user to follow a link to the particular web API call to actuate adverse transaction on behalf of the victim. How could I protect the API from this attack without introducing server side state?
Also, is it true XSS vulnerability would inheritedly allow CSRF type attack in the following scenario: Injected JavaScript would retrieve CSRF token from the client side state, DOM or the browser storage and prepare a malicious ajax call to the server. Browser would still automatically include the httpOnly cookie for the same origin request. Is there a way to get protected from this other than protecting from the XSS vulnerability in the first place?
Stateless anti-forgery tokens
The first question is about preventing CSRF without server-side state. The current approach for stateless anti-forgery tokens is the double submit cookie pattern.
CSRF attacks depend on the browser automatically sending the API's own cookies back to it, regardless of where the request originated. The attacker doesn't have or need access to the cookie contents. They only need to trick the user into loading malicious HTML. The double cookie pattern adds a new requirement: the attacker must know and separately send the contents of the anti-forgery cookie.
There are ways for an attacker to overwrite the anti-forgery cookie with their own. So you may want to look at some additional security hardening for this approach. Especially HMAC signing the anti-forgery token to prevent token substitution. Using HSTS and the __Host cookie prefix to ensure transport security and proper cookie scope. And having the client provide the anti-forgery token in a custom header.
The custom header ensures the request must be sent from JS, since HTML-tag-based CSRF attacks cannot set custom headers. Being sent from JS also triggers additional protections. For cross-origin requests it triggers SOP on the browser and CORS validation on the server. The server can also do basic Origin validation.
Regarding the scope of CSRF attacks, here is a note from the OWASP CSRF link at the top.
Forcing the victim to retrieve data doesn’t benefit an attacker because the attacker doesn’t receive the response, the victim does. As such, CSRF attacks target state-changing requests.
XSS question
Yes, an XSS attack could happen that way. Once a malicious script is loaded into JS, it has free reign to use anything accessible to Javascript. Including app code/memory, browser storage, and cookies. Even though HttpOnly cookies are not readable, they can still be sent in requests. A non-targeted attack might look for key data in locations used by popular frameworks. And might try to probe for popular/discoverable API frameworks on the server. A targeted attack means the attacker studied your system and crafted a custom payload for it.
The primary vector for XSS is unsanitized external data (user input, database values, etc.). To prevent XSS, check out these guidelines from OWASP. Of note is that front-end frameworks like Angular, React, Svelte, Vue, and others have built-in XSS protection. Because they sanitize data before rendering it. Example: an attacker enters an HTML string into an input. When it is later displayed, these frameworks HTML-encode the string. So left and right angle brackets are replaced with < and > and so on. This causes the browser to evaluate the string as text instead of runnable HTML. But you can still mess it up in different ways if careless.
XSS attacks can also come from external resources. Maybe a compromised CDN or NPM script. If your deployed code takes dependencies on NPM libraries, pay extra attention to NPM audit warnings. One attack pattern is to attach a small loader (easier to go unnoticed), which will fetch attack payloads at runtime. A CSP policy can help prevent this. Specify an allowed list of resources -- your app assets and API URLs -- and block all others. CSP can also prevent data exfiltration.
For both CSRF and XSS
For attacks on your API, you can additionally employ server-side mitigations. IP-based throttling / temporary bans, unusual activity grey-listing and alerting, etc.
For especially sensitive operations, one strategy is to use an escalated authorization. This could take the form of requiring the user to re-authenticate or use a 2nd factor like a one-time password. This can block automated attacks since it requires active user intervention.
To mitigate attackers using existing escalated authorizations (which may also be in a cookie or app memory), they can have short expirations and be limited to specific operations. To go even further, the approved operations + relevant data can be signed. This will prevent malicious scripts from reusing an escalation to execute the same kind of operation with different data. Even further, these sensitive operations can be idempotent. So if an attacker does resend already-executed operations, they will not cause any additional changes in the system.
Zooming out
Try to engineer your systems to be as uninteresting as possible to hackers. Use trusted external services for sensitive needs like credit cards and credentials. Ideally (from a security perspective) the hacking risk would be reduced to just data vandalism/loss. So in the worst case that a breach happens, it would have little long-term impact. And it could be recovered with common practices, including routinely tested backups. And then further mitigations added for the specific attacks used.
Tread especially carefully with user-to-user interaction. Since this adds more targets and pivot points for hackers -- your user base. The most security-conscious eyes should be on these pieces. Not only for technical dangers like user-to-user XSS attacks, but also social ones. Human weaknesses are the most well-known and easiest to exploit.
Lastly, there is no sense investing in mitigations which have low risk/consequences in your situation. So do not take everything here as a requirements checklist. It's not a complete list anyway. Focus on your biggest risks first. Reevaluate periodically.
You can generate a token (e.g. a UUID) and put it into the jwt token as well as send it back to the client. Then the client sends it during every each request in a header. Then the server can compare the token in the header and the token in the jwt token to make sure the request comes from the client who was aunthenticated.

Can I use a session identifier in a REST API? [duplicate]

Is using sessions in a RESTful API really violating RESTfulness? I have seen many opinions going either direction, but I'm not convinced that sessions are RESTless. From my point of view:
authentication is not prohibited for RESTfulness (otherwise there'd be little use in RESTful services)
authentication is done by sending an authentication token in the request, usually the header
this authentication token needs to be obtained somehow and may be revoked, in which case it needs to be renewed
the authentication token needs to be validated by the server (otherwise it wouldn't be authentication)
So how do sessions violate this?
client-side, sessions are realized using cookies
cookies are simply an extra HTTP header
a session cookie can be obtained and revoked at any time
session cookies can have an infinite life time if need be
the session id (authentication token) is validated server-side
As such, to the client, a session cookie is exactly the same as any other HTTP header based authentication mechanism, except that it uses the Cookie header instead of the Authorization or some other proprietary header. If there was no session attached to the cookie value server-side, why would that make a difference? The server side implementation does not need to concern the client as long as the server behaves RESTful. As such, cookies by themselves should not make an API RESTless, and sessions are simply cookies to the client.
Are my assumptions wrong? What makes session cookies RESTless?
First of all, REST is not a religion and should not be approached as such. While there are advantages to RESTful services, you should only follow the tenets of REST as far as they make sense for your application.
That said, authentication and client side state do not violate REST principles. While REST requires that state transitions be stateless, this is referring to the server itself. At the heart, all of REST is about documents. The idea behind statelessness is that the SERVER is stateless, not the clients. Any client issuing an identical request (same headers, cookies, URI, etc) should be taken to the same place in the application. If the website stored the current location of the user and managed navigation by updating this server side navigation variable, then REST would be violated. Another client with identical request information would be taken to a different location depending on the server-side state.
Google's web services are a fantastic example of a RESTful system. They require an authentication header with the user's authentication key to be passed upon every request. This does violate REST principles slightly, because the server is tracking the state of the authentication key. The state of this key must be maintained and it has some sort of expiration date/time after which it no longer grants access. However, as I mentioned at the top of my post, sacrifices must be made to allow an application to actually work. That said, authentication tokens must be stored in a way that allows all possible clients to continue granting access during their valid times. If one server is managing the state of the authentication key to the point that another load balanced server cannot take over fulfilling requests based on that key, you have started to really violate the principles of REST. Google's services ensure that, at any time, you can take an authentication token you were using on your phone against load balance server A and hit load balance server B from your desktop and still have access to the system and be directed to the same resources if the requests were identical.
What it all boils down to is that you need to make sure your authentication tokens are validated against a backing store of some sort (database, cache, whatever) to ensure that you preserve as many of the REST properties as possible.
I hope all of that made sense. You should also check out the Constraints section of the wikipedia article on Representational State Transfer if you haven't already. It is particularly enlightening with regard to what the tenets of REST are actually arguing for and why.
First, let's define some terms:
RESTful:
One can characterise applications conforming to the REST constraints
described in this section as "RESTful".[15] If a service violates any
of the required constraints, it cannot be considered RESTful.
according to wikipedia.
stateless constraint:
We next add a constraint to the client-server interaction:
communication must be stateless in nature, as in the
client-stateless-server (CSS) style of Section 3.4.3 (Figure 5-3),
such that each request from client to server must contain all of the
information necessary to understand the request, and cannot take
advantage of any stored context on the server. Session state is
therefore kept entirely on the client.
according to the Fielding dissertation.
So server side sessions violate the stateless constraint of REST, and so RESTfulness either.
As such, to the client, a session cookie is exactly the same as any
other HTTP header based authentication mechanism, except that it uses
the Cookie header instead of the Authorization or some other
proprietary header.
By session cookies you store the client state on the server and so your request has a context. Let's try to add a load balancer and another service instance to your system. In this case you have to share the sessions between the service instances. It is hard to maintain and extend such a system, so it scales badly...
In my opinion there is nothing wrong with cookies. The cookie technology is a client side storing mechanism in where the stored data is attached automatically to cookie headers by every request. I don't know of a REST constraint which has problem with that kind of technology. So there is no problem with the technology itself, the problem is with its usage. Fielding wrote a sub-section about why he thinks HTTP cookies are bad.
From my point of view:
authentication is not prohibited for RESTfulness (otherwise there'd be little use in RESTful services)
authentication is done by sending an authentication token in the request, usually the header
this authentication token needs to be obtained somehow and may be revoked, in which case it needs to be renewed
the authentication token needs to be validated by the server (otherwise it wouldn't be authentication)
Your point of view was pretty solid. The only problem was with the concept of creating authentication token on the server. You don't need that part. What you need is storing username and password on the client and send it with every request. You don't need more to do this than HTTP basic auth and an encrypted connection:
Figure 1. - Stateless authentication by trusted clients
You probably need an in-memory auth cache on server side to make things faster, since you have to authenticate every request.
Now this works pretty well by trusted clients written by you, but what about 3rd party clients? They cannot have the username and password and all the permissions of the users. So you have to store separately what permissions a 3rd party client can have by a specific user. So the client developers can register they 3rd party clients, and get an unique API key and the users can allow 3rd party clients to access some part of their permissions. Like reading the name and email address, or listing their friends, etc... After allowing a 3rd party client the server will generate an access token. These access token can be used by the 3rd party client to access the permissions granted by the user, like so:
Figure 2. - Stateless authentication by 3rd party clients
So the 3rd party client can get the access token from a trusted client (or directly from the user). After that it can send a valid request with the API key and access token. This is the most basic 3rd party auth mechanism. You can read more about the implementation details in the documentation of every 3rd party auth system, e.g. OAuth. Of course this can be more complex and more secure, for example you can sign the details of every single request on server side and send the signature along with the request, and so on... The actual solution depends on your application's need.
Cookies are not for authentication. Why reinvent a wheel? HTTP has well-designed authentication mechanisms. If we use cookies, we fall into using HTTP as a transport protocol only, thus we need to create our own signaling system, for example, to tell users that they supplied wrong authentication (using HTTP 401 would be incorrect as we probably wouldn't supply Www-Authenticate to a client, as HTTP specs require :) ). It should also be noted that Set-Cookie is only a recommendation for client. Its contents may be or may not be saved (for example, if cookies are disabled), while Authorization header is sent automatically on every request.
Another point is that, to obtain an authorization cookie, you'll probably want to supply your credentials somewhere first? If so, then wouldn't it be RESTless? Simple example:
You try GET /a without cookie
You get an authorization request somehow
You go and authorize somehow like POST /auth
You get Set-Cookie
You try GET /a with cookie. But does GET /a behave idempotently in this case?
To sum this up, I believe that if we access some resource and we need to authenticate, then we must authenticate on that same resource, not anywhere else.
Actually, RESTfulness only applies to RESOURCES, as indicated by a Universal Resource Identifier. So to even talk about things like headers, cookies, etc. in regards to REST is not really appropriate. REST can work over any protocol, even though it happens to be routinely done over HTTP.
The main determiner is this: if you send a REST call, which is a URI, then once the call makes it successfully to the server, does that URI return the same content, assuming no transitions have been performed (PUT, POST, DELETE)? This test would exclude errors or authentication requests being returned, because in that case, the request has not yet made it to the server, meaning the servlet or application that will return the document corresponding to the given URI.
Likewise, in the case of a POST or PUT, can you send a given URI/payload, and regardless of how many times you send the message, it will always update the same data, so that subsequent GETs will return a consistent result?
REST is about the application data, not about the low-level information required to get that data transferred about.
In the following blog post, Roy Fielding gave a nice summary of the whole REST idea:
http://groups.yahoo.com/neo/groups/rest-discuss/conversations/topics/5841
"A RESTful system progresses from one steady-state to the
next, and each such steady-state is both a potential start-state
and a potential end-state. I.e., a RESTful system is an unknown
number of components obeying a simple set of rules such that they
are always either at REST or transitioning from one RESTful
state to another RESTful state. Each state can be completely
understood by the representation(s) it contains and the set of
transitions that it provides, with the transitions limited to a
uniform set of actions to be understandable. The system may be
a complex state diagram, but each user agent is only able to see
one state at a time (the current steady-state) and thus each
state is simple and can be analyzed independently. A user, OTOH,
is able to create their own transitions at any time (e.g., enter
a URL, select a bookmark, open an editor, etc.)."
Going to the issue of authentication, whether it is accomplished through cookies or headers, as long as the information isn't part of the URI and POST payload, it really has nothing to do with REST at all. So, in regards to being stateless, we are talking about the application data only.
For example, as the user enters data into a GUI screen, the client is keeping track of what fields have been entered, which have not, any required fields that are missing etc. This is all CLIENT CONTEXT, and should not be sent or tracked by the server. What does get sent to the server is the complete set of fields that need to be modified in the IDENTIFIED resource (by the URI), such that a transition occurs in that resource from one RESTful state to another.
So, the client keeps track of what the user is doing, and only sends logically complete state transitions to the server.
As I understand, there are two types of state when we are talking about sessions
Client and Server Interaction State
Resource State
Stateless constraint here refers to the second type in Rest. Using cookies (or local storage) does not violate Rest since it is related to the first.
Fielding says: 'Each request from client to server must contain all of the information necessary to understand the request, and cannot take advantage of any stored context on the server. Session state is therefore kept entirely on the client.'
The thing here is that every request to be fulfilled on the server needs the all necessary data from the client. Then this is considered as stateless. And again, we're not talking about cookies here, we're talking about resources.
HTTP transaction, basic access authentication, is not suitable for RBAC, because basic access authentication uses the encrypted username:password every time to identify, while what is needed in RBAC is the Role the user wants to use for a specific call.
RBAC does not validate permissions on username, but on roles.
You could tric around to concatenate like this: usernameRole:password, but this is bad practice, and it is also inefficient because when a user has more roles, the authentication engine would need to test all roles in concatenation, and that every call again. This would destroy one of the biggest technical advantages of RBAC, namely a very quick authorization-test.
So that problem cannot be solved using basic access authentication.
To solve this problem, session-maintaining is necessary, and that seems, according to some answers, in contradiction with REST.
That is what I like about the answer that REST should not be treated as a religion. In complex business cases, in healthcare, for example, RBAC is absolutely common and necessary. And it would be a pity if they would not be allowed to use REST because all REST-tools designers would treat REST as a religion.
For me there are not many ways to maintain a session over HTTP. One can use cookies, with a sessionId, or a header with a sessionId.
If someone has another idea I will be glad to hear it.
i think token must include all the needed information encoded inside it, which makes authentication by validating the token and decoding the info
https://www.oauth.com/oauth2-servers/access-tokens/self-encoded-access-tokens/
No, using sessions does not necessarily violate RESTfulness. If you adhere to the REST precepts and constraints, then using sessions - to maintain state - will simply be superfluous. After all, RESTfulness requires that the server not maintain state.
Sessions are not RESTless
Do you mean that REST service for http-use only or I got smth wrong? Cookie-based session must be used only for own(!) http-based services! (It could be a problem to work with cookie, e.g. from Mobile/Console/Desktop/etc.)
if you provide RESTful service for 3d party developers, never use cookie-based session, use tokens instead to avoid the problems with security.

CSRF protection of GET links

I need to add CSRF protection to a web application.
Problem is in the fact that the app relies heavily on links (GET requests that is) to make changes in the database.
Links are generated using a class, so I could easily add an extra parameter for CSRF token to each link.
However, I understand that CSRF token in a GET request might not be a good enough protection.
Note that app is only available over HTTPS, so GET params can not be exposed/stolen during client/server communication (but history stealing issue remains).
Could GET CSRF token param be considered "safe enough" in this setting?
If not, what is the best way to solve this problem? Only thing that comes to my mind is to wrap each of my links into a form (ether explicitly, or creating form onSubmit using JavaScript).
To be able to read the response to a CSRF attack’s request, an attacker would need to get the victim to execute his JavaScript code. So, CSRF for a "GET" request is almost not useful. This is assuming you have followed the standards that "GET" requests should not modify any data and any modifications need to be done only using "POST"
Using cookie based authentication and SSL should keep you away from a guy who is trying to change the parameters
You may want to introduce some signing based on timestamp to avoid replay attacks
That said, if you have any POST requests, you should consider the CSRF protection.

GWT - Dealing with XSRF/CSRF

Am I correct, that if I pass a self-generated sessionID with every RPC request, and only check this sessionID instead of the one passed in the cookie header, the session can't be hijacked by malicious sites? I know that you should also send this sessionID in the cookie and then compare it with the one sent with every request to detect an XSRF attack but doing it my way should at least protect against XSRF attacks, doesn't it?
EDIT
I know that GWT 2.3 takes care of XSRF by providing XSRF Token Support. Sadly I'm stuck with GWT 2.2 and so have to deal with it by myself.
Yes, because the browser doesn't have enough information to convince your application that it has the right credentials. In a traditional XSRF attack the browser mechanism itself is being exploited and if it doesn't know how to send the extra information or what information to send then it just won't work.
However, with this approach, I would be aware that a malicious attacker could still compromise your self-generated sessionID and use it as soon as they figured out the mechanism.
See this wiki page on cryptographic nonce for more ideas. In using the nonce you're creating something that can only be used for that moment. Once the moment passes the data either becomes useless (in terms of a password salted with a time) or won't be accepted by the server. This is traditionally used to prevent replay attacks because, if you'll forgive me, the nonce has passed.
You might want to look at OWASP's CSRF Guard Project. They use a filter that checks every request to the server for the required CRSF Token. It's quite configurable - you can specify various aspects of your defense for ex:
URLs which don't require protection
entry point form which the CRSF Token
is to be generated (upon login)
the behaviour when a possible attack
is picked up (redirect, logging) etc
It's effectively a solution which requires no code change where the latest version also supports AJAX (RPC) calls to the server. So I believe it's definitely an option to try out (I'm currently POCing this solution for a fairly large GWT app).
Lastly I trust that you have already built your defenses against XSS. As XSRF defenses can be nullified if XSS is possible (not to mention that XSRF attacks are generally launched via XSS).

CSRF protection techniques

Can someone point me to information on how to protect applications from CSRF?
Any code related to this.
I am using extjs for the UI, Java on the backend and tomcat server.
Thanks in advance.
Use of the session id in the way the dan_waterworth suggests, while easy, is very poor protection. The attacker only needs to capture the session id cookie and then can circumvent the protection for the life of the session.
The session id is a cookie so it's submitted with any request. So all an attacker needs to do to capture the sessionid is to cause your application submit a request to a server under the attacker's control. This could be done by a cross-site scripting attack but can also be done by framing the app and submitting the iFrame's forms (there are other ways to do this).
The interaction that needs to be protected from CSRF should include information that the attacker cannot possibly know in advance (a CSRF Token) that is unique per session, per page and per form then ideally used only once. The CSRF token should be submitted in the form, and not in a cookie (for the reason mentioned above). See the 'implementation example' in the OWASP CSRF protection cheatsheet for details and a sample implementation. Some web application engines (e.g. Tomcat 8) and frameworks (e.g Spring, JSF) have protections that you can apply by turning on a configuration.
yes, I have a simple solution that has worked well for me. For each post request, send the sessionid in the data via javascript (obtained from the cookie) and on the server side it just needs to check that the sessionid cookie and the sessionid in the data are the same for every post request.