How to prevent spam in contact forms without using CAPTCHA?

Asked

Viewed 7,447 times

22

I am looking for a simple and efficient solution to avoid spam in contact forms. The idea is that the customer does not need to inform that he is a "person" (example CAPTCHA), the form presented should be clean (the customer should see nothing but the form).

Rules:

  • Cannot be used CAPTCHA;
  • The customer should only see the form;

Recommendations:

  • Use only HTML, CSS and JS;
  • Smallest code possible;
  • There may be extra validation from the server, but it would be interesting if there were no.

Form:

<form>
    <label for='name'>Nome:</label><input type='text' id='name' name='name'>
    <label for='email'>E-mail:</label><input type='text' id='email' name='email'>
    <label for='message'>Mensagem:</label><textarea id='message' name='message'></textarea>
    <input type='submit' value='enviar'>
</form>

Note: the main objective is the prevention of spam that are carried out on random websites.

  • You cannot enter the Hidden field?

  • @bfavaretto can, but the server will not check whether this field has been filled or not.

  • 1

    I even spent time writing an answer, but after reading the restrictions I saw that it was impossible. Orion, even captcha should be validated on the server. There is no way to prevent spam on client, otherwise it would be enough to play the HTTP request without using a browser.

  • It is very complicated to have nothing on the server... It is possible to make a bot to catch the action of form, pick up the fields input (text e hidden), generate random text and make a GET. I think if you can’t move the server, why not change the destination of the form to another place you might receive or receive SPAM treatment? And why not a solution third-party? Delegate this responsibility to someone who knows how to treat.

  • @utluiz changed the rules and made some recommendations

  • @bfavaretto edited the question

  • @Wakim edited the question

  • Something with Javascript’s localStorage may be the solution. But it is client dependent. And any modification of the code by the client can end the solution.

  • I would suggest adding the tag [tag:usability], because I understand that not using Captchas in the question has to do with the difficulty imposed on users. I have no time to prepare an answer, but here is the best article I have ever read on the subject: http://www.smashingmagazine.com/2011/03/04/in-search-of-the-perfect-captcha/

  • 4

    Take a look at this question in the EN OS, the first two answers are interesting. First measure the time between the page load and the form’s Ubmit (combined with the construction of the form via javascript, because if the bot does not run javascript, it cannot cause spam). And the second is to create a honeypot, to have a hidden text field that the user doesn’t see, if someone filled it out means that they’re not an ordinary user. Follow the link: http://stackoverflow.com/questions/2387496/how-to-prevent-robots-from-automatically-filling-up-a-form

  • You can use Akismet ( http://akismet.com/ ) or some trap for robots like Spampoison ( http://spampoison.com ). Spampoison at least once seemed to work, I don’t know if today bots are smarter... Take a test!

  • 1

    Orion, I just "desexcluir" my reply from last week with some more information. I hope it helps!

  • It doesn’t make much sense not to check on the server, because spam can be sent STRAIGHT to the server, without using any extra functionality of your form! A spam script can read your form only to get the name of the fields, but do the GET or POST directly.

  • @Bacco the idea is to prevent indirect spam, those performed on random websites. For this purpose the use of Javascript only can solve this problem, for example by setting the address of action after x seconds or when the user performs some action on the page as a click etc..

  • 1

    @Bacco the question is how the bot will find the address of action of form to send messages if the bot has not performed human actions. I think there are several possibilities to prevent a bot from submitting a form, especially when it requires human actions for this form appear or work.

  • 1

    @Orion from your statement you already take part of the solution ;) I already prefer something that does not depend on JS to work, but you can, as mentioned in the action, change the destination of the action via JS after the form loaded.

  • @Bacco the main idea is to discover solutions that I can not see, I have some in mind, but I wanted to know others in the view of the guys :), since it is a contact only form, I look for something simple and functional

  • 1

    If you use MVC . NET there is a unique code for this. @Html.Antiforgerytoken()

Show 13 more comments

5 answers

27


A warning

Not requiring server validation means controlling the user’s browser.

This implies that any solution will be easily circumvented with minimal Javascript knowledge. Another possible attack is simply replicating the HTTP request without actually using a browser. Opera summary: no server validation any solution will be extremely vulnerable.

Solution that does not require server validation

To prevent only more naive attacks, a solution is to use an event on the page that enables the submission of the form if identified that a real user is accessing the page.

The challenge is to identify the pattern of a real user. I imagine a user will either click the button or use the key TAB until we get there, right? Then we could activate the submission only if there is an event mouseover or focus on the button.

In addition, to prevent an automatic script from identifying the action and form fields I would use a solution with Ajax.

See the following example of two fields with one button:

Field 1: <input id="f1"/><br/>
Field 2: <input id="f2"/><br/>
<button type="button">Enviar</button>

And then a script that monitors events mouseover and blur, adding the event click that will make Ajax only when one of the first two events is executed:

//monitora por focus e mouse over
$('button').bind('focus mouseover', function() {

    $(this)
        //eventos não são mais necessários
        .off('mouseover focus') 
        //adiciona o evento que executará a requisição final
        .click(function() {
           console.log('implementar ajax aqui');
        });

});

Demo at Jsfiddle

Anyway, I believe it is possible to help this also for a submit conventional if applicable.

Solutions that require server validation

Here I will record the response I had written using server validation.

There are several solutions for not using captcha, some more professional others based on creativity.

Hidden field for "humans"

One response from the OS gave the idea of creating a hidden field in the form. A "robot" program that sends messages automatically will try to fill this field with some random information. Then your code will know that if the hidden field is filled someone has been messing around with something they shouldn’t.

Example:

<!-- este campo não deverá ser preenchido, mas provavelmente os bots tentarão fazê-lo -->
<input type="text" id="nao_humano" name="nome" />

<!-- este campo é o que realmente o usuário deve preencher -->
<input type="text" name="nome_real" />

<!-- o estilo inibe o campo que o usuário não deve preencher -->
<style>
   #nao_humano { display: none }
</style>

Service with artificial "intelligence"

Some services do the job of identifying spam. For example, in the my blog I use the Akismet.

Akismet works something like this:

  1. User submits a comment in the form
  2. A code on my website receives the message and sends it to the Akismet service
  3. The Akismet service checks the comment against a spam information base
  4. Akismet returns saying if the message is a potential spam or not

Obviously, there is some concern about the safety of this process. In a public blog there are no difficulties, but for a company that receives information from clients the traffic of information to a third party server can be a deterrent.

Detecting human behavior

Another idea I’ve seen around for some time is to detect events on the site to validate whether someone is actually typing the message.

Doing this is relatively simple. First, generate a random code and place it in the user’s session. Print that same code into a Javascript block within the page:

var codigo = 'CODIGO_GERADO';

Then add a hidden and initially empty field to the form:

<input type="hidden" name="validacao"/>

Now create a code at some event like mouse over or key up on the page that fills the field validacao with the value codigo.

Finally, the server should validate the field validacao came with the code. To dribble some spammers smarter, the name of this field can also be random.

Completion

In my opinion, creativity is the one who rules this point. The more different and creative your solution, the more difficult spammers will detect it.

Don’t forget that any customer validation can be easily circumvented by any user who knows how to use the developer tool and has an intermediate knowledge of Javascript.

12

One way is to use a proof of work (Proof-of-work system), such as the Hashcash or the virtual currency mining system Bitcoin (among others). A simple example would be:

  1. Choose an integer number T to be your work factor; if your site faces little spam, that number may be small, if the spam problem increases, increase that number;
  2. Generate a random token on the server a, a timestamp and an expiration date (short), digitally sign and send to the customer (in a cookie) - along with the current work factor;
  3. Enter a Javascript code that will generate random tokens b, seeking to find such a:

    scrypt(a + b) < (2**256 >> T)
    

    In other words, find a b such that the resulting hash has T zeros to the left [in binary]. If you don’t want to mess with binary arithmetic, just see if the hexadecimal hash has T/16 characters 0 to the left.

  4. When sending the form, also send the token b found;

    • Until this token is found, do not send the form, as it will be rejected by the server; show the user a message like "validating..."
  5. Upon receiving the form, check whether the date is valid (i.e. longer than the timestamp, less than the expiration), and whether the parameter b satisfies the above restriction. Otherwise, reject the form.

(Note: I suggested the scrypt because it is harder to manipulate, but you can use another hash function that is lighter for the server.)

If a single human client is filling out a form only once, they will barely notice this extra work in the browser - especially if you put it to run in parallel with the fill job, in a Webworker for example. Already a spammer wanting to submit the form several times would have to repeat that time-consuming calculation once for each submission, in particular if you invalidate the tokens already used (it may weigh a little in the BD*) or if you include form key fields (e.g.: the email and the message**) on the input of the hash function.

At the end of the day, the cost with the processing power*** needed to send spam is greater than the expected profit from this spam. And expensive for the client, but light for the server.

This was a simple example, and certainly the protocol can be improved in some way, but it is the only solution I know that is not likely to be circumvented - because even the methods described in the other answers (check IP, Referrer, use sophisticated algorithms to identify "human behavior", etc.) can be circumvented if your site is of high value to spammers. But the ideal, of course, is to use an "in-depth defense", so that if you can employ these methods as well (simultaneously) the chances of stopping spam increase.


* This may or may not be relevant, depending on whether your website already requests the BD in any way or not. One way to minimize this is to put the token a as a column in the message table, with the restriction UNIQUE - then avoid a spammer reusing the same token in multiple messages, and break you still get a "free" UUID for it. :)

** The disadvantage is that you can’t parallelize, so the user will always see the "validating" message and will have to wait a few more seconds when sending each message. Compared to CAPTCHA, it is a net-win, but from the user’s point of view your site will still seem "slow"...

*** If the spammer is using a botnet to send spam, it will not be the spammer that will pay this cost, then this technique is less effective. On the other hand, this will make the user’s computer slow, which may help you to suspect that it is contaminated by malware.

7

Why not use Captcha?

Well, there are several techniques to send spam, so we would have to treat all (which is impossible, since the techniques are recreated and invented every day).

  • You can use a CSRF TOKEN, that is, a unique hash generated by the server, which will be within the request (POST) to be sent by the user. If this hash does not come as you expected, it is because they are trying to request from outside the browser.

  • You can check the server with the HTTP REFERRER, which comes from the request, and see if the user comes from the URL and the expected domain (your);

  • None of the above solves the possibility of a robot sending forms through the browser repeatedly (here would enter the captcha). What you can do is compare the timestamp of when the page was generated between the timestamp of when the user sends the form. Usually robots quickly fill out the form and send it. You can determine a minimum time when a human fills in the form (15 seconds, depending?) and if it is shorter, you reject it.

  • Robots usually fill all fields found inside a <form>, that is, if you put a <input type="text" style="display: none" name="name2" />, probably the robot will fill in. This field would not appear to the user, so it would be sent empty. If it comes filled, you’ll know it wasn’t a human who filled it.

If your app is spam safe? Certainly not. It wouldn’t even be with captcha, but it would be great to have one. =)

Reference: https://stackoverflow.com/questions/2387496/how-to-prevent-robots-from-automatically-filling-up-a-form

5

Here’s what I’d do:

  1. right away I would take the Source IP of whoever is writing the form and submit to a trusted RBL (Barracuda, Spamcop, etc.) if the IP is contained in any of these places the chance of being SPAM increases considerably, and you can allow the form to be submitted or not.
  2. Another method is to submit the content of the form to some script check and classify the content, analyzing the context written in the form it may or may not be considered spam, you can interact with spamassassim that can classify a text, through learning you can teach the algorithm.
  3. Another method is to create in your form an Origin or From field so that a valid email in this case of who is sending the form is completed, you send this email a confirmation link so that the message only comes out if the guy clicks on the link he will receive by email.

4

There is only one way to prevent spam correctly, and it is by filtering through the backend. Hidden fields and other "creative" ways only serve to prevent old and/or simple bots.

If Voce is so worried about the user not having to type a captcha, the "loss" will have to fall with you, receiving messages and later filtering them with services like Akismet and Mollom.

This is how most major websites deal with spam, the filter if after sending the message.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.