Ensure that PHP form process file is only used with specific web form page? - php

I am a little new to PHP, and I have gotten in the habit of creating a specific file that handles all the form processing.
For example, I have one PHP file that displays the actual form, let's called it "registration.php" for example, and it specifies as its action "registration-process.php". A user fills out the registration form on registration.php, hits submit, and the data is POSTed to registration-process.php because it was specified as the action file by the form.
Now my question is this: Can't someone who knows what they are doing POST data to registration-process.php without going through registration.php? This would have the potential to lead unexpected consequences.
Is there any way to ensure that registration-process.php will ONLY accept POSTed data from registration.php? Like maybe a hidden field with a value that gets encrypted via some PHP code, and that value gets checked by the registration-process.php file? I wouldn't know how to do that, however, or if that's even the best solution.

Yes, using a hidden "security token" field is a common way to verify a forms integriy. Many public forums are using this method.
Try Google for php form security token or check out this site:
http://css-tricks.com/serious-form-security/

Can you only accept POST data from one location, probably. It is worth it, probably not.
As long as you are validating your form fields correctly (make sure what you're getting is within the realm of what you're expecting) there won't be any negative consequences of leaving it so anything can POST to it.
Also, technically you can send POST data to any file on the web, it just depends on what the file does with it whether or not it means anything.
Also, what Mario Werner is talking about is CSRF tokens. That won't stop other things from posting to your site, it just adds a level of security that makes sure the request came from the right place. For a detailed explanation, you can read this: http://en.wikipedia.org/wiki/Cross-site_request_forgery

Related

Protect backend from multiple form submits in Laravel

I'm trying to protect my backend from multiple post requests to avoid duplicate data on the database and the server overload.
I've already blocked the frontend disabling the submit button after a first click, but it will not prevent some "smart user" to submit my form from the console or disable javascript from the page and try something.
So I want to know if Laravel has some solution for this case.
PS: I've already tried some solutions on the backend too if you want I can post here.
As requested:
So one of my alternatives is check if the incoming data is already on the database and denied the request if is it, it will prevent the duplicate data but not the server overload.
Another alternative is to create a token in session for one use only on Create() method from the controller, send the token to the view and put it on a hidden field, retrieve it from post request and check the post token with the session token. If the two tokens are the same, then unset it to avoid others requests try using it and if they try I deny the request.
If you know who your users are (because they have an ID) then this is somewhat easy to do. Possibly use some sort of quick-access system such as Reddis to check-in that a user is in a state of edit while the action is being carried out.
However that creates complications of its own. Also doesn’t work if you don’t know who your users are.
The safer thing would be to make sure that your requests can handle potential problems. Consider using database transactions to ensure the integrity of the data.
It would depend really on what you’re trying to avoid, why you are, and what kind of data you’re worried about duplicating.
if it's too important for you to protect for multiple submit u can put a random string in hidden input in your form and also put it in a special session for each form you have and check it every time and after that try to change your session after each time you end your proccess

How can I protect a form processor script file?

I have set up a rather complicated HTML form that uses the JQuery Validate plugin with several required fields and various rules. Form is working great. It POSTs to a separate PHP processor file that does a number of things such as send a couple of emails and eventually sends the user to Paypal. (It is a club membership application.) It appears that it only took about a week for some type of "bot" to find the processor file and start running it directly over and over. About 500 emails & apps were generated before I caught it and stopped it by renaming the files temporarily. At the time it was happening I wasn't quite sure exactly what was going on, but after evaluating it for most of the day I came to realize that it couldn't be as a result of the main form being executed, but by just running the processor file directly.
So...my question is this: How can I keep this from happening? There must be some type of coding to include that will ensure that the processor can't run unless it is really coming from the real HTML form...or is there a better way? I followed all of the "examples" on the 'Net in regards to forms and POSTing but nowhere did I see anything that relates to this type of problem.
Generally this can be reduced by adding a CSRF token to the form.
Set a random sha/md5 value to your session, and set that value in the form also as a hidden input, upon a legit user sending the form that value will be passed along too, validate and check the passed value with the one in session. if all is good process.
If its a bot, the bot would need to parse the form for the CSRF token first. Or you could step up and make that security key an image and make the user type it (captcha).
How to properly add CSRF token using PHP
Its something you should also add to your login forms ect, else your have bots brute forcing there way in.
Maybe you could add a $_SESSION[] global variable on the form page. Then check it on your processing page and unset it after execution. Sounds like the simplest way to me, but you should hear out what others suggest. You can fin documentation on $_SESSION[] variables here PHP $_SESSION
Add a token to the form when generating the page, and save it into the session.
When you got the post data, check the token with the one in the session.
And you probably want to use CAPTCHA code to protect yourself from the bots.

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.

Data from the exact form

I have been googling a lot but i am still without an answer so i decided to ask this question here:
Is there a way in PHP how to check that the data i am receiving in some script are from the specific form on the page? I am asking because everyone can see the name of the script i am using for saving the data to my database, so if somebody is able to find out the whole URL, he is also able to send some fake data to the script and i need a condition, that the saving process is triggered only when the data comes from the proper form on my page.
I am using jQuery to call AJAX function, so basically if i click on the button "send", the $.POST() method is triggered to call the script for saving the data.
Thanks,
Tomas
Use tokens to check if request is valid
You could always add some kind of security token when submitting data:
Tokens can be easily extended for many different uses and covers wide area when it comes to checking if some request is valid, for example you could let your non critical forms open for public, ask users to get their secret keys from some page (forcing them to open that page) and then use those keys to identify them when submitting data.
Of course all of this can be completely transparent to user as you could give keys from front page via cookies (or session cookies, it does not matter here, no more or less security as server keys should change after use and invalidate within specified time or when user's identity changes).In this example of use, only user that opened front page can submit data to server.
Another case is when cookies is given away at same page which contains form for submitting data to server. Every user that open page will have their keys to submit data straight away, however if someone tries to make request from outside it will fail.
See OWASP Cross Site Request Forgery
and codinghorror.com Blog CSRF and You
Only with AJAX?
Here is my answer to another question, this answer covers different methods for inserting additional data to ajax request: Liftweb: create a form that can be submitted both traditionally and with AJAX (take a closer look at
$.ajax({
...
data: /* here */
...
Currently I am using tokens this way:
Form used to submit
This hidden input can be added to form, it is not requirement as you can use methods described earlier at another answer.
<input type="hidden" name="formid" value="<?php echo generateFormId(); ?>" />
Function generateFormId()
Simply generate random string and save it to session storage
function generateFormId() {
// Insert some random string: base64_encode is not really needed here
$_SESSION['FORM_ID'] = 'FormID'.base64_encode( uniqid() );
// If you want longer random string mixed with some other method just add them:
//$_SESSION['FORM_ID'] = 'FormID'.base64_encode( crypt(uniqid()).uniqid('',true) );
return $_SESSION['FORM_ID'];
}
Processing submitted form data
if (!isset($_SESSION['FORM_ID']) || $_SESSION['FORM_ID'] != $_POST['formid']) {
// You can use these if you want to redirect user back to form, preserving values:
//$_SESSION['RELOAD_POST'] = $_POST;
//$_SESSION['RELOAD_ID'] = uniqid('re');
echo 'Form expired, cannot submit values.';
//echo 'Go back and try again';
exit(1); // <== Stop processing in case of error.
}
If you need to check which form is submitting data
Then you could just add prefix when generating id's and check for that prefix when processing form data.
This is case when one php script deals with many different forms.
Remember that only ultimate answer to prevent evil users is to pull off all wires from your server...
This is an interesting topic, but you are missing an important point: A spam robot / bad user could also bomb your database by using that specific form page (!).
So, the question is not how to check if the request comes from that page or not, the question is how to check if he's a regular user or a robot/spammer/bot.
Do it with a captcha, like http://www.recaptcha.net
In case i slightly misunderstood the question: If you want to be sure that the request comes from a "real" user you will have to work with a login system / user system and check for users id / password (via db or sessions) every time you want to do a db request.
You can verify that the page is being requested via AJAX with checking against this:
strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) != 'xmlhttprequest'
You could also check the HTTP_REFERER.
But it sounds like you're trying to protect a page that processes vulnerable data. This requires more than just the two things above. I'd recommend googling 'CSRF Forgery' to get more information on this.
These are something that you should take a look at.
Capthcas.
Referer check.
Use POST than GET. [Still Curl can automate it.]

Categories