GWT - Dealing with XSRF/CSRF - gwt

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).

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.

GWT's built-in XSRF protection

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?

REST API security review

I'm working with some people who have had a product in development for a while, with apps on various platforms calling a web service which they're using as an API to store data.
The security model they have developed is not completely unlike others i've worked with, but it's very non-standard in a lot of ways. First, they require an API key for each client, which makes sense. Then there are some methods you can hit without authentication, great. when you need to do authenticated updates, however, this is how they do it:
First you call an endpoint with a username/password to get a "session" going on the server side. this session id is returned to the client after a successful login. Everything else you do that requires authentication takes a session id parameter which is required and the idea is that if you don't supply a valid session id then reject your requests.
I spent some time a while back doing authentication using OAuth and requiring tokens for authenticated requests on another project, so this feels weak to me. One obvious issue is the potential for someone to hijack someone's session by means of a brute-force attack, but I expect they'll dismiss that as just plain unlikely. Their session Id's are GUID's, which I suppose are huge and difficult to hack on some scale, plus you have to hit a valid session that's already established.
Am I missing something obvious, or is this perhaps good enough? I don't want to raise a stink about it and propose a platform-wide migration to OAuth if I can't make the case that it's really necessary.
Thanks for any help.
This sounds acceptable, just make sure that GUIDs are indeed generated with a strong random engine that can't be brute-forced, and that they expire after a while of no activity.
First of all, requiring an API key is a form of authentication. It authenticates the client instead of the user.
Requiring an API key on all clients increases the risk of losing the key (especially when stored on untrusted clients like mobile devices).
Using session identifiers is not insecure, but it does require talking to the issuer (and likely doing a database lookup) for every call.
Security tokens can carry semantic information (claims) and can be validated on the called server (verifying signature), which improves scalability.

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.

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.