LoginSignup
0

More than 1 year has passed since last update.

Google reCAPTCHA v2はどうするとスパム判定されるのか?

Last updated at Posted at 2022-02-23

Google reCAPTCHA v3の続き。

Google reCAPTCHA v2

いわゆる 「ロボットではありません」です。

v3はそれが表示されないのですが、v3が新しくてよい、というわけではなく以下のような区別のようです。

  • v2: スパムの判定をGoogleに任せる
  • v3: スパムの判定を自分で行い、細かい制御を行う
    • ハンドリングしてあとから制御したりできるメリットが有る

key, secretの取得

https://www.google.com/recaptcha/admin/create
ここからkeyとsecretを発行します。

フロントエンド

<script src="https://www.google.com/recaptcha/api.js" async defer></script>
<div class="g-recaptcha" data-sitekey="YOUR_KEY"></div>

以下のようなHTMLが生成されます。iframeですね。

<iframe title="reCAPTCHA" src="https://www.google.com/recaptcha/api2/anchor?ar=1&amp;k=xxxxxxxx&amp;co=xxxxxxx.&amp;hl=ja&amp;v=xxxxxxx&amp;size=normal&amp;cb=xxxxxx" width="304" height="78" role="presentation" name="a-xxxxxx" frameborder="0" scrolling="no" sandbox="allow-forms allow-popups allow-same-origin allow-scripts allow-top-navigation allow-modals allow-popups-to-escape-sandbox"></iframe>

バックエンド

g-recaptcha-response というパラメータが渡されるので、それをバックエンドからGoogleのAPIをリクエストすることで検証します。
今回はAPIのレスポンスを表示しています。

$captcha = $_POST['g-recaptcha-response'];

if (!isset($captcha)) {
  echo "g-recaptcha-response is not set";
  return;
}

$secret = "YOUR_SECRET";
$verifyResponse = file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=".$secret."&response=".$captcha);
echo $verifyResponse;

テストページ

今回、ターゲットになるフォーム
僕の実験サイトなので好きに触ってみてください。

試してみた

正常系

{
  "success": true,
  "challenge_ts": "2022-02-23T08:36:24Z",
  "hostname": "pokosho.com"
}

JSでクリックしてみる

iframeなので操作できません。
これができたら、Twitterをiframeで表示して、ようこそ @kaiba さん! って出せてしまいますからね。

ちなみにCORSのエラーですので、自社サービス間とかは許可することで取得できますね。

Blocked a frame with origin "https://pokosho.com" from accessing a cross-origin frame.

headless chrome(puppeteer)

JSで取得できないので座標で押してみる。
.g-recaptcha で座標を取得して、チェックボックス内をクリックします。
左端から右、下に30pxをクリックします。

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('https://pokosho.com/a/recaptcha/v2.html',
    {'timeout': 10000, 'waitUntil':'load'}
  );
  await page.waitForTimeout(1000); 

  const selector = ".g-recaptcha";
  const recaptchaPosition = await page.evaluate((selector) => {
    var el = document.querySelector(selector);
    var rect = el.getBoundingClientRect();
    return {
        height: rect.height,
        width: rect.width,
        x: rect.left,
        y: rect.top
    };
  }, selector);
  const margin = 30;
  await page.mouse.move(recaptchaPosition.x + margin, recaptchaPosition.y + margin, { steps: 1 });
  await page.mouse.click(recaptchaPosition.x + margin, recaptchaPosition.y + margin);

  await page.waitForTimeout(1000); 
  await page.click('#submit');
  const json = await page.content();
  console.log(json);
  await browser.close();
})();
{
  "success": true,
  "challenge_ts": "2022-02-23T09:05:21Z",
  "hostname": "pokosho.com"
}

え… マジで…?

まとめ

  • Google reCAPTCHA v2「ロボットではありません」ならマウスの動きとかを見てロボットかどうか判定してくれる。そう考えてた時期が俺にもありました。
  • Google reCAPTCHA v2のボタンはiframeなのでJSでは押しづらい。
  • Puppeteerで座標を指定してクリックするとスパムにはならなかった。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0