protection against CSRF without hidden input in all forms - php

I wonder if I could put the crsf token in <head>, on a meta tag or something, and then access it on my server. It would really simplify the process and make it more transparent. I just don't know how. I was really hoping to do this without javascript involved.
I think rails implements something like that...with etags maybe?

There are many methods listed on the CSRF prevention cheat sheet. One that doesn't require a hidden field on every form, is to check the referer. Keep in mind the lack of the referer should be considered a CSRF attack and may cause problems with some privacy browser addons (which is very uncommon).

The fundamental purpose of a CSRF token is that it is delivered back to the server with each form submission. You deliver the unique token to a page, and when the form on that page is submitted the token comes back with it.
If you don't include the token on the form (or use JavaScript to programmatically add a token to the form that's currently elsewhere on the page) it will not be sent back to the server.
Perhaps the better question is: what is it you're really trying to accomplish? In other words, why would you not want to include a CSRF token within the form? What's the disadvantage you'd like to overcome in your scenario?

Related

CSRF Token simple way to add to forms in PHP

I have developed a project that is quite big, I was thinking in improving security by saving a token in Session variable and sending that token in each form to check if it is correct to prevent from CSRF attacks.
The thing is that the project has many forms and it could be painful and take a lot of time to go through each form in order to add the token in a hidden input.
So I was asking myself, is there any easy way to add that hidden value to each form without having to go through each form?
Maybe using jquery, I could localize each form inside the page to add a hidden input, then add a general $_POST/$_GET function to check for any request if token is correct.
This is an idea, but probably there may be another simple and better way.
Is there any simple, fast and decent way to do so?
What would be the best approach in this situation (preparing CSRF attack prevention after project has been developed).
As far as I know the best way to prevent from CSR attacks is using token variables, is there maybe another decent way to do so without having to use a token and go through each form?
See here: Automatically insert CSRF token in all forms with JQuery.
You could add some code to a function, inline in a <script> tag as demonstrated:
jQuery(document).ready(function() {
jQuery("form").each(function() {
var tokenElement = jQuery(document.createElement('input'));
tokenElement.attr('type', 'hidden');
tokenElement.attr('name', 'token');
tokenElement.val(<?= $token ?>);
jQuery(this).append(tokenElement);
});
});
This will automatically add the server side $token to be included as a hidden form field for each <form> element.
If you want to achieve this without any server side processing, with the added benefit that all the above code could be included in a .js file, you could store the token in a cookie and simply access this value client side (using COOKIE plugin):
tokenElement.val($.cookie("csrftoken"));

How much of an html form can be altered without triggering CSRF protection?

I implemented CSRF protection by including a token with PHP into a hidden input for every form. Each token can only be used once, of course.
However, there are tools, such as any web developer tools, which allow inputs to be changed. For example, I can change on-page input forms: I can make disabled checkboxes enabled, and I can change input boxes to textarea boxes without reloading the page or anything like that. CSRF wouldn't catch such changes.
So, how much of a form do I need to validate to stay safe? Do I need to validate every single input to make sure it wasn't altered, including selects, checkboxes, hidden inputs, etc? Surely it can't be safe to assume that these haven't been altered?
You need to validate (on the server side) everything that needs to be validated. What exactly needs to be validated depends on many factors and personal choices. Some of it may be for safety, but only a bare minimum is needed for that in many cases. For the most part validation is to improve or create user experience.
For example you can check to see whether they have entered a valid email address. If they haven't, you can give them a message. If you don't do that nothing bad will happen to your application, but the user won't be able to receive email from you.
There is also an important distinction between validation and sanitation. Sanitation is done for security (e.g. to prevent injection). Validation is done to make sure that input meets requirements to work correctly with your application although incorrect input may be benign. It's also possible for sanitized malicious input to be valid.
All input must be sanitized. No input needs to be validated, so it's really up to you.
CSRF protection has nothing to do with validation. All it does is prevent a user from making a request using your form from an external source because the only way to generate and see the token is to make a request to your site first.
What we are trying to do using CSRF is to ensure that the request IS coming from a reliable source. For e.g, your case what you need to do is ensure that the value in the hidden field is sane. And it can be sane (provided that your token is strong enough) only if it is the same as the one that was provided while the form was rendered by the server.
Now whether fields in the form changed or not, is just your application logic. It does not have anything to do with csrf. If the token is sane, then it came from the right source. Now, if it was the same person who entered values in the form for e.g. is not within the scope of csrf.
I think you are getting the wrong end of the stick here. The token is not a hash of the form when it was sent.
The way this works is to store your unique token in a hidden field on the form and into the session when you server the original page.
When you get the page POSTed/GETed back from your user you check that the token on the page is the same as the token previously stored in the session.
Changing fields must still be allowed or your user will not be able to enter any data on the form. You are just checking that you got the same form back that you sent, because the token is the same, rather than one from somewhere else, i.e. its not a cross site request forgery.
You still have to validate all the fields and do any data preparing before storing it in a database.
Reading1
Reading2

Should I send POST data cross domains?

What is the best practice as such? I have an iframe with a form and when it submits it updates the parent page. Currently it sends the form contents via GET so the parent page url reflects this. I can do the same via POST, but am wondering if this is frowned upon and if sometimes this is blocked/ unuseable.
Any help and advice is welcomed
There are no problems caused by using POST across domains (at least none that you wouldn't get from using POST on the same domain or GET on a different domain).
There is no problem submitting a form to a different domain, unless via javascript.
One concern to keep in mind is validations. You would want to take care on what happens when the form has errors, as you wouldn't want them to loose the information they've typed in if they missed something like 'name'. The server should be the final line of defense for validations, but you'll want to make sure that the client side validations for your form match those of the server and appropriately notify the user of their (or the server's) mistake.
The other thing that could potentially block a form from submitting over post would be a form that requires an authentication token. These are used by many different frameworks to prevent CSRF (Cross-site request forgery) attacks and ensures that the form was submitted from the same website domain.

Prevent CSRF on things which aren't part of forms in codeigniter

I know that Codeigniter has a very useful security class which can prevent CSRF/XSRF if you use the form helpers, but since the CI url structure calls a lot of functions pretty much directly, how can I prevent CSRF for things like /action/logout without having an additional confirmation form like SE has?
Ideas I've had:
Check page referrer
Check requested MIME type (even possible?) (for image CSRF such as <img src="http://example.com/action/logout" />)
Make all actions part of a form (not preferable)
Include the CSRF token in the page URL (ugly and very bad, users like to copy and paste urls without regard for session IDs stored or other private information)
I won't bother protecting things like /account/view/1/cyclone/ since it doesn't perform an action and would at most be a waste of bandwidth.
Granted, I do know that some people like to code things to automate their website usage and I respect that, which is why I'll be creating an API for performing actions via code or automatically.
As a general rule, any form request that performs an action should use POST. For all else GET is permitted. Using POST will definitely help. I believe you can also include the token as a hidden field in the form instead of an ugly string in the URL. As for checking the requested MIME type, this is not possible. Do a print_r($_SERVER) and in there is basically everything you get from the user as well as server side stuff.

Security: Form Submission + javascript/jQuery

Question:
What is best practice for form submissions while keeping in mind security?
This may be a n00b question but I'm concerned that people might be able to alter some data as its being submitted. Take my example:
I have a form that has a hidden input that stores a user's unique Facebook ID. I take that Facebook ID and create a user account from it. If I use jQuery, won't some users be able to change the data being posted?
It is just as safe as a regular form post. Both methods can be hijacked and data injected. The key is how your server side scripts validate the data alongside authentication, session, anti forgery tokens etc
Users will always be able to post whatever data they like to your server. You can't do anything to change that with javascript. With a decent browser it's easy to find hidden form fields, unhide them, and put whatever you want in them. A more skilled user can craft an http post by hand and send whatever they like. Security must be done on the server, not on the client.

Categories