Wordpress

No Captcha reCaptchaを使ったWordPressへのボット攻撃の防止

ReCaptcha は、画像にテキストを表示し、ユーザがそのテキストを入力することでフォームを送信する仕組みです。ボットが画像上のテキストを読み取ることは困難でしたが、ボットのアルゴリズムがより高度になるにつれ、このセキュリティを破るようになりました。もはや安全ではありませんでした。この古い方法は、ユーザーの利便性という点ではかなり悪いものです。そこでGoogleは、No Captcha reCaptchaという新しいreCaptchaを作りました。

このチュートリアルでは、No Captcha reCaptchaとは何か、また、WordPressのログイン、登録、コメントのフォームにreCaptchaを統合し、様々なタイプの攻撃を防ぐプラグインの作り方を紹介します。

No Captcha reCaptchaの紹介

No Captcha reCaptchaは、ユーザーがボットではない場合にチェックを入れるようにチェックボックスを表示するだけです。一見、ハッキングしやすそうに見えますが、内部ではGoogleが高度なアルゴリズムと手法を用いて、ユーザーがボットであるかどうかを判断しています。この新しいモデルは、従来のモデルよりもユーザーフレンドリーで安全です。

どのように機能するのか?

単なるチェックボックスのように見えるかもしれませんが、これはチェックボックスではありません。それは、チェックボックスのように動作するグラフィックです。ほとんどのボットはJavaScriptを実行しないので、エミュレートできません。しかし、エミュレートできるボットの場合は、マウスの動きとGoogleのアドセンス不正クリック検出アルゴリズムによって追跡されます。

No Captcha reCaptchaアプリの登録

このプラグインをインストールしたユーザーは、サイトキーとシークレットキーを取得するために、自分のウェブサイトを登録する必要があります。

WordPressの管理者がreCaptchaの管理画面から取得したサイトキーとシークレットキーをインストールできるように、プラグインの設定ページを作成する必要があります。

function 
no_captcha_recaptcha_menu()
{
    add_menu_page( "reCapatcha Options", "reCaptcha Options", "manage_options", "recaptcha-options", "recaptcha_options_page", "", 100 );
}

function recaptcha_options_page()
{
    ?>
        <div class="wrap">
        <h1>reCaptcha Options</h1>
        <form method="post" action="options.php">
            <?php
                settings_fields( "header_section" );
                do_settings_sections( "recaptcha-options" );
                submit_button();                     
            ?>          
        </form>
    </div>
    <?php
}

add_action( "admin_menu", "no_captcha_recaptcha_menu" );

function display_recaptcha_options()
{
    add_settings_section( "header_section", "Keys", "display_recaptcha_content", "recaptcha-options" );

    add_settings_field( "captcha_site_key", __("Site Key"), "display_captcha_site_key_element", "recaptcha-options", "header_section" );
    add_settings_field( "captcha_secret_key", __("Secret Key"), "display_captcha_secret_key_element", "recaptcha-options", "header_section" );

    register_setting( "header_section", "captcha_site_key" );
    register_setting( "header_section", "captcha_secret_key" );
}

function display_recaptcha_content()
{
    echo __( '<p>You need to <a href="https://www.google.com/recaptcha/admin" rel="external">register you domain</a> and get keys to make this plugin work.</p>' );
    echo __( "Enter the key details below" );
}
function display_captcha_site_key_element()
{
    ?>
        <input type="text" name="captcha_site_key" id="captcha_site_key" value="<?php echo get_option('captcha_site_key'); ?>" />
    <?php
}
function display_captcha_secret_key_element()
{
    ?>
        <input type="text" name="captcha_secret_key" id="captcha_secret_key" value="<?php echo get_option('captcha_secret_key'); ?>" />
    <?php
}

add_action( "admin_init", "display_recaptcha_options" );

上記のコードがどのように機能するか見てみましょう。

  • WordPressの管理画面に設定ページを作成しました。
  • この設定ページには、サイトキーとシークレットキーの2つの入力テキストフィールドが表示されます。
  • これらのキーはWordPressのオプションとして保存されています。オプションには site_key と secret_key という名前をつけました。

スパムコメントの防止

フロントエンドのコメントフォームにreCaptchaを統合して、ボットがスパムコメントを入れないようにする必要があります。

プラグインディレクトリにstyle.cssファイルを作成し、以下のコードを配置してください。

#submit { display: none; }

上記のコードは、WordPressのコメントフォームの送信ボタンを非表示にし、送信ボタンとreCaptchaボックスの両方を手動で挿入することで、送信ボタンの上にreCaptchaボックスを配置することができます。

以下はコメントフォームに reCaptcha を組み込むためのコードです。

add_action( "wp_enqueue_scripts", "frontend_recaptcha_script" );

function frontend_recaptcha_script()
{
    if( get_option( 'captcha_site_key' ) && get_option( 'captcha_secret_key' ) )
    {
        wp_register_script( "recaptcha", "https://www.google.com/recaptcha/api.js" );
        wp_enqueue_script( "recaptcha" );

        $plugin_url = plugin_dir_url( __FILE__ );

        wp_enqueue_style( "no-captcha-recaptcha", $plugin_url . "style.css" );
    }   
}

add_action( "comment_form", "display_comment_recaptcha" );

function display_comment_recaptcha()
{
    if( get_option( 'captcha_site_key' ) && get_option( 'captcha_secret_key' ) )
    {
        ?>
            <div class="g-recaptcha" data-sitekey="<?php echo get_option( 'captcha_site_key' ); ?>"></div>
            <input name="submit" type="submit" value="Submit Comment">
        <?php   
    }

}

add_filter( "preprocess_comment", "verify_comment_captcha" );

function verify_comment_captcha( $commentdata )
{
    if( isset( $_POST['g-recaptcha-response'] ) )
    {
        $recaptcha_secret = get_option( 'captcha_secret_key' );
        $response = file_get_contents( "https://www.google.com/recaptcha/api/siteverify?secret=" . $recaptcha_secret . "&response=" .$_POST['g-recaptcha-response'] );
        $response = json_decode( $response, true );
        if( true == $response["success"] )
        {
            return $commentdata;
        }
        else
        {
            echo __( "Bots are not allowed to submit comments." );
            return null;
        }
    }
    else
    {
        if( get_option( 'captcha_site_key' ) && get_option( 'captcha_secret_key' ) )
        {
            echo __( "Bots are not allowed to submit comments. If you are not a bot then please enable JavaScript in browser." );
            return null;    
        }   
        else
        {
            return $commentdata;
        }
    }
}

上記のコードがどのように機能するか見てみましょう。

  • Google reCaptcha の JavaScript ファイルを wp_enqueue_scripts アクションを使って WordPress のフロントエンドにエンキューしました。
  • また、wp_enqueue_style を使って style.css ファイルをエンキューしました。
  • コメントフォームでは comment_form アクションを使ってチェックボックスを表示しています。
  • コメントが投稿され、データベースに挿入される前に、WordPress は preprocess_comment フィルターを呼び出します。このフィルターでは、ユーザーが人間かボットかをチェックします。人間の場合は挿入されるべきコメントを返し、そうでない場合はコメントがデータベースに追加されるのを防ぐために null を返します。

ブルートフォースログイン攻撃の防止

ボットがパスワードを解読するためにブルートフォース攻撃を行うのを防ぐために、管理者ログインフォームにreCaptchaを統合する必要があります。以下は、管理者ログインフォームにreCaptchaを統合するためのコードです。

add_action( "login_enqueue_scripts", "login_recaptcha_script" );

function login_recaptcha_script()
{
    if( get_option( 'captcha_site_key' ) && get_option( 'captcha_secret_key' ) )
    {
        wp_register_script( "recaptcha_login", "https://www.google.com/recaptcha/api.js" );
        wp_enqueue_script( "recaptcha_login" );
    }
}

add_action( "login_form", "display_login_captcha" );

function display_login_captcha()
{
    if( get_option( 'captcha_site_key' ) && get_option( 'captcha_secret_key' ) )
    {
        ?>
            <div class="g-recaptcha" data-sitekey="<?php echo get_option('captcha_site_key' ); ?>"></div>
        <?php
    }   
}

add_filter( "wp_authenticate_user", "verify_login_captcha", 10, 2 );

function verify_login_captcha( $user, $password )
{
    if( isset( $_POST['g-recaptcha-response'] ) )
    {
        $recaptcha_secret = get_option( 'captcha_secret_key' );
        $response = file_get_contents( "https://www.google.com/recaptcha/api/siteverify?secret=" . $recaptcha_secret . "&response=" . $_POST['g-recaptcha-response'] );
        $response = json_decode( $response, true );
        if( true == $response["success"] )
        {
            return $user;
        }
        else
        {
            return new WP_Error( "Captcha Invalid", __( "<strong>ERROR</strong>: You are a bot" ) );
        } 
    }
    else
    {
        if( get_option( 'captcha_site_key' ) && get_option( 'captcha_secret_key' ) )
        {
            return new WP_Error( "Captcha Invalid", __( "<strong>ERROR</strong>: You are a bot. If not then enable JavaScript" ) );
        }
        else
        {
            return $user;
        }
    }   
}

上記のコードがどのように機能するか見てみましょう。

  • login_enqueue_scriptsアクションを使って、GoogleのreCaptcha JavaScriptファイルをWordPress管理画面のログイン、登録、パスワード紛失ページにエンキューしました。
  • login_formアクションを使用して、チェックボックスを表示しました。
  • 最終的な認証結果を出す前に、WordPressはwp_authenticate_userフィルターを実行して、追加の検証ステップを追加します。このフィルターでは、ユーザーがボットか人間かをチェックします。人間の場合はユーザーオブジェクトを、そうでない場合は WordPress のエラーオブジェクトを返します。

偽装アカウントの作成を防ぐ

ボットが偽のアカウントを作成するのを防ぐために、管理者登録フォームにreCaptchaを統合する必要があります。以下は、管理者登録フォームにreCaptchaを組み込むためのコードです。

add_action( "register_form", "display_register_captcha" );

function display_register_captcha()
{
    if( get_option( 'captcha_site_key' ) && get_option( 'captcha_secret_key' ) )
    {
        ?>
            <div class="g-recaptcha" data-sitekey="<?php echo get_option( 'captcha_site_key' ); ?>"></div>
        <?php   
    }       
}

add_filter( "registration_errors", "verify_registration_captcha", 10, 3 );

function verify_registration_captcha( $errors, $sanitized_user_login, $user_email )
{
    if( isset( $_POST['g-recaptcha-response'] ) )
    {
        $recaptcha_secret = get_option( 'captcha_secret_key' );
        $response = file_get_contents( "https://www.google.com/recaptcha/api/siteverify?secret=" . $recaptcha_secret . "&response=" . $_POST['g-recaptcha-response'] );
        $response = json_decode( $response, true );
        if( true == $response["success"] )
        {
            return $errors;
        }
        else
        {
            $errors->add( "Captcha Invalid", __( "<strong>ERROR</strong>: You are a bot" ) );
        }
    }
    else
    {   
        if( get_option( 'captcha_site_key' ) && get_option( 'captcha_secret_key' ) )
        {
            $errors->add( "Captcha Invalid", __( "<strong>ERROR</strong>: You are a bot. If not then enable JavaScript" ) );
        }
        else
        {
            return $errors;
        }

    }   

    return $errors;
}

上記のコードがどのように機能するか見てみましょう。

  • register_formアクションを使ってチェックボックスを表示しました。
  • 最終的な認証結果を出す前に、WordPress は registration_errors フィルタを実行して、追加の検証ステップを追加できるようにしています。このフィルターでは、ユーザーがボットか人間かをチェックします。人間の場合は空のエラーオブジェクトを返し、そうでない場合はエラーオブジェクトに追加を加えて返します。

ボットによるパスワード紛失フォームの送信を防止する

ボットがこのフォームを送信するのを防ぐために、admin lost password formにreCaptchaを統合する必要があります。以下は admin lost password フォームに reCaptcha を統合するためのコードです。

add_action( "lostpassword_form", "display_login_captcha" );
add_action( "lostpassword_post", "verify_lostpassword_captcha" );

function verify_lostpassword_captcha()
{
    if( isset( $_POST['g-recaptcha-response'] ) )
    {
        $recaptcha_secret = get_option( 'captcha_secret_key' );
        $response = file_get_contents( "https://www.google.com/recaptcha/api/siteverify?secret=" . $recaptcha_secret . "&response=" . $_POST['g-recaptcha-response'] );
        $response = json_decode( $response, true );
        if( true == $response["success"] )
        {
            return;
        }
        else
        {
            wp_die( __( "<strong>ERROR</strong>: You are a bot" ) );
        }
    }
    else
    {
        if( get_option( 'captcha_site_key' ) && get_option( 'captcha_secret_key' ) )
        {
            wp_die( __( "<strong>ERROR</strong>: You are a bot. If not then enable JavaScript" ) ); 
        }
        else
        {
            return;
        }

    }   

    return $errors; 
}

上記のコードがどのように機能するか見てみましょう。

  • lostpassword_formアクションを使ってチェックボックスを表示しました。
  • 最終的なパスワードリセットリンクを作成する前に、WordPressは追加の検証ステップを追加するためにlostpassword_postアクションを実行します。このフィルターでユーザーがボットか人間かをチェックします。人間の場合は何も返しませんが、そうでない場合はエラーメッセージを出してスクリプトを終了させます。

最後に

Webサイトのフォームをボットから守り、ユーザーの利便性を高める新しい方法です。また、Google はこの新しいタイプのキャプチャを使用して内部的にボットまたは人間を検出する方法を学ぶことができます。

Follow me!

-Wordpress

PAGE TOP