How is using Synchronizer Token Pattern to prevent CSRF safe? - javascript

I have been reading about using a synchronizer token pattern to prevent CSRF (CSRF meaning Cross-site request forgery.), and I don't understand how it actually safe.
Let's say I have a fake bank site fakebank.com with two urls:
fakebank.com/withdrawForm.html - a GET request which displays the withdraw money form
fakebank.com/doWithdraw - POST to this url to do the withdraw
My understanding of the security flaw is that maliciousSite.com can spoof a POST request to fakebank.com/doWithdraw, and if you're currently logged in to fakebank, the POST will be successful.
Let's say we implement a Synchronizer Token Pattern which will embed a secret code on fakebank.com/withdrawForm.html. Can't maliciousSite.com just spoof a GET request for that form, parse the html result, get the token, and then create the POST request with that token?
This is assuming fakebank.com isn't checking HTTP Referrer or Origin or maliciousSite.com is successfully spoofing that the Referrer/Origin is fakebank.com.

The reason why this is secure, and maliciousSite.com cannot simply do a GET, steal the token, and then do a POST is that the request is done by the user's browser, not by the server at maliciousSite.com. All data returned from fakebank.com is returned to the user's browser, not to the server at maliciousSite.com. If maliciousSite.com does perform a GET to retrieve a token, it will be a different token than was issued to the user. maliciousSite.com cannot set this cookie into the user's browser to be submitted to fakebank.com because of same-domain restrictions.
The CSRF POST attack works by tricking the user's browser into requesting fakebank.com/withdrawForm.html directly using a properly formed POST request. The server at fakebank.com happily executes the requested POST, thus transferring funds using the parameters supplied in the POST body (which include a destination account belonging to the attacker that was put there by maliciousSite.com). The server at maliciousSite.com doesn't need to see the data returned, because the action has been taken (unless fakebank.com uses these CSRF tokens, which the maliciousSite.com can't possibly know unless it has been divulged in some way. It can't ask for it). If fakebank.com is using CSRF tokens, then maliciousSite.com will submit a POST request that is missing the token, thus indicating a potential CSRF attack in progress.
Vulnerabilities of this method include using a CSRF token that is not kept sufficiently secret and is divulged in some way. Also, if the CSRF token is not sufficiently random, then maliciousSite.com might be able to guess it. Also, if there is a weakness in the browser's enforcement of same domain policy, this could be exploited. Generally speaking, modern browsers are not vulnerable to this.
Please let me know if this is an insufficient explanation and I'll attempt to articulate it a little better for you.

And that is exactly the point. The Same Origin Policy in the browser does not allow GET requests to other sites. So no site can GET the CSRF token from another just using Javascipt within the browser.

Related

Can this be a strategy to defend csrf? (double submit cookie)

used framework: nuxt.js + spring boot(api)
Invoke once api to generate random values and set httpOnly cookie(e.g. key=csrfToken) when the page is first accessed.
The api response is also stored in vuex.
(the response also has token body. with Set-Cookie header.)
When request using axios, If there is the "csrfToken" cookie, add custom header(e.g. key=CSRF_TOKEN_HEADER) to the request.
In the server, if csrfToken cookies are delivered, look up the custom header values to compare them to see if they are the same.
I know that $store is not secure in itself. However, I think CSRF is defensible because $store is not accessible from outside sites.
Please let me know if there is anything wrong with me.
When request using axios, If there is the "csrfToken" cookie, add custom header(e.g. key=CSRF_TOKEN_HEADER) to the request.
Since the cookie is httpOnly, you wouldn't be able to tell if there was or not.
A CSRF attack works by tricking the user into making a request that they didn't intend to make.
The traditional way to do this is to have a form on an attacking website which has the action sent to the website being attacked. When that form is submitted, the request comes from the user's browser and has all the user's cookies for the target website included.
The defence against this is to require that the request includes information that the attacking site cannot know. The CSRF token.
Since the attacking site can't read that token from the user's cookies or the site's session store (depending on where it was stored) or from anywhere else, they can't include it in the form data.
But you aren't using a regular form submission. You are using JavaScript to make the request.
This comes with a built-in defence: The Same Origin Policy and Preflight Requests.
All you need do is force the request to be preflighted (e.g. by setting the Content-Type request header to application/json and including a JSON payload in the body).
This will force a request from the attacking site to make a preflight request. Your server won't have the attacker whitelisted. The browser will therefore never make the attacking request.
If the attacker tries to make a non-preflighted request, it won't have the JSON payload, so your server can reject it as malformed.

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

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.

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.

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.

csrf token confusion. i can just get it with wget, no cross-origin problems. what's the point then?

I don't understand fully the point of csrf token protection.
That's the token that says that the POST is coming from my site.
But anyone has access to that token by just verifying their cookie content.
I don't understand then, how is this token protecting me?
To get the csrf cookie, can i make an ajax call to the server and just set the cookie that way? Will that break the csrf protection?
CSRF attacks involve malicious code hosted somewhere. The idea is this:
Attacker lures you to site, and your browser loads malicious code
Malicious code, in the context of that site it came from, attempts to carry out a POST to some known URL at some other secure site: your bank, your hospital, whatever.
If you happen to be logged in to the secure site, then your browser will have a secure session cookie for it. When the malicious code attempts the POST, then, your browser will dutifully send along the cookie. The bad code doesn't know what the cookie value is, but it doesn't have to.
The malicious code does, however, need to know everything else about how to put together the parameters for the POST request to be carried out. That's where the secure CSRF token idea comes from. The malicious code can't actually see what's on the pages in your browser from the real secure site. Thus, a secure site that expects a CSRF token won't see one when the malicious code attempts its POST operation.
(There are probably other variations on this; I'm not a security expert and I don't have exhaustive knowledge of attacks like this.)
csrf token confusion. i can just get it with wget, no cross-origin problems. what's the point then?
The part you're missing is cookies - wget will not send the cookie from the victim's browser along with the request.
The Synchronizer Token Pattern associates the CSRF token (which is visible in a hidden <input> field within the HTML) with the session cookie. If another user makes a request to get the CSRF token from your page, as they are not logged into the same session as their victim, this token will not be useable in their attack.
A CSRF attack works like follows. Imagine the following code on www.evil.com, a site that the attacker has managed to get their victim to visit (e.g. via a facebook post or an email):-
<form method="post" action="https://www.example.com/executeAction">
<input type="hidden" name="action" value="deleteAllUsers">
</form>
<script>document.forms[0].submit()</script>
As the victim is logged into your site (www.example.com) as an admin user, the form submission works and all users are deleted from your system.
The Synchronizer Token Pattern is the recommended way to fix this vulnerability. The CSRF token is a cryptographically secure random string. When a legitimate user loads your form and submits it, your system will check that the token POSTed matches the one expected. Any attacker cannot read the token from your site as any cross site access is protected by the Same Origin Policy
There is another prevention method known as Double Submit Cookies (which may match the method you are talking about). This works in a similar way, although there is no server side state of the CSRF token stored. This requires a cookie value to match a CSRF token that is submitted with the form, but as the attacker cannot set this cookie nor read it, they do not know the value to set the form submitted value to in order to match the cookie.

Categories

Resources