WordCampサイトのローカルテスト中にフォーム操作ができなくなった場合は、スパム判定を疑おう

最近、WordCampのソースコードを触り、決済フォーム周りのスパム対策やスコア処理について勉強中。ローカルで意図的にエラーを発生させたい場合は、スパム判定回避としてget_score_for_ip_address関数を編集し、常に0を返すようにする方法がある。本番環境でスパム誤判定を避けるためには、Transient APIに保存されたデータが消えるのを待つしかない。操作に注意して開発を進めよう。

広告ここから
広告ここまで

目次

    最近不定期にではありますが、WordCampのソースコードを触る機会を増やそうとしています。その中で先日、決済フォーム周りの動作を確認していた際に、気になる動きを見つけたので覚書として紹介します。

    WordCampサイトは、フォームまわりにスパム対策処理が入っている

    当然ではあるのですが、WordCampのシステム(WordPressマルチサイト)にはフォームへのスパム投稿を検知・ブロックする仕組みがあります。ソースコードでいくと、public_html/wp-content/mu-plugins/utilities/class-form-spam-prevention.phpあたりにそれらしき処理がありました。

       /**
         * Retrieve the throttle score for a given IP address.
         *
         * @param string $ip_address An IP address.
         *
         * @return float
         */
        protected function get_score_for_ip_address( $ip_address = '' ) {
            if ( ! $ip_address ) {
                $ip_address = $this->get_ip_address();
            }
    
            $score = floatval( get_transient( $this->generate_score_key( $ip_address ) ) );
    
            return $score ?: (float) 0;
        }

    実装をざっとみた感じでは、Transient APIを利用して、IPアドレスごとにスパム判定のスコアを一時保存している様子で、一定のスコアを超えるとフォーム送信などがブロックされるようになっていました。

    ローカル開発で、「意図的にフォーム処理を失敗させる」とどうなるか

    決済まわりで、Stripe APIを呼び出す際にAPIエラーが発生するケースがWordCamp Kansai 2024の運営中に発生していました。これの再現をローカルで試みていたところ、「短時間にフォーム送信を失敗する謎のIPアドレス」がWordPress側に認識されてしまい、「何もしていないのに、期待しているエラーと違うエラーしか出なくなる現象」に遭遇しました。

    ソースコードを確認してみたところ、次のような処理が見つかりました。add_score_to_ip_addressの中では、フォーム送信を失敗させると点数が通常より増えやすくなっています。意図的に決済失敗を繰り返したため、このスコアが急激に伸びてしまったのが原因と思われます。

                   if ( is_float( $test ) || is_int( $test ) ) {
                        $score += $test;
                    } else {
                        switch ( $test ) {
                            case 'pass':
                            default:
                                $score += 0.5;
                                break;
                            case 'fail':
                                $score += 2;
                                break;
                        }
                    }

    本番環境で発生したらどうするか?

    本番環境でスパムと誤認されるような操作をするんじゃない・・・といいたいところですが、本番環境では、Transient APIに保存されたデータが消えるのを待つしかないでしょう。処理を見る限り、1時間程度保存される様子ですので、「この時間は別の作業をやりましょうか」と切り替えていくしかないように感じます。

       public function __construct( array $config = array() ) {
            $defaults = array(
                'score_threshold'     => 4,
                'throttle_duration'   => HOUR_IN_SECONDS,
                'prefix'              => 'fsp-',
                'honeypot_name'       => 'tos-required',
                'timestamp_name'      => 'dob-required',
                'timestamp_max_range' => '- 2 seconds',
                'individual_styles'   => false,
            );
    
            $this->config = wp_parse_args( $config, $defaults );
        }

    ローカル環境で意図的にエラーを発生させたい場合の、スパム判定回避方法

    意図的にエラーを発生させたい場合で、「この作業をやっている間だけ、スパム判定を止めたい」というケースでは、ちょっとした力技を使うことができます。get_score_for_ip_address関数を編集して、常に0が返るようにしましょう。

       /**
         * Retrieve the throttle score for a given IP address.
         *
         * @param string $ip_address An IP address.
         *
         * @return float
         */
        protected function get_score_for_ip_address( $ip_address = '' ) {
            if ( ! $ip_address ) {
                $ip_address = $this->get_ip_address();
            }
    
            $score = floatval( get_transient( $this->generate_score_key( $ip_address ) ) );
            return 0;
    
            return $score ?: (float) 0;
        }

    これですでに高いスコアが記録されていたとしても、判定処理には常に0が渡るため、フォーム操作などがブロックされなくなります。

    もちろんローカル開発の際に意図的に振る舞いを変えるためだけの措置ですので、この変更を誤ってgit commitしたり本番環境に適用したりしないようにご注意ください。

    広告ここから
    広告ここまで
    Home
    Search
    Bookmark