CSRF Double Submit Cookie is basically "not Secure" - api

From OWASP page : A CSRF attack works because browser requests automatically include all cookies including session cookies.
To prevent it, we can use double-submit cookie hash.
In some sample codes I found, basically this algorithm is found.
Victim access app:
Backend : generate login cookie AND hash string related to login
cookie
Frontend : store the hash string into second cookie (say :
CSRF-token cookie)
Frontend (secured) : send request with login
cookie and CSRF HTTP header, where the header value is extracted
from CSRF-token cookie.
Attacker :
Use some kind of social media engineering to make users click malicious link, where this malicious link use session cookie.
The attacker then steal this session cookie to logged in as victim
Double submit cookie should prevent this attack since attacker also need to provide valid CSRF token in the HTTP header.
I still don't get this: If browser requests automatically include all cookies, that means on clicking malicious link, both login cookie AND CSRF-token cookie will also included, and attacker steal both of them.
So the attacker is just need to extract value from CSRF-token cookie, and create his own API access, using login cookie that he steal, and CSRF HTTP header with extracted value?
Am I missing something?
Thanks

A few things appear to be mixed up here.
So in the original synchronizer token pattern, you would generate a random token, store it server-side for the user session, and also send that to the client. The client would then send the token back as a form value or request header, but not as a cookie, so it doesn't get sent automatically - that's the whole point. (And the server would of course compare the token from the request to the one in the session.)
In double posting, the token doesn't even need to be generated server-side, the client can also do it (or the server can send it, doesn't matter that much if we accept that crypto is good enough in Javascript).
The token will be sent as a cookie, and also as something else (form value, request header, anything not sent automatically). If the server sent it as a cookie (obviously without httpOnly), the client can read it from that and include as a non-cookie too in a request. The server will again just compare the two.
The point is that an attacker on attacker.com will not be able to access the cookie (neither read nor write) for the application domain. So if the client can read the cookie and include it as something else in the request, that client must be running on the application origin (if we are talking about unmodified browsers only), so no CSRF is being performed. The client can also create the whole token itself, because attacker.com will still not be able to create a cookie for the application domain.
So based on the above, if everything is just in cookies, the implementation is wrong, and does not protect against CSRF.

While Gabor has basically answered the question, I just wanted to add some emphasis on some of the important parts, since I was once also confused with this double submit cookie technique.
The main misconception here is to assume that CSRF attack happened because the attacker is able to steal the cookie from the "targetweb.com", while in fact the attacker doesn't need to know the value of the cookie at all!
For the CSRF attack to happen, the attacker only need 4 conditions:
The session on the target site has already been established (user has logged in to the "targetweb.com")
The attacker knows the request format of some operation (e.g transfer fund)
The session token is stored in cookie.
The user trigger something (e.g a button/link), that unbeknownst to him, send a request to the "targetweb.com".
All the attacker need to do is to make the user trigger the request that had been forged by the attacker without the user knowing (and the important part is, the forged request doesn't need to contains the session cookie, since it will be added automatically by the browser later when it is sent -- thus the attacker doesn't need its value).
Now, with the double submit cookie technique, the server send additional value in the cookie. The attacker doesn't know its value. And when a request is made, this value need to be also appended to, say, a request header (which not automatically added). The server is then compare this header value with the cookie value and only proceed when the value match.
What's different from the attacker point of view is now he need to append the value to the header also to make the request valid. And he doesn't know the value, thus CSRF is prevented.

CSRF protection with double submit cookie is not secure.
Therefore, in the OWASP documentation, the double submit cookie is classified as one of defense in depth.
The reason is that cookies can be set by a third party with MITM attack.
HTTPS requests and responses cannot be eavesdropped or modified. However, MITM attack can modify the HTTP response(plain text).
An attacker could direct the victim to http://example.com/ (Target site) to send a plaintext http request.
Then, in response, the attacker can use MITM to return a Set-Cookie header.
HTTP / 1.1 200 OK
Set-Cookie: CSRFTOKEN=XXXXXXXXXXXXXXXXXXXXXXX;
This CSRFTOKEN is set in the victim's browser.
Next, the attacker sets up a CSRF trap page below.
<form action="https://example.com/target" method="POST">
<input type="hidden" name="mail" value="evil#example.net">
<input type="hidden" name="token" value="XXXXXXXXXXXXXXXXXXXXXXX">
<input type="submit">
</form>
The destination of the above form is a https page, but the cookie set by http response is also valid on https requests.
So the cookie and hidden parameter will be sent the same value, bypassing CSRF protection.

Related

AntiForgery Token in ASP.NET Core

I am working in a Razor pages project. In ASP.NET Core, #Html.AntiForgeryToken() is applied for preventing cross-site request forgery (XSRF/CSRF) attacks.
And I read an article about it:
https://www.red-gate.com/simple-talk/development/dotnet-development/anti-forgery-validation-asp-net-core/
This defense strategy works just as long as the controller’s code that handles the POST double-checks that it is receiving a hidden field named __RequestVerificationToken and a cookie with the same name.
By using postman, I can just simply copy the cookies value and the antiforgery token, and append it with the request so that I can post without visiting the page. And the cookies and token can be used repeatedly.
My question is, how can I do to prevent users/hackers calling the handlers/controllers without visiting the page and ensure that the token only can be used one time?
Do I have to write my own solutions for this? Or Microsoft already provided a solution?
The antiforgery token prevents csrf attacks. It does this by denying post requests that only contain the cookie. If the attacker has access to the antiforgery token then it is over. This is why the token must change when you log in. And it must be invalidated when you log out. It doesn’t necessarily need to change for each request.
https://owasp.org/www-community/Anti_CRSF_Tokens_ASP-NET
There are many strategies. Microsoft does not recommend you add the token to your cookies collection, but if you do, you must use HTTPS. As you know, cookies are exposed in each request. You can strengthen them with HttpOnly and Secure. But if you add HttpOnly, you can't read it yourself.
A better approach is to use headers because your header won't persist after the request is over.
As for Microsoft, here's a good resource: enter link description here

Avoid refresh token for authentication when using HttpOnly cookie

I have a solution for an authentication system without using refresh token. Please tell me where are the vulnerabilities of this method.
I assume the following:
Client and Server are on the same domain.
Client is a browser that support HttpOnly cookie.
Client is using a Single Page Application.
The steps are:
User login by making a request to /api/auth with the credentials.
Server authenticate the user and send back a Set-Cookie Header with an HttpOnly cookie containing a JWT.
Client receive and set the HttpOnly cookie. Client also set in Local Storage a variable logged: true.
After sometime User reopen the browser. The Single Page Application check if the variable logged in Local Storage is == true. If so check if it still has the HttpOnly cookie by making a request to /api/check-cookie.
Server respond with true if it find the HttpOnly cookie and it is valid. Otherwise false.
Client, if receive false from /api/check-cookie, will prompt the user with the login.
With this approach the JWT can have a long expiration date and there is no need to keep track of refresh tokens.
Am I missing something?
I like your thinking and had similar ideas, particularly with setting a local storage variable to reflect the state as logged in so I could check that before making a pointless server call to refresh a token that potentially doesn't exist, however, I'm still using the refresh token.
I believe the crux of your issues will be when the user updates on the server side, it won't be reflected on the client side until the user re-authenticates with a new long-lasting, singular token as opposed to when the short-lived access token refreshes, setting the user again with the updated data.

Host Header Injection

I am a beginner in security and reading about the host header injection. I tested an application for this vulnerability and it is possible there for some request but developer implemented no-cache, no-store flags and this vulnerability is not in password reset request.
So first thing is there will not be cache poisoning. and the second is it is not happening in password reset request.
As I understand that for exploiting this vulnerability, I changed that host header. So I want to know why will It be a vulnerability, why a user will change Host of the application? and how an attacker can exploit it?
As in all of the cases the client input on the application should be never trusted (in security terms). The host header attribute is also something that can be changed by the client.
A typical attack scenario would be for example:
Lets suppose you have an application that you blindly trust the HOST header value and use it in the application without validating it.
So you may have the following code in your application, where you load a JS file dynamically (by host name):
<script src="http://<?php echo $_SERVER['HOST'] ?>/script.js">
In this scenario, whatever the attacker set as the HOST header would be reflected on this JS script load. So the attacker could tamper with this by manipulating the response to load a JS script from another host (potentially malicious). If the application is using any Caching mechanism or CDN and if this request is repeated multiple times, it can be cached by the Caching Proxy. Then, this can be served to other users as well (as it was saved to cache).
Another way of exploiting this is:
Let suppose that the application has a user password reset feature. And the application will send an email to whoever asks for a password reset with a unique token to reset it, like the email below:
Hi user,
Here is your reset link
http://<?php echo $_SERVER['HOST'] ?>/reset-password?token=<?php echo $token ?>
Now an attacker can trigger a password reset for a known victim email by tampering the HOST header value to the one of his desire. Then the victim would receive the legitimate email for password reset, yet the URL will be changed to the domain set by the attacker. If the victim would open that link, the password reset token could be leaked to the attacker so it would lead to account takeover.

CSRF Token necessary when using Stateless(= Sessionless) Authentication?

Is it necessary to use CSRF Protection when the application relies on stateless authentication (using something like HMAC)?
Example:
We've got a single page app (otherwise we have to append the token on each link: ....
The user authenticates himself using POST /auth. On successful authentication the server will return some token.
The token will be stored via JavaScript in some variable inside the single page app.
This token will be used to access restricted URLs like /admin.
The token will always be transmitted inside HTTP Headers.
There's NO Http Session, and NO Cookies.
As far as I understand, there should(?!) be no possibility to use cross site attacks, because the browser won't store the token, and hence it cannot automatically send it to the server (that's what would happen when using Cookies/Session).
Am I missing something?
I found some information about CSRF + using no cookies for authentication:
https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/
"since you are not relying on cookies, you don't need to protect against cross site requests"
http://angular-tips.com/blog/2014/05/json-web-tokens-introduction/
"If we go down the cookies way, you really need to do CSRF to avoid cross site requests. That is something we can forget when using JWT as you will see."
(JWT = Json Web Token, a Token based authentication for stateless apps)
http://www.jamesward.com/2013/05/13/securing-single-page-apps-and-rest-services
"The easiest way to do authentication without risking CSRF vulnerabilities is to simply avoid using cookies to identify the user"
http://sitr.us/2011/08/26/cookies-are-bad-for-you.html
"The biggest problem with CSRF is that cookies provide absolutely no defense against this type of attack. If you are using cookie authentication you must also employ additional measures to protect against CSRF. The most basic precaution that you can take is to make sure that your application never performs any side-effects in response to GET requests."
There are plenty more pages, which state that you don't need any CSRF protection, if you don't use cookies for authentication. Of course you can still use cookies for everything else, but avoid storing anything like session_id inside it.
If you need to remember the user, there are 2 options:
localStorage: An in-browser key-value store. The stored data will be available even after the user closes the browser window. The data is not accessible by other websites, because every site gets its own storage.
sessionStorage: Also an in browser data store. The difference is: The data gets deleted when the user closes the browser window. But it is still useful, if your webapp consists of multiple pages. So you can do the following:
User logs in, then you store the token in sessionStorage
User clicks a link, which loads a new page (= a real link, and no javascript content-replace)
You can still access the token from sessionStorage
To logout, you can either manually delete the token from sessionStorage or wait for the user to close the browser window, which will clear all stored data.
(for both have a look here: http://www.w3schools.com/html/html5_webstorage.asp )
Are there any official standards for token auth?
JWT (Json Web Token): I think it's still a draft, but it's already used by many people and the concept looks simple and secure. (IETF: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-json-web-token-25 )
There are also libraries for lot's of framework available. Just google for it!
TL;DR
A JWT, if used without Cookies, negates the need for a CSRF token - BUT! by storing JWT in session/localStorage, your expose your JWT and user's identity if your site has an XSS vulnerability (fairly common). It is better to add a csrfToken key to the JWT and store the JWT in a cookie with secure and http-only attributes set.
Read this article with a good description for more info
https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage
You can make this CSRF protection stateless by including a xsrfToken JWT claim:
{
"iss": "http://galaxies.com",
"exp": 1300819380,
"scopes": ["explorer", "solar-harvester", "seller"],
"sub": "tom#andromeda.com",
"xsrfToken": "d9b9714c-7ac0-42e0-8696-2dae95dbc33e"
}
So you will need to store the csrfToken in localStorage/sessionStorage as well as in the JWT itself (which is stored in a http-only and secure cookie). Then for csrf protection, verify that the csrf token in the JWT matches the submitted csrf-token header.

CSRF with Twilio

I am trying to get Twilio to work with my express/node.js installation. Twilio is making an incoming connection to my server, when it gets a text message. Then I am replying to this with a SMS response.
This works the first time. Then the second time, my server blocks Twilio because it says that it was a forged request.
Is there a proper way to get around this?
You should disable CSRF for that URL. See this question on how to do that: Disable csrf validation for some requests on Express
CSRF is a vulnerability that only pertains to requests that require session information in the form of a cookie (which is why CSRF is also sometimes called "session riding"). In short, CSRF is when a malicious site owner can use a <form> tag on a page they control to post a form to your site, causing an authenticated request to be sent to your server without the user's knowing. For instance, let's say Facebook has a /delete_user.php which deletes the current authenticated user. A CSRF attack on that URL will be in the form (no pun intended) of a <form action="http://facebook.com/delete_user.php"> tag on the malicious site owner's site, which gets submitted without the user's knowledge. A non-CSRF-safe implementation of /delete_user.php will see the user's auth cookie and delete the user -- much to the user's dismay.
Anyway, long story short, your Twilio handler does not require a user's browser cookie, and thus is not subject to CSRF attacks. Just disable CSRF checks for the Twilio callback URLs.