patternphpModerate
PHP form with bot deterrent
Viewed 0 times
withphpbotformdeterrent
Problem
-
I saw somewhere on here that it helps reduce spam by adding a dummy input field that you hide with
-
I don't know if my token validation stuff is anywhere close to how it should be. Please let me know if what I'm doing with that is even adding any security or not.
-
After the user submits the form, I put some echo's in so that what they entered is still shown in the form fields, in case there was an error so they don't lose what they typed. Is my use of
Please share any other comments, recommendations, improvements, etc, etc that you see with my code, because I really want to get better at this and your answers almost always help me understand things better. You know, the manual can be kind of confusing at times when your new so having a master coder review your code and explain things helps so much for me.
```
checker: " . $_SESSION['token1'] . " and the post token " . $_POST['token'] ."";
if(filter_var($_POST['youremail'], FILTER_VALIDATE_EMAIL)) {
$name = htmlspecialchars($_POST['yourname']);
$email = htmlspecialchars($_POST['youremail']);
$from = $name . ' - ' . $email;
$ip = getIp();
$message = htmlspecialchars($_POST['yourmessage']) . "\r\n" .
'Name : ' . $name . "\r\n" .
'Email : ' . $email . "\r\n" .
'User IP: ' . htmlspecialchars($ip);
$message = wordwrap($message, 60, "\r\n");
$headers = 'From: ' . $from . "\r\n" .
'Reply-To:
I saw somewhere on here that it helps reduce spam by adding a dummy input field that you hide with
display: none, and like if it's filled out, then it's obviously a bot sending the message. Well, I did something kind of like that but initially set it to = 0. So if it's not 0 then it doesn't send the form, since a bot would have changed the value to something else. I don't know if that will really work effectively or not. If you have a better way to do something like that, please share.-
I don't know if my token validation stuff is anywhere close to how it should be. Please let me know if what I'm doing with that is even adding any security or not.
-
After the user submits the form, I put some echo's in so that what they entered is still shown in the form fields, in case there was an error so they don't lose what they typed. Is my use of
htmlspecialcharacters needed there?Please share any other comments, recommendations, improvements, etc, etc that you see with my code, because I really want to get better at this and your answers almost always help me understand things better. You know, the manual can be kind of confusing at times when your new so having a master coder review your code and explain things helps so much for me.
```
checker: " . $_SESSION['token1'] . " and the post token " . $_POST['token'] ."";
if(filter_var($_POST['youremail'], FILTER_VALIDATE_EMAIL)) {
$name = htmlspecialchars($_POST['yourname']);
$email = htmlspecialchars($_POST['youremail']);
$from = $name . ' - ' . $email;
$ip = getIp();
$message = htmlspecialchars($_POST['yourmessage']) . "\r\n" .
'Name : ' . $name . "\r\n" .
'Email : ' . $email . "\r\n" .
'User IP: ' . htmlspecialchars($ip);
$message = wordwrap($message, 60, "\r\n");
$headers = 'From: ' . $from . "\r\n" .
'Reply-To:
Solution
Right, I'll be adding to this answer later on, but for a kick-off, here's a few quick remarks/considerations:
On the hidden input fields
As Martijn said in his comment: most bots will probably parse the DOM, and filter out those fields that are marked as required (looking for labels with a
It's not hard to deal with that, and if I were to write a bot, it wouldn't take me 5 minutes to add the code to deal with those input fields, too.
You can keep those hidden input fields as a means of security (they don't do any harm, after all), but don't set their style attributes in the markup, use CSS classes, or better still: use JavaScript to set class/attributes on the load event. That way, the DOM doesn't reflect what the page will actually look like as much as it does now.
This may help a little, but all in all, this will only protect you from script-kiddies and amateurish attacks.
The token stuff
That's fine. Session tokens that should be posted back are basic security steps that everybody should take. How you get those tokens is up to you, but an
Of course I get that a hash string just makes the token look more important, and in a way less random than it actually is, but why not hash some of the clients data in that case, like the remote address or referrer or whatever... though far from reliable, it can give you something extra to check, and log, and compare to the access logs of your server. It may also give you a clue as to what tools are being used when your page is targeted.
However, you should add checks along the lines of
htmlspecialchars
Is it needed? NO. In fact, they're capable of doing more harm than good in some cases. Particularly when they're applied to the email address, as you seem to be doing. You're using
On the hidden input fields
As Martijn said in his comment: most bots will probably parse the DOM, and filter out those fields that are marked as required (looking for labels with a
* text node in them), and they'll simply ignore hidden fields. You've created regular input fields that are not displayed. That might work on some bots, but like I said, they'll probably parse the DOM and see that they have a style attribute that sets the display to none.It's not hard to deal with that, and if I were to write a bot, it wouldn't take me 5 minutes to add the code to deal with those input fields, too.
You can keep those hidden input fields as a means of security (they don't do any harm, after all), but don't set their style attributes in the markup, use CSS classes, or better still: use JavaScript to set class/attributes on the load event. That way, the DOM doesn't reflect what the page will actually look like as much as it does now.
This may help a little, but all in all, this will only protect you from script-kiddies and amateurish attacks.
The token stuff
That's fine. Session tokens that should be posted back are basic security steps that everybody should take. How you get those tokens is up to you, but an
md5 of the timestamp? A hash doesn't make your token more secure. Don't go thinking that md5 does anything else than add overhead, however minor it may be.Of course I get that a hash string just makes the token look more important, and in a way less random than it actually is, but why not hash some of the clients data in that case, like the remote address or referrer or whatever... though far from reliable, it can give you something extra to check, and log, and compare to the access logs of your server. It may also give you a clue as to what tools are being used when your page is targeted.
However, you should add checks along the lines of
if (isset($_POST['yourlastname'])) and isset($_SESSION['token1']), to ensure that you can actually validate the form submission. But that's as an asside.htmlspecialchars
Is it needed? NO. In fact, they're capable of doing more harm than good in some cases. Particularly when they're applied to the email address, as you seem to be doing. You're using
filter_var($email, FILTER_VALIDATE_EMAIL), which is great, because that filter can handle the complex and wacky email addresses can contain htmlspecial chars, including:
I've just looked into the source of phpcaptcha now. I must say, there's a couple of things I don't much care for in there, but on the whole, it's not bad. I've even gone through the trouble of forking the repo, and I've started writing a little extra feature (which I'll call "mangler"). It'll transform words like transform into tr@nsf0rm, in such a way that both transform and tr@nsf0rm are accepted.
Though still work in progress, feel free to contribute ;-P
When echo-ing PHP variables inside HTML, you may find your code easier to read when using the short echo tag. This is not the same as the short open tag (<?) in that it does not require specific ini settings. In other words, it's always going to be available.
If nothing else, it at least requires less typing/code-chars
">
">
Not even the ;` at the end of the line is required, but I prefer to have it there... it's a good habit.Code Snippets
$email = filter_var($_POST['email'], FILTER_SANITIZE_EMAIL);//sanitize
if (filter_var($email, FILTER_VALIDATE_EMAIL))
//continue$token1 = md5(microtime(true));
$_SESSION['token1'] = $token1;//set token, then:
?>
<!DOCTYPE html>
<html>
<!-- setting HTML... -->
<?php $token2 = md5(microtime(true)); ?>
<form method="post" name="form" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>">
<input name="token" type="hidden" value="<?php echo htmlspecialchars($token2); ?>"><form method="post" name="form"> <!-- will do the trick --><input name="token" type="hidden" value="<?php echo htmlspecialchars($token2); ?>">
<!-- can be written as (I'm applying my critiques, too) -->
<input name="token" type="hidden" value="<?= $token1; ?>">Context
StackExchange Code Review Q#41129, answer score: 14
Revisions (0)
No revisions yet.