I have a contact form on a website that has been receiving a lot of spam. It is hosting on Github so my methods of server side validation / captcha is quite limited. All fields always had the 'required' attribute and I have added some 'pattern' attributes to the form field and a very basic security question.
Originally I would receive spam responses with all fields completed but random numbers where the name should be, a name where the phone number should be, an email, and URLs in the message area.
When I first added just the security question handled by javascript / jquery, it seems to have no effect so I am assuming the bot could read the correct answer from the code?? What is more concerning, is that after more recently adding some 'pattern' attribute to the form fields I have started getting spam responses that still contain random numbers where the name should be, and now the phone and email field is non existent (not submitted / entered).
I do not get how the field can be submitted when it doesnt match the pattern validation, or how two fields can be left blank when they still have the 'required' attribute. I have tested the form myself and all validation and required fields function as expected and all fields are received like they used to be so it is just the spammer that seems to ignore these rules.
If anyone can please explain what may be happening / have happened here?? Also / alternatively if anyone is aware of a better and proven way of weeding out spam responses that works with the form I have and within the constraints of hosting the website on Github that would be GREATLY appreciated!!
The website in question is http://orionimportgroup.com/ if you would like to see the form in the live environment.
var n1 = Math.round(Math.random() * 10 + 1);
var n2 = Math.round(Math.random() * 10 + 1);
$('document').ready(function(){
$("#a").val(n1 + " + " + n2);
document.getElementsByName('captcha')[0].placeholder=("CAPTCHA CODE: " + n1 + "+" + n2);
});
$('form').submit(function(e) {
if (eval($("#captcha").val()) == (parseInt(n1) + parseInt(n2))) {
e.preventDefault();
$.ajax({
url: "https://docs.google.com/a/blakedavies.net/forms/d/e/1FAIpQLSfHdHMJePTJ3R5JOtBrH8zdPdX74eXQ8TDFIGjgkbIbGNdpnQ/formResponse",
data: $(this).serialize(),
type: "POST",
dataType: "xml",
success: function(data) {
console.log('Submission successful');
},
error: function(xhr, status, error) {
console.log('Submission failed: ' + error);
}
});
$('#gform *').fadeOut(0);
$('#contact-box *').fadeOut(0);
$('#gform').prepend(
'<div class="thank-you-box"><p class="thank-you">Hi, thanks for reaching out! We will get back to you within 24 hours.</p><p class="thank-you">If your issue cannot wait, you can also reach us via our Facebook Page or call 0429-105-580.</p></div>'
);
return true;
}
else{
alert('You have not entered the correct captcha code value');
return false;
}
});
<form name="gform" id="gform" enctype="text/plain" action="https://docs.google.com/a/blakedavies.net/forms/d/e/1FAIpQLSfHdHMJePTJ3R5JOtBrH8zdPdX74eXQ8TDFIGjgkbIbGNdpnQ/formResponse">
<div class="inner">
<input name="entry.1683926249" id="entry.1683926249" placeholder="Name" required pattern="[A-Za-z' -]+" oninvalid="setCustomValidity('Please enter a valid name using letters only.')" onchange="try{setCustomValidity('')}catch(e){}" />
<input name="entry.189066148" id="entry.189066148" placeholder="Phone" required pattern="[0-9 -]+" oninvalid="setCustomValidity('Please enter a valid phone number using numbers only.')" onchange="try{setCustomValidity('')}catch(e){}" />
<input name="entry.429019481" id="entry.429019481" placeholder="Email" required pattern="[a-z0-9._%+-]+#[a-z0-9.-]+.[a-z]{2,3}$" oninvalid="setCustomValidity('Please enter a valid email making sure to include an # sign and the domain suffix (.com .net etc.).')" onchange="try{setCustomValidity('')}catch(e){}" />
</div>
<div class="inner">
<textarea name="entry.2094840737" id="entry.2094840737" placeholder="Message" required></textarea>
<input name="captcha" id="captcha" placeholder="CAPTCHA CODE: 5+7" required />
</div>
<input class="submit" name="submit" type="submit" value="Send Message" />
</form>
<script src="js/contactform.js" type="text/javascript"></script>
One way to prevent spam is Honeypot technique, it is proven to work and prevented more than 90% of spam for my company's site.
To implement the Honeypot technique, all that’s required is adding a hidden form field to the form.
And that’s what gives away whether the form submission is spam or not:
Real users don’t see the hidden field so they won’t submit it with any value.
Spam bots, however, will still see the field in the form’s markup, auto-populate it with something, and submit it with the rest of the form.
So from there all that’s needed is to test whether the hidden field was submitted with a value or not. If it was, the submission can be treated as spam.
Read more about Honeypot technique
Response to comments and additional info (I can't comment yet)
#user7531422, try it like this:
Add a class to an additional input element (honeypot element) with CSS style to hide it display: none;, and make it look same as the name or phone field but change name attribute.
most bots will read only the HTML markup and won't notice CSS rules, and most bots aren't so smart to dive into every piece of code.
Before submitting the form directly check if your hidden field has data (Check for it value if not empty), if so don't even send the form.
It's a client side solution.
Related
Is it possible after processing any login Form to prevent the browser from offering the option to remember the password?
I know it's been asked and answered here but none of the answers have worked so far, even one of them suggested using:
autocomplete="off"
But that also didn't worked.
I'm using AngularJS and Jade as templating engine (not sure if relevant or not anyhow), is there any way to do this?
if a site sets autocomplete="off" for a form, and the form includes username and password input fields, then the browser will still offer to remember this login, and if the user agrees, the browser will autofill those fields the next time the user visits this page.
https://developer.mozilla.org/en-US/docs/Web/Security/Securing_your_site/Turning_off_form_autocompletion
You should also set autocomplete="off" on your input as well as your form.
Google Chrome release notes:
The Google Chrome UI for auto-complete request varies, depending on whether autocomplete is set to off on input elements as well as their form. Specifically, when a form has autocomplete set to off and its input element's autocomplete field is not set, then if the user asks for autofill suggestions for the input element, Chrome might display a message saying "autocomplete has been disabled for this form." On the other hand, if both the form and the input element have autocomplete set to off, the browser will not display that message. For this reason, you should set autocomplete to off for each input that has custom auto-completion.
I would suggest using Javascript to create a random number. Pass that random number to your Server Action using a hidden field, then incorporate that random number into the names of the "login" and "password" fields.
E.g. (psuedo code, the exact syntax depends on whether you use PHP, jQuery, pure Javascript, etc.)
<script>
var number = Math.random();
var login_name = 'name_'+number;
var pass_word = 'pass_'+number;
</script>
<input name='number' value="number" type='hidden'>
<input name="login_name" type='text'>
<input name="pass_word" type='password'>
Your server reads the "number" field, then uses that to read "name_"number value and "pass_"number value.
It won't matter whether or not the user saves their password in the browser, since every time the user logs in, the name and password fields will be different.
Since you're using AngularJS, you can leave the field unnamed, and access the data it contains through the model :
Login: <input ng-model="login" type="text" />
Password: <input ng-model="password" type="password" autocomplete="off" />
and in your javascript file :
$scope.doLogin = function() {
var dataObj = {
login: $scope.login,
password: $scope.password
};
var res = $http.post('/login', dataObj);
}
Tested in IE10 and Chrome 54
This post is little bit old now, but sincce I found a solution that works for me (at least with Chrome version 56), I'll share it here.
If you remove name and password attributes on your input, then Chrome won't ask to save the password. Then you just have to add the missing attributes by code just before submitting the form:
<!-- Do not set "id" and "name" attributes -->
Login: <input type="text">
Password: <input type="password">
<!-- Handle submit action -->
<input type="submit" onclick="login(this)">
Then in Javascript:
function login(submitButton) {
var form = submitButton.form;
// fill input names by code before submitting
var inputs = $(form).find('input');
$(inputs[0]).attr('name', 'userName');
$(inputs[1]).attr('name', 'password');
form.submit();
}
I hope this will help. Tested on Chrome 56 only.
The problem I have is that while I understand the 'annoyance' to a user in not being able to have their browser remember their password and I don't want to 'disable' that feature completely, there are times when I want to disable it for just a certain password field. Example for me being a 'reset your password' dialogue box.
I want to force them to have to re-enter their old password and then of course type the new one twice.
It's been my experience that no matter what I name that 'old' password input, it is auto-filled with the 'remembered' password (in Firefox 49.0.1 anyway). Maybe this is where I'm getting this wrong, but it just fills it no matter the fact that this input's name is different from saying the login input field.
The behavior I see is basically that the browser seems to say "This user has remembered a password for this site, so now just fill every input type='password' box with that password no matter the name. It seems to me that this should be based on the name attribute, but for me (on multiple sites I've worked on) this just does not seem to be the case.
My solution:
Color this password field to the same color as the background of your input so the 'password dots' is essentially invisible on page load.
onload, onblur, after a timeout, or however you want to do it, use JQuery or JS to set the value of that password field to nothing (blank), then set the color of the field to whatever it is supposed to be.
$("#old_password").val('').css('color','black);
I've discovered that Firefox 52.0.2 is incredibly determined to remember the autocompletion values. I tried almost everything suggested above, including changing the name attributes to random values. The only thing that is working for me is setting the values to "" with Javascript after the browser has had its way with the form.
My use case is lucky in that I do not have to resort to CSS tricks to prevent a confusing and/or annoying flash of autocompleted form values (as proposed by #MinnesotaSlim above) because my form is hidden until they click a button; then it's displayed via a Bootstrap modal. Hence (with jQuery),
$('#my-button').on("click",function(){
$('#form-login input').val("");
});
// this also works nicely
$('#my-modal').on("show.bs.modal",function(){
$('#form-login input').val("");
})
And I imagine you might be able to get the same effect by having your form initially hidden, and in your document load event, manually override the browser and then display the form.
For me, the only solution that reliably worked was to empty username and password input element just before submitting form combined with replacing submit button for the regular button with onclick handler.
NOTE: We use Microsoft MVC so we needed to populate ViewModel with entered credentials. Therefore we created hidden input elements bound to model and copied credential values to them before emptying visible inputs.
<form>
<input id="UserName" name="UserName" type="hidden" value="">
<input id="Password" name="Password" type="hidden" value="">
</form>
<input id="boxUsr" name="boxUsr" type="text" value="" autocomplete="off">
<input id="boxPsw" name="boxPsw" type="password" autocomplete="off">
<input type="submit" value="Login" onclick="javascript:submitformforlogin()">
function submitformforlogin() {
$("[name='boxPsw'],[name='boxUsr']").attr('readonly','true');
var psw = document.getElementsByName('boxPsw')[0];
var usr = document.getElementsByName('boxUsr')[0];
if (psw.value != "false") {
$('#Password').val(psw.value);
$('#UserName').val(usr.value);
psw.value = "";
usr.value = "";
$("form").submit();
} else
window.alert("Error!");
}
I have a form with a field, and when that element has ng:invalid I am showing another (which is a tooltip) that has an error message.
However, I need to have that tooltip display different messages based on WHY the field isn't valid. For example:
If the user didn't enter ANY value, it should display "Required"
If the user didn't enter a valid email address, it should display "Please enter a vaild email address"
If the user entered an email address that exists (in a local array, say) then it should display a different message
.. and so on.
Since ng:invalid would be set even if one of the rules fail, I need a way to differentiate between the rules and idenify the one that failed, and then set the HTML for the tooltip based on that.
What's the "angular way" to do this?
EDIT: I was able to solve part of this using ng-invalid-required. But the question is still open, for multiple other rules on the same field.
By default AngularJS exposes an $error object that you can use to get more information about the error. See the following example:
<form name="userForm">
<input id="userEmail" name="userEmail" type="email" data-ng-model="userEmail">
<div class="alert alert-errors" data-ng-show="userForm.userEmail.&dirty && userForm.userEmail.&invalid">
<p data-ng-show="userForm.userEmail.$error.required">Email is required.</p>
<p data-ng-show="userForm.userEmail.$error.email">Please enter a valid email address.</p>
<div>
</form>
Angular only covers some scenarios out of the box. To cover your final requirement, you will need to write a custom validation. This should get you headed in the right direction: https://docs.angularjs.org/guide/forms
I have 2 php files "source.php" and "target.php". In the source.php part I have,
<form method="POST" id="form1" action="target.php">
...
<input type="submit" name="submit" value="Submit"/>
</form>
When I click on submit it goes to the "target.php" (even if I have errors in the form), but I want that, only after all form fields are validated it will go to the target page, else it shows some kind of warning message and stays on the same page. Please help! Maybe this is a stupid question for some but I am a beginner. (I know how to do all the field validations and its working fine).
Duplicate of duplicate questions.Please search throughly before you post next time.
Generally javascripts are used for validation.But there are cases when javascripts become inefficient,for example when you need to validate country and its states.Its not practical to send the entire list of countries and states to the client. In such scenarios AJAX is used.By using AJAX the client sends the data to server immediatly after the user enters it.then it fetch only the required data.Its a simultaneous two way communication between client and server.for example if the user enters country name as INDIA,using AJAX states of INDIA are loaded for validation,thus saving bandwidth.
JavaScript and AJAX are not easy to learn,you must research try and correct different codes.Just google "JavaScript form validation"...
This is from w3Schools...
Required Fields
The function below checks if a field has been left empty. If the field is blank, an alert box alerts a message, the function returns false, and the form will not be submitted:
function validateForm()
{
var x=document.forms["myForm"]["fname"].value;
if (x==null || x=="")
{
alert("First name must be filled out");
return false;
}
}
The function above could be called when a form is submitted:
Example
<form name="myForm" action="demo_form.asp" onsubmit="return validateForm()" method="post">
First name: <input type="text" name="fname">
<input type="submit" value="Submit">
</form>
here is more basic examples http://www.w3schools.com/js/js_form_validation.asp
Good Luck
You can use AJAX to validate your form. JavaScript is not recommended for form validation.
A simple tutorial for AJAX Validation is available here
But be aware, even if you are validating your form before submission to target.php, always make sure that you check the data in target.php too. This is because JavaScript can be changed (thanks to the modern DOM interpreters) in the browser. It can be made so that the form is submitted without AJAX verification. So you should check it twice, before and after submission.
Also make sure to escape the data, as user input can never be trusted.
You should also user strip_tags($string) to prevent use from inserting php code.
JavaScript is most likely the easiest way to do this (read the other posts).
However, if you don't want to use JavaScript you could always check if all forms are set using isset() or something similar and then passing on the $_POST variables in the URL and grabbing those using $_GET. Of course make sure there isn't any sensitive information in the URL. In addition: you could always work with global variables.
Another way to do this without JavaScript is submit to a database after several checks (like escaping the strings etc.), perhaps even encrypt, but I don't suggest this since this is the long way around.
I have some strange restrictions on the following problem. (My friends aren't very good with JavaScript, nor do they understand what happens to the information once it's sent, i.e., they don't understand Java nor what happens on the back end. Consequently, any potential solutions I'm cooking up are trying to avoid using too much of either of those two. Finally, since I'm trying to allow all users to view the page completely, I'm not using too much HTML5, which IE isn't supporting fully just yet.)
I'm trying to do the following: I want to have a form that people can fill out. If they don't fill out a required field I want to notify them without redirecting. Can I use HTML tags in the following way
<input type="text" name="EMAIL" id="EMAIL" value="" required="required" /> ?
I can wrap this form with an onSubmit() function that says,
function onSubmit()
{
for (each_required_field)
{
if (cur_val == null || cur_val == '') return();
}
document.submit();
}
I just don't know if this is possible in HTML and JavaScript. (I mostly know Java, but I don't want to redirect the whole page to handle this. Can I grab the value of the variable EMAIL without having to redirect the client?)
You don't need jQuery. One should learn javascript before they learn jQuery.
<input type="text" name="EMAIL" id="email" value="" required="required" /> <div id="email-err"></div>
function onSubmit()
{
for ( node in document.getElementById('myform').childNodes )
{
if (node.value == '')
{
// add an asterisk to error field next to input
document.getElementById( node.id + "-err" ).innerHTML = "*";
return; //note that return is not a function
}
myForm.submit(); // this is just for illustration
}
You may also want to look into server side and client side email validation regular expressions to make sure it is a valid email address.
How can I detect from input boxes any attempt to insert an email address or phone number.
This is the main scenario: we have some inputs where user should only write what they are for, like name or street or features.
How can I detect/verify after the user submits that in all that data he sends there are no: emails/phone numbers. Take in consideration that I also have to eliminate this kind of tries:
email at domain dot com, emails # [spaces] dot [spaces] com and so on.
Are there any plugins, tools out there we can use? Do you have an idea about this? Let's put it to the test.
We are building a web application. (php/javascript mainly)
If you are searching for jQuery validation plugins there are tons of them.
E.g. http://bassistance.de/jquery-plugins/jquery-plugin-validation/ or search Google for "jquery validation plugin"
Also validate your input server-side with php after submit, because Javascript can be disabled in the browser.
There are also many tutorials out there (e.g http://myphpform.com), or search SO.
HTML
<input type="text" id="lname" name="lname" />
<input type="submit" value="Submit" name="submit" onclick="return validate();"/>
in Javascript
function validate()
{
var regex = /^[a-zA-Z_]+$/;
var lname = document.getElementById('lname').value;
if (regex.test(lname)) {
return true;
} else {
return false;
}
}
you can edit regex to suit your criteria
Use a jQuery plugin for validation - then use regex (or some of the already built in functions) to validate the input ...
I use the Position Absolute validator for jQuery