I have a question about stopping spoofed form submissions. How about if by using the $_SERVER['HTTP_REFERER']
I only allow submissions to my forms coming from my website? Would that help?! Thanks!
It would help, and it's fairly easy thing to add but it wont stop a targeted attack, after all you can spoof a HTTP_REFERER
header.
One thing to keep in mind is that a client is not required to send a HTTP_REFERER
, so if the header is missing you might want to allow submissions anyway. If this is not possible, then checking HTTP_REFERER
wont help you.
Run a search for CAPTCHA "Completely Automated Public Turing test to tell Computers and Humans Apart", this is what you're really looking for.
Stop? No. Limit? Possibly. Is your website really being hit with an alarming number of spoofed form submissions, or are you just being preemptive? Don't solve problems that aren't there.
Let us be clear: it's technically impossible to prevent spoofed form submissions. Summing it up in one sentence:
If your browser can do it, everyone can do it.
The referrer is easily spoofed.
You should validate the form best you can to catch out stupid bots, and possibly use a server side CAPTCHA.
Referer is easy to spoof, so any attacker that wanted to spoof a form submission could just spoof the Referer header as well. Also, I don't believe web browsers are required to send the Referer header, so it could potentially exclude form posts from legitimate users.
Try a captcha like ReCaptcha. Not only you will prevent spambots from spamming your website but you'll also be able to "authorise" only those people who use your form (at least to some extent - they will need to load your form to get the captcha and then send a response).
Doesn't really help. Read this: http://shiflett.org/articles/form-spoofing
Spoofing HTTP headers is pretty easy and so shouldn't be used for something that requires rigorous security. One technique typically used is to send both an encrypted cookie and a matching, encrypted token in a hidden input on the form. The cookie should be an HTTP-only cookie. On form submission check that the value from the cookie and the value from the hidden input match. This will help prevent cross-site request forgeries since a request to your site can't be successfully made from another site because they'll either be missing the cookie (for a MIM attack) or the hidden input (spoofed form). Of course, this depends on you making sure your site is otherwise secure so they can't sniff the tokens to find out what to supply.
Here's a nice discussion on how this is done in ASP.NET MVC, http://blog.stevensanderson.com/2008/09/01/prevent-cross-site-request-forgery-csrf-using-aspnet-mvcs-antiforgerytoken-helper/
The main issues with form spoofing is that you don’t have any control over what the client sends. The user could change any form parameter. So everything the client sends on form submission needs to be validated and verified.
This also means, the less parameters you provide to be send in the form, the less you need to validate and verify. Particularly parameters that are preset and not to be changed by the user (i. e. hidden form fields) don’t need to be embedded into the form if not really necessary. Instead you could store them in a container in the session and only refer to this container via a hidden field. If this is not an option, make sure that you at least can detect any integrity flaw by singing the preset values with a MAC.
Another issue is that the form parameters that need to be send for a successful form submission are quite predictable so that an attacker could send repeatedly valid form submissions. If you would require a non-predictable parameter that can only be issued by your server and is validated on form submission, you could verify that the form submission is granted.
One solution would be to use a random one-time token that is generated on form request and is stored in the session as well as put into the form as a hidden input field. Then on form submission you check if a token was provided and whether it is equal to the one stored in the session; if they are equal, the you remove the token from the session and process the form, otherwise you deny the form processing.
Frankly, this mechanism is not perfect as you could still request the form first and then send a spoofed form data. That’s where you could use additional Captchas or other mechanisms that prevent automatic requests.
The best would be to use a combination of all measures mentioned above:
Additionally, these session based form containers do also prevent CSRF as their identifiers are unpredictable for an attacking third party.
Without definition of "spoofing" it would be but empty talk.
There are a dozen of different "spoofs", each with it's different protection.
Most general solution is CAPTCHA.
A suggestion would be to use a token. If you are using any of the popular MVC architectures, you do not need to worry as spoofing prevention is taken care of. But if you are on a custom MVC Architecture like myself, a token is an approach. In your Database class, for every CRUD(CREATE, READ, UPDATE AND DELETE) function, check for the token. e.g the token can be generated via md5.
public function save(){
if(isset($_SESSION['token']){
//proceed with saving
}else{
//kill it,
die;
}
}
Alternatively, you can easily integrate your web application with this Cross-Site Request Forgery protection kit. Check it out here