ロボットで「私はロボットではありません」を突破してみる

  • 30 December 2021
Post image

 ふと何気なくyoutubeを見ていたら以下の動画にたどり着いた。内容は「recaptcha v2」の 「私はロボットではありません」のセキュリティチェックがロボットにとって最も難しいと説明されていた。



 いや、そんなわけあるか!しかもこの動画は"2021/04/13"に公開されているので、「私はロボットではありません」が強固と言われていた古い時代に作られた動画でもない。2021年にはすでにrecaptchaのv3やEnterpriseが存在していて、この「私はロボットではありません」ってのは古くてショボいものって印象。この動画の作者はおそらく誤った動画を作ってしまっているように思える。

 そこでこの「私はロボットではありません」の操作が本当にロボットにとって一番難しいのか実際に確かめてみた
 ちなみに一応書いておくが、以下の操作は悪用しないで。どこかのサイトに対してやると当然悪用した者の身元は割れてしまうので、犯罪行為で何かしらの罰を課せられる可能性がある。


recaptchaを搭載したページを用意

 WPのコンタクトフォーム7でrecaptchaを用意する。ちなみにCF7では、古いバージョンでなければV2を設定できないので、CF7のバージョン4.9系をインストールして以下のようなページを作成した。(もちろんAPIキーも正しく本番用をセット)

 内容に文字列を入れて送信するとメールが送信されるようにしている。つまり、このページにロボットでアクセスして送信し、メールが届けば成功ってこと。


recaptchaを突破するための作戦

 まぁまずブラウザ経由でないアクセスは当然人間でないと判断されるだろう。実際cURLで当該ページを取得したところ、「私はロボットではありません」の箇所はJSとiframeで描写されているようだったので、通常のHTTPリクエストのみでは不可能だろう。そこで、以下のような作戦でロボットを操作してみる。

  1. Chromiumブラウザを起動して対象ページをプログラムから操作する
  2. 人間が操作したかのようなms(ミリ秒)のwaitをしたりして人間ぽくしてみる

 とりあえずこの2つの要件を満たすコードを書いて試してみる。これでだめならもう少し複雑な操作を追加してみる。


Puppeteerでスクレイピング

 Chromiumを簡単に導入するならPuppeteerが楽勝そうだったのでやってみる。(nodejsはインストールされている前提)

npm install puppeteer --save

 たったこれだけでヘッドレスchromiumを利用したスクレイピングが可能だ。クッソ簡単。
 ちなみに以下のようなコードで、ロボットがブラウザからウェブサイトにアクセスしてその状態のスクリーンショットで保存するのも簡単だ。なのでロボット操作の状態を視覚的に確認することが可能。

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('ページのURL');
  await page.screenshot({path: 'result.png'});
  await browser.close();
})();

 ちなみに、用意したページに対してロボットが通常の方法でアクセスして送信ボタンを押させてみたら、スクショは以下のようにセキュリティに引っかかってエラーが出ていた。

 ほぉん。これがreCaptchaの力か・・・


ロボット君、人間になり済ませるか!?

 早速app.jsというファイルを作成し、以下のプログラミングを行った。

const puppeteer = require('puppeteer');
function delay(time) {
  return new Promise(function(resolve) { 
      setTimeout(resolve, time)
  });
}
(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('対象のURL');
  await delay(2312); // ランダムな数値に変更してもよい
  await page.type('input[name="your-subject"]', '私はロボットです'); //メールの本文を書き込み
  await delay(2433); // ランダムな数値に変更してもよい
  await page.frames().find(f => f.url().indexOf('recaptcha') != -1).click('div.recaptcha-checkbox-border');
  await delay(1877); // ランダムな数値に変更してもよい
  await page.screenshot({path: 'result.png'});
  await page.click('input[type="submit"]');
  await browser.close();
})();

 そして以下のコマンドで実行。

node app.js

 するとpuppeteerのスクリーンショットは以下のようになった。

 もちろん正しくメールも送信されていた。(「送信ボタン」をロボットが押せている。)

I’m not a robot…らしいっすわ

 たった20行にも満たないコードで簡単にロボット君は人間になり済ませましたw。ちなみにUSリージョンのサーバ内から実行しても成功しました。つまり海外からの突破も可能ってこと。


あの、ウソつくのやめてもらっていいですか?

 う~ん。さすがに簡単すぎないか?上記のコードを作成するのに15分程度しかかかってないぜ。簡単すぎで初めは失敗すると思ってこのあと、スクロールやカーソル、クリックをランダムに動作させて人間ぽくすることも考えていたんだけど。
 つまりこの「私はロボットではありません」が搭載されたログイン画面や会員登録画面に対して、プログラムでアクセスして何万回も試行することも簡単ってこと。(!犯罪行為です!)
 2021年現在ではこのreCaptchaはEnterpriseってのが出ていてさすがにこれはもっと精度が高いでしょう。ただv3やEnterpriseで「私はロボットではありません」のボタンが出てくることはない。あと、あえてやらないけど、v3やEnterpriseも同じような考えで突破可能だと思われる。

 あの、、 「私はロボットではありません」が最強ってウソだよね。上記のような単純なプログラミングでもロボットが突破出来てしまっているので、最強は言いすぎでしょ。
 それと、同時にこの程度のものでセキュリティ対策ってちょっと信用できないよね。chromiumでwaitとかしているから1回の実行に時間がかかるため、何万回もの試行を避けられるとか思っているのでしょうか?コンテナ数百個起動して、かつ、上記のnodeをそれぞれ並列で実行すれば、いとも簡単に数十万回実行可能だ。
 ということで、今回はロボットで「私はロボットではありません」を簡単に突破してみた

You May Also Like

WordPressサイトを守る最低限の設定

WordPressサイトを守る最低限の設定

 WPへの攻撃方法について書きましたが、WPサイトを構築する上での最低限のセキュリティ対策をおこなっていれば、前回記事のようなことにはならない。そこで最低限の対策を紹介。 ログイン情報は複雑に パスワードは覚えるものではない  とにかくログインパスワードを複雑にしておけば、クラックするのが各段に難し …

情弱が運営するWordPressサイトを攻撃する

情弱が運営するWordPressサイトを攻撃する

 なんとなく悪いことってのは、魅力的だったりする。 おそらく1970年代~1990年前半に生まれた人で、学生時代にPCを触っていた人ってアングラな世界に1度や2度触れたことがあるのではないでしょうか?特にエロ系ね。私も若かりし頃は、なんとかしてずりネタを確保しようと、意味も分かってなかった通信プロト …