CAPTCHA(アンチスパム・イメージ)を使った認証

(1/1)
CAPTCHA(アンチスパム・イメージ)
Webのユーザー登録画面などで、左のような画像に含まれている文字を入力させる場面がある。スパムによる自動入力を防止するための措置で、このような画像を「CAPTCHA」(アンチスパム・イメージ)と呼んでいる。
今回は、PHPを使って CAPTCHA を生成し、入力された文字が CAPTCHA に合致するかどうか、予想される攻撃にも配慮しつつ、プログラムを作ってみることにする。
CAPTCHA は、JpGraph がライブラリとしてサポートしているので、これを利用することにする。

(2024年3月24日)pahooInputData導入, bug-fix

サンプル・プログラムの実行例

CAPTCHA(アンチスパム・イメージ)を使った認証

サンプル・プログラム

圧縮ファイルの内容
captcha.phpサンプル・プログラム本体
圧縮ファイルの内容
tide.phpサンプル・プログラム本体。
pahooInputData.phpデータ入力に関わる関数群。
使い方は「数値入力とバリデーション」「文字入力とバリデーション」などを参照。include_path が通ったディレクトリに配置すること。
captcha.php 更新履歴
バージョン 更新日 内容
2.2.0 2024/03/24 pahooInputData導入, bug-fix
2.1 2022/03/26 PHP8対応,リファラ・チェック改良
2.0 2018/06/03 antispam_image.php と一体化、UTF-8化
1.1 2008/04/29 セキュリティ対策
1.0 2007/01/27
pahooInputData.php 更新履歴
バージョン 更新日 内容
1.5.0 2024/01/28 exitIfExceedVersion() 追加
1.4.2 2024/01/28 exitIfLessVersion() メッセージ修正
1.4.1 2023/09/30 コメントの訂正
1.4.0 2023/09/09 $_GET, $_POST参照をfilter_input()関数に置換
1.3.0 2023/07/11 roundFloat() 追加

準備

  59: //表示幅(ピクセル)
  60: define('WIDTH', 600);
  61: 
  62: //発生するアンチスパム画像の桁数(デフォルト)
  63: define('DEF_COL', 6);
  64: 
  65: //マッチングするのに使うCOOKIE名
  66: define('COOKIE', 'AntiSpamChars');
  67: 
  68: //マッチングするのに使うCOOKIEの有効時間(秒)
  69: define('INTERVAL', 60);
  70: 
  71: //JpGraph(各自の環境に合わせて)
  72: require_once('jpgraph/jpgraph_antispam.php');

CAPTCHA の生成には JpGraph を利用する。導入方法については、「PHPとJpGraphで人口ピラミッドを表示する」を参照のこと。

解説:CAPTCHAを生成する

 256: //CAPTCHA生成+Cookieにセット
 257: if ($captcha) {
 258:     $spam = new AntiSpam();
 259:     $chars = $spam->Rand($col);
 260:     setcookie(COOKIE, $chars, time() + INTERVAL, '/');      //Cookie
 261:     $spam->Stroke();
 262:     $spam = NULL;

AntiSpam クラスの新しいインスタンスを作成する。
発生させる CAPTCHA をランダムに発生させるメソッド RandAntiSpam クラスに用意されている。引き数は発生する CAPTCHA の桁数である。
また、表示できるイメージは半角数字・半角英小文字のみである。ただし、アルファベットの 'O' (オー)と数字の '0' (ゼロ) はよく似ており間違えやすいので、使われない。

CAPTCHA を生成するのは Stroke メソッドである。

実際に表示する CAPTCHA を文字列データとして、関数  setcookie  を使って Cookie に入れておく。Cookie の寿命は定数 INTERVAL に設定してある。
これにより、認証に使う文字列データはクライアントに渡されたことになる。以後、サーバ側では関知できず、サーバ攻撃を受けたとしても認証文字列データが漏れることはない。

解説:CAPTCHAを認証する

 264: //CAPTCHAチェック+表示
 265: else {
 266:     if ($key == '') {
 267:         $res = FALSE;
 268:     } else if (preg_match('/^[a-z|0-9]+$/', $key) == 0) {
 269:         $errmsg = '入力キーは数字または英小文字です';
 270:     } else if (isset($_COOKIE[COOKIE]) && ($_COOKIE[COOKIE] == $key)) {
 271:         $res = TRUE;
 272:     }
 273:     $HtmlBody = makeCommonBody($key, $res, $errmsg);
 274: 
 275:     // 表示処理
 276:     echo $HtmlHeader;
 277:     echo $HtmlBody;
 278:     echo $HtmlFooter;
 279: }

認証処理では、組み込み関数  preg_match  を利用して、入力文字の種類(半角数字・半角英数字;AntiSpam クラスが発生させることができる文字種)を検査する。
これは、クロスサイトスクリプティング(XSS)対策の意味もある。

検査をクリアしたら、CAPTCHA発生時にセットされた Cookie の内容と入力文字列を比較する。完全に一致すれば認証成功である。

CAPTCHAが破られる?

2008年(平成20年)2月、セキュリティ企業の Websense は、スパマーがボット・プログラムを使って Windows Live Mail の CAPTCHAを破ったと伝えた。
このボットは、Live MailのCAPTCHA画像をCAPTCHA破りサービスに送信して読み取らせ、解読したテキストを受け取る仕組みになっている。CAPTCHA破りに成功する確率は平均で3回に1回程度だが、このプロセスを何度も繰り返すことで、悪用目的のアカウントを大量登録しているという。
さらに4月には、Googleの CAPTCHA も突破されたと報じている。

こうした動きを受け、米ペンシルバニア州立大学は。新しいCAPTCHA技術「IMAGINATION」を開発した。
IMAGINATIONでは、まず組み合わされた複数の画像の中からどれか一つの画像の中心をクリックし、次に表示された画像の説明をリストから選ぶという二段階の認証方式をとっている。ユーザに表示される画像は、ランダム生成されたパラメータによって色が変えてあったり、関係ない質感や縁取りが表示されるようになっている。

JpGraph によって生成された CAPTCHA も、いつか破られる(破られた)かもしれない。
こうしたプログラムは、ユーザーが少ない方が破られにくい(スパマーが興味を抱かないため)ので、参考サイトで紹介しているようなライブラリを使うといいだろう。

CAPTCHAに関する最近の話題

妹認証」が登場した。妹の絵に書かれた文言(日本語の画像)に返答することで認証できる。
デモ版のインターフェースはともかく(笑)、隠語を符丁にしたCAPTCHAというコンセプトは使えそうだ。

Securimage PHP CAPTCHA では、PHPから利用できるさまざまな CAPTCHA 生成ライブラリを無償提供している。これらを使い分けることで、CAPTCHAを破られるリスクは低くなるだろう。

2010年(平成22年)7月、カナダのソフト企業Leap Marketing Technologiesは、動画を使って強化した「NuCaptcha」を発表した。
NuCaptchaは、歪んだ文字をアニメーションで表示することで、コンピュータによる文字の判読をさらに難しくするという。
同社は、NuCaptchaをWebサイトに組み込むためのプラットフォーム「NuCaptcha Basic」を提供する。月間2万5000CAPTCHAまで無料で利用できる。

2011年(平成23年)5月、お絵かきでCAPTCHAできるようにするjQueryプラグイン「MotionCAPTCHA」が公開された。
フォーム下に線画を用意しておいて、それをマウスでなぞってValidateする仕組みだ。

CAPTCHAを使って書籍をデジタル化

米カーネギーメロン大学のコンピュータサイエンス校が「reCAPTCHA」というプロジェクトを立ち上げた。
これは、文字のにじみなどがありOCRでは判読できない書籍の一節をCAPTCHAに利用。未判読の単語と既に判読されている単語を組み合わせて表示し、ユーザーに両方の単語を読み取ってもらうというもの。判読済みの単語が正しく入力されれば正解として扱い、別のユーザーにも判読してもらうことで精度を高める。こうして、人力で書籍をデジタル化していくのである。

このプログラムを約1年間にわたってネット上で公開したところ、4万以上のウェブサイトで採用され、約1万7600冊の書籍に相当する4億4千万以上の単語が、ネット利用者によって解読された。正解率は、書籍のデジタル化サービスの業界標準に匹敵する99.1%にのぼったという。

参考サイト

(この項おわり)
header