Question

I just implemented a reCaptcha on a WP Site contact form.

It works like this:

  1. Submission is cancelled using $form.submit(function(e) { e.preventDefault(); return false; }
  2. reCaptcha is dynamically inserted before the form.
  3. if reCaptcha's AJAX response is successful, perform HTLMFormElement.submit, using $form[0].submit();

HTML

<div id="ny_cf-3" class="footer-ny widget widget_ny_cf"><h2 class="widgettitle">Contact Us</h2>               

    <!-- contact form widget -->
    <p class="response"></p>
    <form method="post" enctype="multipart/form-data" class="ny-footer-contact-form" action="http://wpstage.leadscon.com/leadsconny/" data-submit="return fm_submit_onclick(1)" id="fm-form-1" name="fm-form-1">

        <div class="form-group" id="fm-item-text-53546749dea0d">
            <input type="text" name="text-53546749dea0d" id="text-53546749dea0d" style="width:px;" placeholder="Your name" class="form-control">
        </div>
        <div class="form-group" id="fm-item-text-5354674e4b90b">
            <input type="text" name="text-5354674e4b90b" id="text-5354674e4b90b" style="width:px;" placeholder="Email address" class="form-control">
        </div>
        <div class="form-group" id="fm-item-textarea-5354675009293">
            <textarea name="textarea-5354675009293" id="textarea-5354675009293" style="width:px;height:100px;" placeholder="Your message" class="form-control"></textarea>
        </div>
        <input type="email" class="teddybear" style="display:none">

        <button type="submit" id="fm_form_submit" name="fm_form_submit" class="btn btn-primary btn-block submit">Submit</button>
        <input type="hidden" name="fm_nonce" id="fm_nonce" value="1165f15ac2">
        <input type="hidden" name="fm_id" id="fm_id" value="1">
        <input type="hidden" name="fm_uniq_id" id="fm_uniq_id" value="fm-536b89c742833">
        <input type="hidden" name="fm_parent_post_id" id="fm_parent_post_id" value="4">
    </form>
    <!-- end cf widget -->
</div>

JavaScript code:

var getRecaptcha = function($form, $frmResponseField) {

    $form.fadeOut();

    // Add the reCaptcha
    // ========================================================================
    var $recaptchaForm = $('<form class="recaptcha_form" style="display:none;"><p><strong>Spam verification (sorry):</strong></p><p class="response"></p><button class="btn btn-success btn-sm" type="submit">Submit</button></form>');
    var recaptcha_el = $('<div id="recaptcha_el"></div>').insertAfter($recaptchaForm.find('.response')).get(0);

    $recaptchaForm.insertBefore($form).slideDown();

    leadsCon.reCaptchaHTML().appendTo($(recaptcha_el));

    Recaptcha.create('6LdUZPASAAAAAGZI_z-qQ7988o0nGouHHtIsh4yX', recaptcha_el, {
        theme : 'custom',
        custom_theme_widget: 'recaptcha_widget',
        callback: Recaptcha.focus_response_field
    });

    // Bind submit action to check it
    $recaptchaForm.submit(function(e) {
        e.preventDefault();

        var challenge = Recaptcha.get_challenge();
        var response = Recaptcha.get_response();

        var $btn = $recaptchaForm.find('button[type="submit"]')
        var btnVal = $btn.html();
        var $responseField = $recaptchaForm.find('.response');

        var data = {
            action: 'verify_recaptcha',
            challenge: challenge,
            response: response
        };

        $btn.html("<i class='dashicons dashicons-clock'></i>");
        $responseField.text('');
        $.post(ajax_object.ajax_url, data, function(response) {

            if ( response.success == true ) {
                $responseField.removeClass('text-danger').addClass('text-success').html('<i class="icon-ok"></i>  You got it. One second...');

                // We're ok.. send.
                Recaptcha.destroy();
                $recaptchaForm.remove();

                $frmResponseField.removeClass('text-danger').addClass('text-success').html('<i class="icon-ok"></i>  Wait while we send your message.');

                $form[0].submit();

            } else {
                $responseField.removeClass('text-success').addClass('text-danger').html('<i class="dashicons dashicons-dismiss"></i>  Oops! Try again.');
                $btn.html(btnVal);

            }
        });

    });
};
$('.ny-footer-contact-form').submit(function (e) {
    e.preventDefault();

    var $form = $(this);
    var $responseField = $form.siblings('.response').removeClass('text-success text-danger').html('');

    var command = $form.attr('data-submit').match(/return (\w+)\((.+)\)/i);
    var fn = window[command[1]];

    var $honeypot = $form.find('input.teddybear');

    if ( fn(command[2]) && $honeypot.val() == '' ) {
        getRecaptcha($form, $responseField);

    } else {
        $responseField.removeClass('text-success').addClass('text-danger').html('<i class="dashicons dashicons-dismiss"></i>  There are missing fields.');
    }

    return false;
});

My impression is that since $form[0].submit() is not in any way filtered and doesn't trigger the submit event from jQuery, spammers are using that to submit the form and circunvent the reCaptcha.

What can I do?

Was it helpful?

Solution

A spammer will not execute your javascript code. They will simply post to the correct URL. Therefore you can't reliably validate anything on the client, you'll have to validate it on the server as well.

OTHER TIPS

Bots can even does not run your JS - they just find forms in raw html and try to act as an user submitting the form. You have to validate reCaptcha value on server side, see here: https://developers.google.com/recaptcha/docs/php

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top