I use AJAX on my site and tokens to prevent CSRF.
Is there any sense to use different HTTP methods instead of POST to increase protection against CSRF? or any other attack?
Assumption:
We use different security tokens and a constant HTTP method. Why not make it variable?
If a bad guy sends data by POST method but a server waits PUT method from this particular user.
From security point-of-view there is absolutely no difference how does data being transferred to server. So, answer is No.
Related
It seems creating and handling anti-CSRF tokens for Ajax calls in an Angular application is non-trivial and some are getting around the problem by applying a single token to every Ajax call. For example here.
The solution is quite neat. We just generate the token on the server and send it along with the first loaded page after sign-in. Then we ensure it goes out with all future requests like this:
$http.defaults.headers.common['RequestVerificationToken'] = 'token should go here';
But I am concerned this may simplify the job of an attacker. They need only get hold of $http in order to make any valid request. Is this the case? Is this method safe? Is there a 'best practice' regarding Ajax requests and CSRF?
Angular automatically does this for you.
Read Cross Site Request Forgery (XSRF) Protection section.
DOCS
I also suggest you read up CSRF, and what it is, if malicious script is already in your page it does not need to do cross-site requests to pose as the victim.
I know all about SQL injections, and peeking into javascript files that a website uses, and also that GET requests contain all of the information in a URL.
Is there any security concern that is special to AJAX and only pertains to using AJAX?
For example, sending post requests via AJAX seems completely safe to me. Barring SQL injections, I can't think of one thing that could go wrong... is this the correct case?
Also, are "requests" of any kind that a user's browser sends or any information it receives available to be viewed by a third party who should not be viewing? And can that happen to AJAX post requests ('post' requests specifically; not 'get')?
It's like any other form of data input: validate your values, check the referrer, authenticate the session, use SSL.
We are currently in the process of building a new service, the intent is to use PHP for the backend, and more importantly, use AJAX rather than regular HTTP requests for the frontend. So there will only ever be one initial page request.
While doing this, we'd also like to make sure that it is secure.
So the problem is this:
Login is based on regular username/password. The AJAX frontend will make AJAX-requests to the server as necessary, but what should be done to avoid unnecessary security issues? Hashing the password is obviously one, it can be further improved by also including a server generated token in the hash, etc, etc.
But, I'm sure there are established protocols for these things, but I really don't know the merits of them... or even what they're called or where to find them (note, the server itself is trusted).
Would using HTTPS make all this redundant? Or is for instance hashing the password still strictly necessary (theoretical question)? Would using a protocol still be important/useful/pointless over HTTPS?
http://en.wikipedia.org/wiki/Secure_Remote_Password_protocol, is that something I should look into? Does HTTPS make SRP redundant? Are there more suitable protocols, especially over HTTPS?
If you use PHP sessions, you should be fine. When you make a AJAX call, the server will be sent a cookie payload from your page indicating which session ID it corresponds to. Obviously, do this over HTTPS to make the communication secure.
I've created a RESTful API that supports GET/POST/PUT/DELETE requests. Now I want my API to have a Javascript client library, and I thought to use JSONP to bypass the cross-domain policy. That works, but of course only for GET requests.
So I started thinking how to implement such a thing and at the same time trying to make it painless to use.
I thought to edit my API implementation and check every HTTP request. If it's a JSONP requests (it has a "callback" parameter in the querystring) I force every API method to be executed by a GET request, even if it should be called by other methods like POST or DELETE.
This is not a RESTful approach to the problem, but it works. What do you think?
Maybe another solution could be to dynamically generate an IFrame to send non-GET requests. Any tips?
There's some relevant points on a pretty similar question here...
JSONP Implications with true REST
The cross-domain restrictions are there for a reason ;-)
Jsonp allows you to expose a limited, safe, read-only view of the API to cross domain access - if you subvert that then you're potentially opening up a huge security hole - malicious websites can make destructive calls to your API simply by including an image with an href pointing to the right part of the API
Having your webapp expose certain functionality accessed through iframes, where all the ajax occurs within the context of your webapp's domain is definitely the safer choice. Even then you still need to take CSRF into consideration. (Take a look at Django's latest security announcement on the Django blog for a prime example - as of a release this week all javascript calls to a Django webapp must be CSRF validated by default)
The Iframe hack is not working anymore on recent browsers, do not use it anymore (source : http://jquery-howto.blogspot.de/2013/09/jquery-cross-domain-ajax-request.html)
Django comes with CSRF protection middleware, which generates a unique per-session token for use in forms. It scans all incoming POST requests for the correct token, and rejects the request if the token is missing or invalid.
I'd like to use AJAX for some POST requests, but said requests don't have the CSRF token availabnle. The pages have no <form> elements to hook into and I'd rather not muddy up the markup inserting the token as a hidden value. I figure a good way to do this is to expose a vew like /get-csrf-token/ to return the user's token, relying on browser's cross-site scripting rules to prevent hostile sites from requesting it.
Is this a good idea? Are there better ways to protect against CSRF attacks while still allowing AJAX requests?
UPDATE: The below was true, and should be true if all browsers and plugins were properly implemented. Unfortunately, we now know that they aren't, and that certain combinations of browser plugins and redirects can allow an attacker to provide arbitrary headers on a cross-domain request. Unfortunately, this means that even AJAX requests with the "X-Requested-With: XMLHttpRequest" header must now be CSRF-protected. As a result, Django no longer exempts Ajax requests from CSRF protection.
Original Answer
It's worth mentioning that protecting AJAX requests from CSRF is unnecessary, since browsers do not allow cross-site AJAX requests. In fact, the Django CSRF middleware now automatically exempts AJAX requests from CSRF token scanning.
This is only valid if you are actually checking the X-Requested-With header server-side for the "XMLHttpRequest" value (which Django does), and only exempting real AJAX requests from CSRF scanning.
If you know you're going to need the CSRF token for AJAX requests, you can always embed it in the HTML somewhere; then you can find it through Javascript by traversing the DOM. This way, you'll still have access to the token, but you're not exposing it via an API.
To put it another way: do it through Django's templates -- not through the URL dispatcher. It's much more secure this way.
Cancel that, I was wrong. (See comments.) You can prevent the exploit by ensuring your JSON follows the spec: Always make sure you return an object literal as the top-level object. (I can't guarantee there won't be further exploits. Imagine a browser providing access to the failed code in its window.onerror events!)
You can't rely on cross-site-scripting rules to keep AJAX responses private. For example, if you return the CSRF token as JSON, a malicious site could redefine the String or Array constructor and request the resource.
bigmattyh is correct: You need to embed the token somewhere in the markup. Alternatively, you could reject any POSTs that do have a referer that doesn't match. That way, only people with overzealous software firewalls will be vulnerable to CSRF.