SPA, website using oauth2 api - do I need csrf protection - javascript

My website is full SPA, and all of the authenticated user's requests are done using access token, the only form that unauthenticated users have access to is login form. So is csrf protection necessary? What potential security issues could I face if I disable csrf protection from my website? Thanks.

If I understand your setup, it is as follows:
User POSTs credentials (eg: login form)
Server returns auth token in response
User includes token in a request header with every subsequent request
If this is accurate, and assuming that you're using TLS and properly validating tokens, I think you are already well protected against Cross-Site-Request-Forgeries.
The typical CSRF protection is to send a token that only the legitimate website can see (eg, by setting a cookie), and then expecting that same token to be returned either in follow-up request headers, query parameters (not a good idea), or request body. Token-based authentication such as yours already meets these requirements.
In short, if an evil site is able to circumvent your setup to forge requests (CSRF), then the evil site could probably use the same vulnerability to defeat a typical CSRF protection.

Related

NodeJS CSRF Protection with Express, GraphQL and CORS enabled

I am creating a web service very much like shopify but using only JS. Nodejs express for an API with GraphQl and Cors enabled. VueJS for frontend. My authentication is running with JWT. But I have things like anonymous checkout so i need a CSRF protection. The thing is my API is not a router. My router is in the frontend and im only getting the data I need via Graphql through Axios calls to the API. I took a look at the csurf module and tried it out but currently the way im getting a CSRF token to the frontend is with a /getCSRFToken endpoint on the API which i've read is not a good practice and the other thing is It's enabled to access to everyone because of the CORS enabled.
This is the main source of information I have: https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet
I don't know how to exactly set up the CSRF protection without having am API route for getting the CSRF token and sending it as a cookie through the response and generally make the whole thing secure with the best practices.
I was also thinking about restricting access to the API only for the domains of the shops that are in the system but don't now if that will be any good either.
Any suggestions are welcome
You can generate the cookie client side (using window.crypto), then have the JS read it and send it in a header, the server simply has to verify that they match. But this is vulnerable to the fact the cookie is not HttpOnly (because your JS needs to read it!). For this reason, this method is not best practice, but it is better than nothing.
It also does not prevent users from issuing requests from curl and such once they figure out that they only need to provide a matching cookie and header, but they still cannot issue requests on behalf of other users unless they have the target users authorisation credentials.
There actually isn't anything wrong with having an API route which generates a token per request, although it does result in doubled request density (you need a new token for each request!). The reason for this is that an attacker cannot read the response from an external site (CORS will prevent this). Then you are not vulnerable to any cookie exploit, since you never store a cookie in the first place.
Edit: I see you hint at having CORS * enabled for this endpoint to be public. If your API really is public then you'll have probably better off using OAuth2/JWT authentication instead, this way CSRF becomes irrelevant, since the authentication does not come from cookies.
Trying to keep a value across multiple requests encounters difficulty with history functionality, so it's recommended to either use a token per request or...
You could also store a cookie from the getCsrfToken() request and keep it valid for some time, but make it HttpOnly, since it was issued by the API, the API will be responsible for making sure that it is receiving a valid CSRF token.
The issue with both of the above is that if you want true anonymity then you can't tie these tokens to a particular user, so one user could avoid the CSRF checks on behalf of another by using their own CSRF token!
If you can come up with some way around that whilst maintaining anonymity then the server can check the validity of the tokens that it is receiving, such that one user cannot use their token on behalf of another.
Your last idea (assuming that you want true anonymity) is probably the best. Provided that the user agent is trustworthy, the referer and Origin headers cannot be tampered with, so if you are happy to lock down your API to only the domains which your JS is running on, then doing a referer/Origin check server side will not be easily worked around by an attacker. This isn't best practice, but is practically effective.
Again, curl requests and such can be issued freely, but they can only be issued on behalf of another user if the attacker has the user's authorisation credentials.
The last thing to note is that CSRF is an alternative attack vector to XSS, but if you have XSS vulnerabilities, then CSRF defences usually become obsolete, so make sure that you defend XSS first, before implementing CSRF defence.

CSRF Basics with SSL & CSRF Relationship

I am trying to implement CSRF and SSL(they are not entirely dependent) and listing below my understanding on the topic for having a proof of understanding.
Please feel free to correct me about the understanding.
We see CSRF Token in almost all of our secure applications.
How Cross-Site Request Forgery (CSRF) works :
You logged into your bank account(eg. SBI or JPMC) and are looking at your accounts or it's just sitting their opened on your browser just because you got busy.
Now you receive an email may be text/image or anything on the next tab. The moment the email is received functions like onload etc other java script function may trigger a GET/PUT/POST request from your browser without you knowing about it.
Now things to note is that CSRF can't actually read anything from your secured webpage because the moment you have a proper SSL the secure pages are encrypted. And also CSRF can't steal your credentials. As a matter of fact it can't find out the CSRF token kept inside hidden tag inside secure website because its encrypted. It works only after you have authenticated yourself with the website and it fires requests which tricks the server into thinking that the request in coming from the browser you just logged into and thus server work as per the received request.
Now with hacker trying to open a CSRF attack, it tricks the browser to send url:
<img src="https://www.bankWebsite.com/transfer?amount=1000&destination=8990">
Thus without you knowing, from a session which is authenticated by you, a request is fired telling to transfer amount of 1000 in account number 8990 n BOOM you were robbed for 1000 bucks just like that.
How to protect youself:
CSRF protection can be done in a couple of ways:
1) Verifying the origin of request from header
2) Verifying the target of the request
3) CSRF token
How CSRF token protection works:
The CSRf token in present in the header/cookie. So when the hacker tricks the browser into sending the request to the server, the token is present only in the header and not in form submitted. So when the server goes to check whether the CSRF token received, it tries to match the CSRF token from the header with that received from the form/request. If it's not present/doesn't match then server identifies that it's an attack and stops the request from penetrating further.
Request you all to please correct me if my understanding about the CSRF attack, protection is correct or not ?
Also does it mean without proper implementation of SSL, CSRF is of no use ?
Request you all to please correct me if my understanding about the CSRF attack, protection is correct or not ?
Yes
Also does it mean without proper implementation of SSL, CSRF is of no use ?
If you send the token to and from the client in plain text (instead of encrypting it with SSL) then it can be intercepted by the attacker.
If the attacker knows what token to put in the form data, the protection is gone.

What are some alternatives to CSRF tokens in Laravel?

For non-PHP based web-clients (JSON) making use of Laravel Controllers; What would be the potential alternatives to CSRF tokens in Laravel to secure web requests?
If your API uses an authentication scheme that does not depend on the authentication token being sent automatically by the browser (which practically means the token or session id is not in a cookie), your API is not vulnerable to CSRF. This includes token-based auths, unless the token is stored in a cookie.
If cookies are used to pass auth tokens (including session ids, which is the same in this respect), you need CSRF protection for all requests that change server state (mostly data, but also logon status or privilege level for example).
For Laravel, you need to pass the token value from the XSRF-TOKEN cookie as a request header value in X-CSRF-TOKEN. With jQuery, this is easily accomplished in any client framework by reading the cookie value and adding it to requests:
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': csrfCookieValue
}
});
If your client is not browser based, you can implement a different protection than the one in Laravel already. OWASP has a cheat sheet on what your options are, probably double submit is the easiest to implement while being reasonably secure. In very short, you create a random token and send that to the server as a cookie and also as a request header, the server only compares whether the two (cookie and header) match. This works, because an attacker on a differnet origin (domain) cannot set or access a cookie for the application origin due to the same origin policy in browsers.
I think the whole point on using a csrf token is for use inside the app. If you are sending your request via ajax from the app itself then you can simply append the csrf_token to the request. However, if you are sending data from an external source via json then the best way would be to use oAuth to secure access to your api. Luckily laravel has already built this functionality with laravel/passport so implememting it is fairly straightforward.

Security on $https requests

Good Morning,
I'm developing an app in ionic and there are some $http requests(angular) that send data to a server controller(yii 1) to save data on database. I finished my app, but it doesn't have security. I was wondering how to protect it, because right now anyone if look my $http request can know what parameters have to send, and kill my app.
What I should do to protect it? Maybe through tokens? I'm really lost with security methods.
Thank you so much,
Carles.
well When you research web application security you will come across Cross-Site Request Forgery (CSRF). This attack vector is taking advantage of cookies, but in a preventable way.
Most attacks focus on stealing your cookies because nearly every website uses cookies as a form of authentication. The setup is this: when a user logs into your server, you set a cookie in the browser. This cookie contains a unique ID which is a link to the user’s session information in your database. The browser supplies this cookie on future requests, and the server knows who you are.
On the surface this sounds not-so-bad, but here is the catch: the web browser can be tricked into making requests to your server, even if the end-user didn’t perform the action themselves.
Using POST Requests
It is sometimes thought that using proper form-based POST requests will mitigate this attack, but that is not true.
Using HTTP-Only or Secure cookies
While you definitely should use these flags on your session cookie, they don’t implicitly stop the attack: the browser still sends the cookies to your domain when a request is made to your domain. Your server does not know if this is a real user or an attack.
How To Prevent CSRF
You can achieve this by relying on a set of rules that browsers respect, called the Same-Origin Policy. This policy asserts that certain sensitive operations are performed by JavaScript code that is running on our website, not some other website.
Angular packages the CSRF token approach, making it simpler for us to implement. For every request that your Angular application makes of your server, the Angular $http service will do these things automatically:
Look for a cookie named XSRF-TOKEN on the current domain.
If that cookie is found, it reads the value and adds it to the request as the X-XSRF-TOKEN header.
Thus the client-side implementation is handled for you, automatically! But this does leave the server side pieces in your hands. You will need to do the following parts:
During login: create the CSRF token (with a random, un-guessable string), and associate it with the user session. You will need to send it on the login response as the XSRF-TOKEN cookie.
Assert that all incoming requests to your API have the X-XSRF-TOKEN header, and that the value of the header is the token that is associated with the user’s session.
That’s it! With a little bit of backend work, you now have a strategy which protects you from CSRF attacks.
you will find a working example of how to prevent CSRF attack here
and for theory of understanding CSRF attacks please follow this reference

Using digest of your site's authentication cookie for CSRF

I want to protect my WebApi endpoints against CSRF. Angular team recommends to use digest of your site's authentication cookie with a salt for added security. I'm not sure what's the advantage here comparing to random token. What is more, how do you protect login page?
Here is explanation why do you need to protect login page https://security.stackexchange.com/questions/2120/when-the-use-of-a-antiforgerytoken-is-not-required-needed
The method you're describing is detailed here:
Cross Site Request Forgery (XSRF) Protection XSRF is a technique by
which an unauthorized site can gain your user's private data. Angular
provides a mechanism to counter XSRF. When performing XHR requests,
the $http service reads a token from a cookie (by default, XSRF-TOKEN)
and sets it as an HTTP header (X-XSRF-TOKEN). Since only JavaScript
that runs on your domain could read the cookie, your server can be
assured that the XHR came from JavaScript running on your domain. The
header will not be set for cross-domain requests.
To take advantage of this, your server needs to set a token in a
JavaScript readable session cookie called XSRF-TOKEN on the first HTTP
GET request. On subsequent XHR requests the server can verify that the
cookie matches X-XSRF-TOKEN HTTP header, and therefore be sure that
only JavaScript running on your domain could have sent the request.
The token must be unique for each user and must be verifiable by the
server (to prevent the JavaScript from making up its own tokens). We
recommend that the token is a digest of your site's authentication
cookie with a salt for added security.
The name of the headers can be specified using the xsrfHeaderName and
xsrfCookieName properties of either $httpProvider.defaults at
config-time, $http.defaults at run-time, or the per-request config
object.
In order to prevent collisions in environments where multiple Angular
apps share the same domain or subdomain, we recommend that each
application uses unique cookie name.
This appears to be a variation on the Encrypted Token Pattern CSRF prevention method, using hashing rather than encryption, and the salt is acting like the secret key.
It also relies upon a HTTP feature that prevents custom headers from being sent cross domain, much like adding X-Requested-With does.
The part that states "an unauthorized site can gain your user's private data" is slightly misleading, as CSRF does not allow this directly - a CSRF attack allows an unauthorized site to submit your site's forms in the context of the currently logged in user.
An advantage of this method is that you do not need to save anything extra server side. For example, if you are using token-based authentication you can easily verify that the CSRF token received matches the cookie by applying the same hash with the server-side salt. Even if you are using cookie-based authentication you do not need to verify the CSRF token against a separate value stored server-side - you simply hash the cookie value to verify that it matches the passed token.
See this answer for how to protect against login CSRF.

Categories

Resources