We're currently developing an entirely AJAX based app that will interact with the server via a RESTful API. I've considered potential schemes to protect against XSRF attacks against the API.
User authenticates and receives a
session cookie, which is also
double-submitted with each request.
We implement an OAuth consumer in
Javascript, retrieve a token when
the user logs in, and sign all
requests with that token.
I'm leaning toward the OAuth approach, mainly because I'd like to provide 3rd party access to our API and I'd rather not have to implement two authentication schemes.
Is there any reason why an OAuth consumer would not work in this situation?
Most AJAX libraries will set an additional header "X-Requested-With: XMLHttpRequest", which is difficult to fake in a basic XSRF attack (though possible if combined with XSS). Verifying that this header exists is a good defense-in-depth strategy if you expect all your requests to be AJAX.
Use a two-step request, the first asking for the server an unpredictible token, the second asking for the real action with the token.
As the attacker can't predict the token, and can't read it (same origin policy) he can't give a valid token in the second query.
But be careful to not leak tokens (learn about capturing json using when they affect value to a global variable and so on) and read :
http://www.google.com/search?q=xsrf+defence
The easiest way to prevent XSRF it to check the referer of every RESTful request to make sure the request is coming from the same domain. The session cookie is important for keeping state, but it will not defend against XSRF becuase it will also be sent with a forged request. Its common to see referer based XSRF protection system on embedded network hardware with limited memory requirements, Motorola uses this method on most of their hardware. This isn't the most secure XSRF protection, token based protection is better but both systems can still be bypassed with XSS. The biggest problem with token based XSRF protection is that it takes alot of time to go back and fix every request and you will probably miss a few requests.
Make sure to read up on the same origin policy and to scan your site for xss. You should also read the OWASP Top 10 for 2010 A3-Broken Authentication and Session Management.
Related
Consider a web application that consists of only HTML and JS for Front end and that communicates with a Web API.
I am trying to protect my application against CSRF attacks and for that I have took reference of this article.
Using the methods in this article, I am able to generate Anti CSRF tokens and pass it to the client. However it depends on first AJAX call that must happen before making regular CRUD operation calls.
With this approach, I need some clarity on few things as well as some alternatives if any. Consider a client visits this web application (which is protected by AJAX based Anti CSRF token), and keeping his session open, he visits a malicious website that contains page that makes the same AJAX calls to get CSRF tokens (assume that attacker is aware of this process), I suppose he can use the headers to make unintended calls thus resulting in an attack.
So how can I protect my application against these?
Please provide more detail regarding this, or if its misleading then help me by providing correct details so that I can tackle it better.
First of all you should use an encrypted communication with the server so the attacker won't be able to read any header data.
If your attacker uses the same calls as you do, he is not be able to guess the anti XSRF token that you use in your calls. A new token is generated for every call to your API. I hope this page helps you with some details:
https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet
I think if we use token based authentication, client have to pass authentication token in each request. And if client do not store it in browser cache and store it in localStorage then browser will not send token in call automatically. And if our service receive any request without auth token then it will discard the request.
I'm looking into JWT as an alternative to traditional sessions with cookies but I fail to see how they differ fundamentally from signed cookies that for example Express is offering through middleware like cookie-parser.
In both of them, the last part is the signature of the payload which guarantees the payload hasn't been tampered with.
Signed cookie:
user=tobi.CP7AWaXDfAKIRfH49dQzKJx7sKzzSoPq7/AcBBRVwlI3
Equivalent JWT:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiVG9iaSJ9.kCTlR_Igb4H5cqBEDedShM2ivSQijPQkWqN4pZAXb2g
Besides the facts that:
(1) JWT doesn't come with origin restrictions and that
(2) the cookie content is immediately human-readable, whereas the JWT content (header + payload) are base64 encoded
is there anything that gives JWT a clear advantage over signed cookies?
Beware of mixing the concerns: cookies are primarily a mechanism for storing data on the client, they aren't inherently an authentication mechanism - but we use them that way :)
The primary benefit of JWTs are the declared structure (JSON, with common fields) and the declared mechanism for signing them. This is all just specification, there is nothing special about it. But it is nice to have a common way of persisting identity assertions.
You still need to store your JWT in a secure fashion, and cookies with HttpOnly; Secure are the best option. This prevents the cookie from being read by the JavaScript environment, which prevents XSS attacks.
I've written some blog posts about JWTs, they contain more information that will help to answer your question:
Build Secure User Interfaces Using JSON Web Tokens (JWTs)
Token Based Authentication for Single Page Apps (SPAs)
Disclaimer: I do work at Stormpath. We sponsor open-source JWT libraries for Node.js and Java, which can be found here:
https://github.com/jwtk
If you are using AngularJS, we also implement JWT best practices out of the box with our Stormpath Angular SDK
Cookies are typically used to protect web applications. The browser will add them automatically to every request. This makes the requests vulnerable to CSRF attacks.
JWT tokens are typically used to protect Web APIs. The token is attached to the AJAX request in JavaScript. Since the token is not attached to the request automatically, the request is not vulnerable to CSRF attacks. JWT tokens can also be used cross-origin in case the API you're talking to is on another domain.
JWT tokens are also used in native clients to talk to web APIs.
I still cannot understand what is the main purpose of JWT. As for me the only purposes are:
to overcome CSRF
and to ensure better mobile support (because mobile apps in some cases don t support cookies).
Also there is a claim that with JWT you don't have to worry about session storage on the server side. This is not clear to me. How could JWT completely replace session storage on the server side? Does this mean that we put all session data into the JWT, encrypt it and send it to client on every response? But if so, does that mean the token that is issued by server will change depending on the data which we used to store in session? And as i understand the only thing that prevent us from using cookie this way(without session storage on the server side) is the size limit on cookie files - only 4kb.
Also do we still need to use SSL to prevent session hijacking?
Please tell me if my understanding is right or there is some other aspects.
I think there're too many legends about JWT. To understand its essence, we should get back to its original definition.
According to its official site:
JSON Web Token (JWT) is an open standard (RFC 7519) that defines a
compact and self-contained way for securely transmitting information
between parties as a JSON object. This information can be verified and
trusted because it is digitally signed.
So essentially, what JWT offers is just a way to transmit data. No more, no less. And because multi parties are involved, the format MUST be standardized. And once the format is standardized, libraries can be made to facilitate its adoption.
Again from the official site:
When should you use JSON Web Tokens?
There are some scenarios where JSON Web Tokens are useful:
Authentication:
This is the typical scenario for using JWT, once the user is logged in, each subsequent request will include the JWT,
allowing the user to access routes, services, and resources that are
permitted with that token. Single Sign On is a feature that widely
uses JWT nowadays, because of its small overhead and its ability to be
easily used among systems of different domains.
Information Exchange:
JSON Web Tokens are a good way of securely transmitting information between parties, because as they can be
signed, for example using public/private key pairs, you can be sure
that the senders are who they say they are. Additionally, as the
signature is calculated using the header and the payload, you can also
verify that the content hasn't changed.
So, Authentication is merely one of the possible use cases of JWT. Though it is indeed a typical usage of JWT.
As far as authentication is concerned, JWT can be used to replace session+cookie approach because it can save server's memory for storing sessions. But how big the benefit is depends on the user amount and your specific scenario. If there's only a few clients and no cross-domain authentication requirements, I don't think you need to give up the good old session+cookie approach.
Last but not the least, Session is not JUST meant for authentication. It is actually meant to place HTTP requests and responses within a larger context. I am not sure if JWT can replace session for that purpose given JWT's size limit. And IMHO, authentication just happened to be one of the use cases of session since such info must be user-specific. There are many other good scenarios to justify session, such as Shopping Cart.
JWTs in itself are just self-contained tokens and don't provide CSRF protection. The protocol used to deliver the JWT may (or should) provide means to prevent CSRF.
One area where JWTs are notably "better" than cookies is their cross-domain capability. You can read more on the comparison between tokens and cookies here: https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/
JWTs can be self-contained so they have all the information that you need in a verifiable container that would enable you to use them without storing them (or a reference to them). But there may be more data that you need in a session so avoiding session storage in general is not a reason in itself for moving to JWTs.
SSL is required for sure to prevent token leakage and session hijacking.
I'm trying to protect an application (php and lots of JS) from CSRF.
I want to use tokens.
A lot of operations are done with AJAX, so I have to pass the token in Javascript.
If I want to generate 1 token per session or per page load it's simple - I generate new token, put it somewhere in a DOM and then find it with Javascript and send to the processing side.
But what if I want to use new token for every operation?
I was thinking about doing an ajax call to regenerate token and then pass the result to processing page.
Does this increase security risk?
I was thinking about luring user to page with script which would ask for token and then use it to make the request but then again cross domain Javascript is forbidden.
Can it be done with flash?
Maybe another approach for protecting ajax calls from CSRF?
Thanks!
There are several techniques, which when used together provide a sufficient CSRF protection.
Unique Token
A single, session-specific token is good enough for most applications. Just make sure that your site doesn't have any XSS vulnerabilities, otherwise any kind of token technique you employ is a waste.
AJAX call to regenerate the token is a bad idea. Who will guard the guards? If the AJAX call itself is vulnerable to CSRF, it kind of defeats the purpose. Multiple tokens with AJAX are in general bad idea. It forces you to serialize your requests i.e. only one AJAX request is allowed at a time. If you are willing to live with that limitation, you can perhaps piggyback token for the second AJAX call in response to the first request.
Personally, I think it is better to re-authenticate the user for critical transactions, and protect the remaining transactions with the session-specific token.
Custom HTTP header
You can add a custom HTTP header to each of your requests, and check its presence on the server side. The actual key/value doesn't need to be secret, the server just needs to ensure it exists in the incoming request.
This approach is good enough to protect CSRF in newer versions of the browsers, however its possible too work-around this if your user has older version for Flash Player.
Checking Referrer
Checking for the Referrer header is also good to protect CSRF in the newer browsers. Its not possible to spoof this header, though it was possible in older versions of Flash. So, while it is not foolproof, it still adds some protection.
Solving Captcha
Forcing the user to solve a captcha is also effective against CSRF. Its inconvenient as hell, but pretty effective. This is perhaps the only CSRF protection that works even if you have XSS vulnerabilities.
Summary
Use a session based token, but re-authenticate for high value transactions
Add a custom http header, and also check for referrer. Both are not foolproof by themselves, but don't hurt
Today I implemented a session/token authentication system for my web api (http get/post rpc style), following this plan:
legend: action (param1, param2) : returnvalue1, returnvalue2
login (username, password) : sessionkey, token
requestA (sessionkey, token, paramA) : token
requestB (sessionkey, token, paramB) : token
logout (sessionkey, token) : void
The login action is sent over https, to protect the users data. You get a session/token combination, where one token is only valid for one request (you will always receive a new token on normal requests).
My thoughts behind this were about reducing the risk for a man-in-the-middle attack, sniffing your session key: if you are "lucky", the sniffed token has already been invalidated through your own subsequent request.
My backend and its unittests are perfectly fine, but i didn't think far enough - i finally ran into issues with asynchronous ajax calls, which defeat this one-time-token idea.
Is the added security worth not being able to process asynchronous requests?
One idea was to introduce a request-queue inside my ajax application - did someone do anything like that, and would you recommend it?
A probably less secure, but more convenient way would imho be not to renew the token for every request - allowing asynchronous processing, but keeping the initial https auth and add a strict lifetime to a session. I should also save the IP to the session server-side.
Did i miss other valuable options?
I am bound to existing username/password values, which with no exception have to work without changes with the new ajax app.
It appears to me that the token mechanism that you designed won't actually protect you from man-in-the-middle attacks. Imagine a man-in-the-middle intercepting every (non-HTTPS) request from the client, and replacing it with a different one that is then sent to the server. The token that the server returns to the man-in-the-middle can then simply be returned back to the client, and the client probably would not be able to tell that its request never arrived at the server.
Is there a way you can simply do all the requests over https? Https offers a fair amount of protection from man-in-the-middle attacks, provided that you use proper certificates, and use highly random session keys that are not valid for too long.
Any subsequent requests after authentication that are made in plain text (read HTTP) should be considered insecure and prone to any attack you can imagine.
If your goal is to secure the communication between the client and your server HTTPS is a must for the whole session. Additionally you will want to make sure you change the session cookie after the client moves from HTTP to HTTPS (I'm assuming here that you are doing some sort of redirection if the original request is to HTTP). This is a common error that leaves the client vulnerable to a session stealing attack.
Rails does something similar to the mechanism you are describing. They call their tokens authenticity tokens. However my understanding is that the primary purpose is to do flow control or double-click protection instead of actually securing the communication.
I think HTTPS and binding the Session to the clients IP and regenerating the session id from time to time (maybe every 5 requests) will secure your API. Adding the request/token mechanism will improve security, but is no longer a must have, imho.
One problem I see upcoming with the request/token system is, if a request failed or no answer is recieved, how can the client restart communication? It has no valid request token and if your API works correctly, it will reject any request following :)