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.
Related
Is it safe to build an API to provide CSRF one-time use token to avoid CSRF attack? Will this open a new vulnerability?
I have one more doubt regarding the traditional approach of including CSRF. I wonder that providing the csrf token in the form can be scraped and attack may be implemented by the attacker. Please correct me if my thought process in incorrect.
First of all you need to understand how a CSRF attack looks like. Someone can send you a link to http://malicious.com/whatever.html. You open this site and there will be an invisible form, that will send a POST request to http://example.com/account/1/delete. You will be logged into example.com on some other tab, so assuming the session is handled via a cookie, the cookie gets automatically attached and you execute a request you never intended to and are even unaware of.
We can mitigate the CSRF issue via different means, on of the being anti-CSRF tokens. The idea is that there is some kind of secret malicious.com will be unaware of and that can not easily be guessed. Please note, that in the CSRF scenario your means of attack are making people open some link. You have no access to the content of what they are seeing. You just send them a link and expect some requested to be executed with their access rights.
I've been struggling with this and would love to see if any OAuth experts here have an answer.
For context, I'm trying to integrate OAuth into an existing first-party (internal) front-end client that lives on a subdomain. It's a single-page application. I have an authorization server that has an /oauth2/authorize and oauth2/token endpoint and I'm working with the OAuth 2 with PKCE authorization flow.
In all the examples I've seen externally, it seems like the recommendation is to make a top-level redirect to the authorization URL initial login . And for silently re-authenticating a user (if they were already logged in), using an invisible iFrame set to the authorization URL (and postMessaging the code back to the parent window).
I'm trying to understand what prevents me from making a front-channel request to my /authorize endpoint via Javascript. Something simple like...
const { state, code } = await fetch(authorizationUrl)
For the login case, I can handle a 403 error back from the AS and then redirect them to login from the client-side. For the re-authenticating case (i.e. client has an expired refresh token but is still logged in), this is great because I just get a 200 response and the code back directly in the JSON body and I can use it immediately. There is no top-level redirect, no hassle of saving app state, etc.
It seems like as long as the AS is willing to return the { state, code } via JSON, this should work. This means that
The AS authorize endpoint must be configured to allow CORS on select origins. This seems okay in a first-party context since I know which origins I should allow.
The AS must be sent client credentials (session cookies) with the request (otherwise the AS would have no idea how to determine if the user is logged in). In JS, this would be as simple as adding credentials: true. As long as the cookie credentials have Same-Site: None and the cookie is part of the same domain (cross-domain would not work since some browsers disable cross-site cookie sharing nowadays!)
I feel like I'm missing something crucial here. But at the same time, my prototype is working, so I'd love to get some input from experienced folks here.
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.
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.
Background
We are integrating third party email solution into our site. When a user goes to the Mail page it must be automatically authenticated at the Mail site.
For now, the Mail link points to our page which automatically submits a form with the user's login and password. After clicking submit the user is redirected to the Mail site with authentication cookie.
The problem with this approach is that we do not want the user to see his Mail password, because we generate it automatically for him and there are some sane reasons not to show it.
Question
Is there any way to receive mail authentication cookies without sending the login information to the client and performing form.submit operation from the client's browser? Is there a better way to do what I'm trying to do?
Edit
Of course "I am trying to do it programatically". Looks like that there are no sane solution except pass these login/password to the client. Looks like we must accept that user can see his mail password and somehow make sure he cannot use this information to change password to some other value we will not know.
Edit: I didn't read the post correctly, I thought he was trying to login to a remote mail application, not one hosted on his own server. Ignore this answer.
When you login to the remote third party mail website, they will create a cookie (since HTTP is stateless, it's the only way it knows the user is authenticated unless they store some kind of session ID in the url). When you send the user to that site, the site needs to know how to authenticate the user. Even if you logged in from your application and grabbed the cookie, you can set a cookie on the users browser for another website. The only way for this to work is if there is some kind of development API on the third parties website you can hook into, or they allow you to use session id's in the URL.
Possible solution but has a security risk
If they allow you to set a session_id in the URL (for instance, PHPSESSID in PHP) then you could grab the session ID and append it to the URL when sending it to the user. I don't really like this idea since if the user clicks on a link in an e-mail, the new page will be able to check the referrer and see their session ID in the URL. This can become a huge security risk.
Lookup topics related to your mail vendor and "Pass-through Authentication." You did not mention what vendor/software you are using for your web mail solution, so I can't help you very much there. Other than forwarding the user's information (in a post request) to the login handler.
Generate unique IDs before sending an email and put them as hidden instead of username/password into form. Make them disposable (usable only once or usable once before successful entering the site)