So we have a platform secured with a JWT access-token. To access platform REST API, we send the token in a Bearer Authorization header; when fetching static content (such as SPAs' code, CSS, fonts, or even for jumping between SPAs) we send the token in a Cookie since we have no control over those requests. We were OK so far...
At some point in time we added Spring Security in our APIs. This made some things easier for us but SonarQube displayed warnings for disabling Spring Security's CSRF protection (when configuring the framework we thougt pfff, we use headers to transport our JWT, we don't need CSRF protection for our APIs), but we tried to solve the warning anyway.
Investigating we came across SameSite attribute for Cookies and we are kind of confused if this would solve all of our problems.
So the question would be: is SameSite cookies' attribute enough for CRSF protection?
If so, is there a way to let Spring Security / SonarQube that we're OK against such attacks?
Related
I am new to web security and implementation of same using spring-security. One important concept is prevention from CSRF using CSRF token. Spring security has provided two ways to manage CSRF token
CookieCsrfTokenRepository
HttpSessionCsrfTokenRepository
However I am not able to understand which one should be used as I can see cons in both the approach.
CookieCsrfTokenRepository is asking to set HTTP only property to false in cookie so that javascript can read it and add the same to in further request. However as per my understanding, setting http only as false is not recommended as malicious script can also read the cookie and share the same token in the forged request.
HttpSessionCsrfTokenRepository is storing the csrf token in session. In this case, we need to introduce session stickiness or session replication in case of distributed environment however recommendation is to go for stateless application.
So please some let me know if my above understanding is correct or not. If correct, which option do we need to select for csrf token implementation.
However as per my understanding, setting http only as false is not recommended as malicious script can also read the cookie and share the same token in the forged request.
I believe this would be true if a) you have an XSS vulnerability on your site or b) you did not set the Domain of the cookie. The rest of your question seems opinion-based to me.
however recommendation is to go for stateless application.
Note: The following is simply my opinion on the matter, as it's difficult to argue for/against statelessness in general.
This is an example where security requires state, so to protect the csrf token and avoid your concern with cookies, you need state on the server and should choose session.
I'm developing a spring boot application and am trying to integrate with Reddit oauth using Spring Security. It all works great up until the request to Reddit for the access token.
Reddit has a set of rules that rate limits requests from User-Agent including Java. The default User-Agent sent by java application is Java/<version>. I tried overriding this by setting the http.agent system property, but Java/<version> is still appended to the end (as shown here) which triggers the rate-limiting.
Is there some other simple way I can override the User-Agent header that's included in the access token request to the oauth server?
We are building a web application using Angular and Spring Boot. As one of our security measures, we use CSRF tokens. The issue is that, on our local machines, the token validation works, but on our staging server, the tokens aren't sent by the frontend. The problem has suddenly occurred; we didn't have this problem for the first few months of using the tokens. After a certain build, they started failing. Then after a while, they were working again, but now have ceased working once more.
So, it seems like there is an environment issue that we fail to see.
What we can see
Spring is creating the CSRF token and sending it on preflight (OPTIONS) requests. It encapsulates the token in the Set-Cookie header, which Angular reads using the CookieXSRFStrategy. Again, locally this works fine, but on our staging server this fails. The issue is that Angular doesn't set the cookie after receiving the token. We checked this by inspecting the cookies in the Google Dev Console.
The specific error given by Spring is:
Invalid CSRF Token was found on the request parameter '_csrf' or
header 'X-CSRF-TOKEN'
The issue this causes
We can't login, since Spring doesn't receive a CSRF token. Therefore we can't do anything with the application unless we turn off CSRF protection completely.
We have tried
Specifically whitelisting cookies for the application in Chrome.
Clearing cookies and cache.
Trying in different browsers, on different machines. This happens in Chrome, IE11 and Firefox. We haven't tried any other browsers.
Making sure the origin is allowed through CORS, which it is. We do this with the Access-Control-Allow-Origin header.
Exposing more headers, like Set-Cookie using the Access-Control-Expose-Headers header. This doesn't change anything.
Allowing more headers, using Access-Control-Allow-Headers. This doesn't change anything either.
Simulating the login process using cURL (with the Postman application). This works. So it's an issue of Angular not being able to process the token properly.
Reading the headers manually with JavaScript/TypeScript. This didn't seem to work since the header wasn't exposed.
After struggling with the issue, we decided to integrate Docker, in an effort to mirror our staging and local environments. This didn't resolve the issue.
Reverting back to a previous build didn't work either.
Important notes
Both locally and on the staging environment we use an SSL certificate. Locally, we use a self-signed certificate.
All of the application runs on a Wildfly server. Both the Angular and Spring code is built and distributed using WAR files, which Wildfly deploys.
We are using a corporate proxy. The staging server is hosted in-house, and is only accessible when you're on the corporate network.
Versions
Angular: 4.2.2
Spring Boot: 1.4.1
Wildfly: 10.1.0.Final
Our current workaround is that we have disabled CSRF protection completely, so as to be able to continue development while we are looking for a solution.
Does anyone have any idea what could be going wrong?
The exception Invalid CSRF Token was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN' occurs when an invalid CSRF token is passed. If Spring would receive no CSRF token at all, it would print a different message "Could not verify the provided CSRF token because your session was not found." That means frontend is sending old or invalid CSRF token.
Possibly your corporate network proxy applies some login mechanism and override your X-CSRF-TOKEN header.
According to Spring Security documentation, cookieHttpOnly=false is needed to allow AngularJS to read the XSRF-TOKEN cookie.
I have implemented Spring Security extentions SPNEGO API for Single Singh On in my application. Can anyone help me to know, is kerberos protocol or SPNEGO is CSRF safe? Do i need to implement CSRF safety explicitly even i have implemented SPNEGO?
You need to implement CSRF protection whenever you have anything that automatically sends authentication information to a server. To my knowledge the only two mechanisms are cookies and Kerberos/NTLM over SPNEGO. With SPNEGO, whitelisted domains will get your kerberos token on each request. An attacker could craft a form and trick a user to submit it, and if the target is an API with SPNEGO support that the browser is whitelisted to send tokens to, it can trick the user into sending authentication information they didn't intend to. Just like an authentication cookie.
Sources: https://www.computerweekly.com/tip/CSRF-attack-How-hackers-use-trusted-users-for-their-exploits and https://security.stackexchange.com/a/190903/12776
I have written a REST- API in Java and I have secured this API with Spring Security. The procedure is like this:
Frontend invokes /login RestService in Backend
Backend gives back token to frontend
at each REST- API Backend invokation the token has to be placed in header
This works fine, but I have read that it is also possible (with Node.JS/Passport.js/Express.js) that the session object with the cookie inside can be transfered out of the box without any custom code.
My question now would be if there is a better approach so that the frontend/client do not need to set the token into the header all the time for any request.
Usually token based authentication has advantages over cookie based.
You can achieve this using middle-ware layer
Here is a good Post - https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/
Server side, I usually first check in the headers if there is an auth token. If not, I then check in the cookies as a fallback.
If you want to use cookies, then at your step 2, you need to add a Set-Cookie header to the response, so that browsers know they must store a cookie. Once done, no need to add a header client-side, since browsers will send cookies each request. You'll need to add a CSRF protection though (here is a good example).