Is there a good method of form security that does not involve CAPTCHA? CAPTCHA is so annoying, but I need security because I am getting form spam. My form is PHP.
Here's what I've found to be very effective (and dead simple):
Put a hidden field on your form. Give it a name like "phone" or something similar/common and put in a default junk value.
Put another regular text input field on your form, but hide it with CSS. Make that one empty. Again, give it a "real" sounding name (first_name, phone_number, whatever).
When the form is posted, verify that the hidden field still has the default value and the field you hid with CSS is still empty.
You're basicly taking advantage of the fact that most spam bots will simply fill in every field in the form in order to avoid failing any required field validation checks. Some might be smart enough to ignore hidden fields, but I've never seen one that was smart enough to ignore fields hidden with CSS.
ETA:
To address some comments - Is this a truly "secure" system? no, it certainly isn't. It would be trivially broken by anybody who wanted to specifically target your site. That said, it is still remarkably effective against the automated form spamming bots that most "low value" sites will see.
If you want to stop a determined attacker, you'll need something a bit more invasive. Another poster mentioned Akismet, which is a good option. Re-Captcha would be another. Stopping determined, targeted spammers is hard though. Even Yahoo and Google have a hard time with it.
Try akismet. It's great at flagging spam. The API is easy to use and completely transparent to your users.
This kind of validator is cute and quick!
Obviously, you will want to display one of a many possible animal images, and the list should be randomized as well.
I understand it will only work X% of the time, but adding more options to the list will help reduce spam.
I have already worked something similar.
When you open a form generate one md5() string and put it in session (for example $_SESSION['captha'])
Your form sould have one hidden field and when you open this form write this data from $_SESSION['captha'] into this hidden field
When you receive this post request compare value in session and value which come with this hidden field. If it is same everithing is ok and vice versa. Of course, after you handle this request just delete variable $_SESSION['captha'].
This work for me.
If all you are doing is avoiding spam bots (automated programs that seek <form> tags, fill in all <input> fields, then submit the form), then a simple solution is to do as Paolo said: use JavaScript to add a hidden field. The disadvantage is for people who disable JavaScript.
Feel free to use this:
<form method="post" action="contact.php" id="commentForm">
<label for="name">Name</label>
<input type="text" name="name" id="name" maxlength="64" /><br />
<label for="email">Email</label>
<input type="text" name="email" id="email" maxlength="320" /><br />
<label for="message">Message</label>
<textarea name="message" rows="10" cols="40" id="Message"></textarea><br />
<label for="human">40 + 2 =</label>
<input type="text" name="human" id="human" size="10" maxlength="3" /><br />
<p align="center">
<input type="submit" name="submit" value="Send" class="submit-button" />
</p>
</form>
Then place the following as "contact.php" in the same directory:
<?php
require_once 'lib/swift_required.php';
// Reason for not contacting.
//
$reason = 'default';
error_reporting( 0 );
ini_set( 'display_errors', 0 );
function not_contacted() {
global $reason;
header( 'Location: error.html' );
}
function wms_error_handler($errno, $errstr, $errfile, $errline) {
not_contacted();
return true;
}
function wms_shutdown() {
if( is_null( $e = error_get_last() ) === false ) {
not_contacted();
}
}
set_error_handler( "wms_error_handler" );
register_shutdown_function( 'wms_shutdown' );
$name = trim( $_POST["name"] );
$email = trim( $_POST["email"] );
$message = trim( $_POST["message"] );
$human = trim( $_POST["human"] );
$subject = 'FormSpam';
$contacted = false;
if( is_null( $name ) || empty( $name ) ) {
$reason = 'name';
$human = false;
}
else if( is_null( $email ) || empty( $email ) ) {
$reason = 'email';
$human = false;
}
else if( is_null( $message ) || empty( $message ) ) {
$reason = 'message';
$human = false;
}
else if( is_null( $human ) || empty( $human ) || $human !== '42' ) {
$reason = 'computer';
$human = false;
}
if( $human === '42' ) {
$subject = 'YourCustomSubject - '.$name;
$transport = Swift_SmtpTransport::newInstance( 'localhost', 25 );
$mailer = Swift_Mailer::newInstance( $transport );
$message = stripslashes( $message );
$message = Swift_Message::newInstance()
->setSubject( $subject )
->setFrom( array( $email => $name ) )
->setTo( array( 'YourEmailAddress' => 'Your Name' ) )
->setPriority( 1 )
->setBody( $message )
;
if( $mailer->send( $message ) ) {
header( 'Location: contacted.html' );
$contacted = true;
}
}
if( $contacted === false ) {
not_contacted();
}
?>
Should prevent 99% of spam.
I have not added constants, but I'm sure you can figure out where to change the script. I've removed the part where it redirects to different pages depending on what was (or was not) entered by the user (e.g., missing full name, e-mail address, message, and such). If you want a full version of the script, let me know and I'll fix the code to be more new-developer-friendly.
Note the Swift Mailer dependency.
Yes, I invented and developed a method many years ago called nocaptcha.
I tested employed it in my sites for a year then noticed google also using it.
I released it for Joomla (see
http://shop.ekerner.com/index.php/shop/joomla-nocaptcha-detail )
and since it has been copied by many platforms (see https://www.google.com.au/search?q=nocaptcha ).
I believe the git hosted version via the above link can be deployed to any site, and if you cant find a version for your site then perhaps ask my dev team for a custom solution (see: http://www.ekerner.com/ ).
Math questions are interesting alternative. You can even write your own simple math checker by using random numbers.
Here are couple of plugins:
http://www.codegravity.com/projects/mathguard
http://sw-guide.de/wordpress/plugins/math-comment-spam-protection/
Depends on the type of form spam, general bots made for spamming any form it finds can easily be foiled by a lot less obstructive measures (like "what is the name of this site?"), but if someone has made a bot targeting your site specifically you will need captchas or something equally annoying.
If cutting down spam is the immediate need, putting the form in an iframe has been effective for me.
<iframe src="contactform.php" scrolling="no" height="*" width="*"></iframe>
Set the frame's height and width a little bigger than your form's width and height. Use CSS to make the frame border 0 so users won't notice they're looking at the form within frame.
Related
I have this HTML
<input type="text" name="message"/>
With this PHP
$message = 'Blank message';
if ( isset( $post['message'] ) )
$message = sanitize_text_field( $post['message'] );
$Message is always "Blank message"
I cannot see how this is wrong. After attempting to get the input value, I have no other code so I know the rest of it is working, but I am unable to obtain the value.
sup, you gotta change the way you're calling the array, it is $_POST, and not $post
Look to the method of your form. Are you using the GET method than you use $_GET['variable'] is it the POST method than you use $_POST['variable'].
I have a simple PHP form that I'd like to improve validation to help fight empty form submissions from bots.
I have the following array that houses input names from another page.
$expected = array('Project-Inquiry','Name','Company-Name','Phone-Number','Email');
I'd like to verify that these elements, in fact, do contain content, as they're already verified with JS on the previous page. JS is only good when it's enabled, so I'd like to add an extra layer of validation here for when it's disabled.
I tried the following:
$expected = array_filter($expected);
if (!empty($expected)) {
// Do Something
}
And I have also tried the following:
$error = false;
foreach($expected as $field) {
if (empty($_POST[$field])) {
$error = true;
}
}
if ($error) {
// Do Something
}
I seem to be falling short. Any suggestions?
If you want to fight against bots
Create a hidden input that human doesn't see and bots will fill it. You need to check that input before doing anything. If that input filled, it means that form sent by bot not human.
Create a session with current time when you are showing form, when post happening check the time difference. if it is less than 3 sec it's a bot.
use captcha system.
If you want to validate inputs
Don't do validation like what you did on your question. You should try to validate each one of them with proper validation method. for example how you should validate email is completely different from name.
for example do this for email:
$email = (isset($_POST['email']) && is_string($_POST['email']))? trim($_POST['email']) : '';
$email_error = (filter_var($email,FILTER_VALIDATE_EMAIL))? true : false;
for name is different:
$name = (isset($_POST['name']) && is_string($_POST['name']))? trim($_POST['name']) : '';
$name_error = (strlen($name)>20 || strlen($name)<3)? true : false;
You can add more filter to my examples.
Have you considered about using a library to validate?
I recommend you to use https://laravel.com/docs/5.5/validation, so you can validate more complex rules also, and it is very clear.
Let your expected data be array be
$expected = ['name', 'email', 'mobile'];
let form post values be $_POST
foreach($_POST as $key => $value) {
if (empty($value) && in_array($key, $expected)) {
if ($value=='') {
echo $key. ' is should not be empty'."<br/>";
}
}
}
you can get result as expected
HTML FORM
<form action="" method="post">
Name <input type="text" name="name"><br>
email <input type="text" name="email"><br>
mobile<input type="text" name="mobile">
<input type="submit" value="Submit">
</form>
1st issue
I have more the one thousand emails and I am entering manually in the input type text field. I mean just copy from excel sheet and paste in the text field.
Just want to know,
1) Can I add more than one thousand email in the single input text? If yes then how many emails I can add?
2nd Issue
There are thousands of email in the field and I have to send that email from one page to another page without using session.
Page1.php
<form action="process.php?key=addemail" method="post">
<input type="text" name="emailtemplate[]" placeholder="Enter email name" class="form-control">
<input type="text" name="subject" placeholder="Subject" class="form-control">
<textarea name="mailbody" id="editor1" class="form-control"></textarea>
<input type="submit" name="addmail" value="Add mail" class="v-btn v-btn-primary">
</form>
Page2
function addemail($conn)
{
$to=$_POST['emailtemplate'];
$subject =$_POST['subject'];
$mailbody=$_POST['mailbody'];
sendMail($to, $subject, $mailbody );
}
I am trying to cheeck echo $to but i am getting error
Notice: Array to string conversion on line 173
Array
Would you help me in this?
Your addemail function could look something like this in order for things to work:
function addemail( $conn ){
$subject = filter_input( INPUT_POST, 'subject', FILTER_SANITIZE_STRING );
$mailbody = filter_input( INPUT_POST, 'mailbody', FILTER_SANITIZE_STRING );
foreach( $_POST['emailtemplate'] as $t ){
$recipient = filter_var( $t, FILTER_SANITIZE_EMAIL );
sendMail( $recipient, $subject, $mailbody );
}
}
Note that this is untested. I don't see the parameter $conn used for instance... But $_POST['emailtemplate'] is an array, you need to iterate through that. I also filtered your input from the form like you always should. That way you're a lot safer from any code injections...
I am new to PHP so sorry if my question seems a bit noobish. I am creating a contact form which is working great but I need to validate two fields; the phone number and the email address, I need it to check that the phone number field has only numbers and is 11 digits long. The email field needs to be "something"#"something"."something".
If possible I would prefer to do it using only html or php (whichever is easiest), I guess that if there is a way to put the validation into the field properties, that would be the easiest way? eg: in here:
<input type="text" name="email" id="email" class="text" form="contact_form" required/>
If that is not possible then maybe in my PHP file which looks like so:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Submitting...</title>
</head>
<body>
<?php
$Name = $_POST ['full_name'];
$Email = $_POST['email'];
$Number = $_POST['phone_number'];
$Company = $_POST['company_name'];
$Message = $_POST['message'];
$formcontent="Name: $Name
\n Email: $Email
\n Number: $Number
\n Company: $Company
\n Message: $Message";
$recipient = "info#vicarage-support.com";
$subject = "Contact";
$mailheader = "From: $Email \r\n";
ini_set("sendmail_from","info#vicarage-support.com");
mail($recipient, $subject, $formcontent, $mailheader) or die("Please try again.");
echo("Form Submitted.");
?>
<script type="text/JavaScript">
<!--
setTimeout("location.href = 'http://www.vicarage-support.com/contact_us.html';",3000);
-->
</script>
</body>
</html>
Thank you in advance.
There are two ways to check form data before submission, i.e. client-side: using JavaScript, and using new (HTML5) HTML attributes for the input element. They can be used together if desired. Neither of them guarantees valid data; client-side checking should be regarded as convenience to the user, not as a way of ensuring data validity (which you need to check server-side, in this case in PHP code).
The HTML way can be exemplified this way:
<input type="email" name="email" id="email" class="text" form="contact_form"
required>
<input type="tel" name="tel" id="tel" class="text" form="contact_form"
required pattern="\d{11}" label="11 digits">
Using type="email" means that conforming browsers will check the email address format. This is a nontrivial task. Using type="tel" does not impose format restrictions (and the format varies by country and authority), but it may make browsers use a better user interface (such as a numeric keypad in touchscreen devices). The restriction is imposed by the pattern attribute. The value \d{11} means exactly 11 digits. (This is bad usability. I think you should allow spaces, and possibly parentheses and other characters as well, and strip them on the server. It is just too difficult to input an 11-digit number without any grouping. And 11 digits sounds arbitrary.)
There are several approaches to implementing the same in JavaScript. The pattern check is simple, whereas email format checks are very tough, and there are different library routines for it. In general, the check should be fairly permissive, basically just checking that there is an “#” character.
If you want to validate this form before it is submitted, that will have to be done with javascript. However, you should still check in your server side code, as javascript could be disabled, which would render javascript validation useless.
I've used this in the past, worked well for my needs.
http://validval.frebsite.nl/
Try adding three variables. First add a $pattern variable, then add two variables and use the switch function.
Sort of like...
<?php
$what = what you are checking (phone, email, etc)
$data = the string you want to check
function isValid( $what, $data ) {
switch( $what ) {
case 'Number':
$pattern = "/^([1]-)?[0-9]{3}-[0-9]{3}-[0-9]{4}$/i";
break;
//Change to a valid pattern, or configure it the way you want.
case 'Email':
$pattern = "/^[_a-z0-9-]+(.[_a-z0-9-]+)*#[a-z0-9-]+(.[a-z0-9-]+)*(.[a-z]{2,3})$/i";
break;
default:
return false;
break;
This shows you what you want. Now try to validate it like...
}
return preg_match($pattern, $data) ? true : false;
}
$errors = array();
if( isset($_POST['btn_submit']) ) {
if( !isValid( 'phone', $_POST['Number'] ) ) {
$errors[] = 'Please enter a valid phone number';
}
if( !isValid( 'email', $_POST['Email'] ) ) {
$errors[] = 'Please enter a valid email address';
}
}
if( !empty($errors) ) {
foreach( $errors as $e ) echo "$e <br />";
}
?>
As you can see, this will validate your form. You may have to configure it so the $pattern is set ti what you want it to be. This may not be the best way to do so, and I reccomend Javascript, but this is how you could do it with PHP and HTML.
I'm trying to work out how to go about checking a text area to see if it contains a certain phrase.
I believe I could maybe use .indexOf?
It's just I have a validation script to check the contents of a contact form. Lately I have been receiving a fair bit of spam through. I have noticed that all these spam messages contain the phrase [url= and I thought, if I could perhaps add a small script to check if the text area contained such a phrase and, if so, stop the message being sent.
At present I have this simple snippet of javascript to check whether the text area is blank:
if (message.val()=='') {
message.addClass('highlight');
message.focus();
return false;
} else message.removeClass('highlight');
Any good ways to add something to check if the message field contains [url=
I also have a similar php validation script:
if (!$message) $errors[count($errors)] = 'Please click back and enter your message.';
Any ideas how I could add a similar validation script to check if message contains [url= in php too?
Any help would be greatly appreciated! :o)
It's unlikely that you'll stop spam by checking the contents of your textarea at the client side:- the spammer is more than likely POSTing directly to your server side script, so you'll need to do your filtering there. Also checking for a particular pattern will only work until the pattern changes and then you'll have to update your script.
A common solution to this problem is the use of a One-Time Form Token.
When you serve the form you generate a random string of characters and place that token in a hidden field in the form. You also store the token on the server in a session or in a database. When the form is submitted you match the stored and submitted tokens. This way you can be more sure that the form itself was filled in and submitted and that you aren't receiving data from a bot.
For extra security you can only allow each token to be used once only, guarding against multiple submissions.
UPDATE
A very simple, one page example
<?php
session_start();
/**
* Process the form if we have a token that we recognise
* otherwise just present the form again, you probably want to handle this a bit better
*/
if( isset( $_POST['token'] ) && isset( $_SESSION['token'] )
&& $_POST['token'] === $_SESSION['token'] ) {
// no more submissions using this token
unset( $_SESSION['token'] );
$name = clean( $_POST['name'] );
$comment = clean( $_POST['comment'] );
// process the input and redirect to a confirmation
// just echoing data for example
echo "$name said $comment";
die();
} else {
$token = uniqid();
$_SESSION['token'] = $token;
}
/**
* Stub function that cleans user input
* #param String $str
*/
function clean( $str ) {
return $str;
}
?>
<html>
<head>
<title>Form token example</title>
</head>
<body>
<form method="post">
<label>
Name<br/>
<input type="text" name="name"/>
</label>
<br/>
<label>
Comment<br/>
<textarea name="comment"></textarea>
</label>
<br/>
<label>
<input type="submit"/>
</label>
<br/>
<br/>
The token field would normally be hidden, it's displayed here so that the user can change it for testing<br/>
<input type="text" name="token" value="<?php echo $token ?>"/><br/>
</form>
</body>
</html>
check out the javascript search method and javascript match method. I prefer search becuase if you only care if it does exist then you do something like this.
var stringToSearch = "stackoverflow";
if (stringToSearch.search("over") >= 0){
//exists
}
By the way your question didn't do something right. I don't know php so i can't help you there
message.val().match('your phrase here')