CAPTCHAをご存知でしょうか。

スパム防止のために歪んだ文字とかを入力させる、アレのことなのですが、 はてなのCAPTCHAの強度が妙に低く思えたので検証してみました。

CAPTCHAというのはいわゆる逆チューリングテストという奴で、 人間には可能だが機械には処理しにくいことをさせることで、 ロボットによる操作を弾こうというものです。

たとえば、Gmailのユーザ登録には以下のような画像が表示され、 表示されている文字を入力することが求められます。

CAPTCHAの強度

例えばスパムを送るために大量のGmailアカウントを得ようとしてる人がいたとします。 手作業でGmailを登録するのは骨が折れる。 そこでプログラムによる機械化を試みることになるわけです。

その際、障壁となるのがこのCAPTCHAなのです。 この画像から正解である文字列"vittac"を得ることは機械には難しい。

プログラミング初心者にはどのようなプログラムを書けばそのようなことが 可能になるか想像もつかないでしょうし、プログラムをある程度かじった人間なら これがいかに難しいことか容易に想像がつくと思います。では、その難しさはどこからくるのか？

ちょっと古い記事になりますが、Radium Software DevelopmentにCAPTCHAの強度に関する記事 「Breaking CAPTCHAs with NNs」 がありました。

CAPTCHAをプログラムで破ろうとする場合、 プログラムは二つの過程を経ることになります。 それは、文字の分割と認識です。

まずは、個別の文字を切り分けなくてはなりません。 それから、その個々の文字が何であるかを判別するのです。

先の記事によると、CAPTCHA破りにおいて難しいのは分割のほうであり、 認識はさほど難しくないとあります。

はてなのCAPTCHAを破る

さて、はてなのCAPTCHAですが、アカウント登録していないユーザが書き込みを行おうとすると 以下のような画像と入力欄が表示されます。

しばらく利用していれば、この画像には0-9とa-fまでの16種類の文字しか表示されない ことに気が付くことでしょう。 10回画像を表示して、並べて見ると以下のようになりました。

どうも文字の表示位置は決まっているように思いませんか？

固定のフォントで固定の位置に幾分色を変えて表示した文字に、ノイズを多少加えたモノのようです。 背景色は同じグレーです(ノイズはjpg化する際に乗るブロックノイズと思われる)。

位置が固定なので、座標を直接指定して文字を切り出します。 この切り出し過程は非常に容易です。あらかじめ、いくつかの画像をもとに、 文字の表示される位置を計測しておくだけでよい。

次に、色の違いをそろえるために白と黒の2値化します。 背景色が一緒なのでその色だけ背景として除去する方法も考えられますが、 jpg化に伴うモノとみられるブロックノイズが乗っていますので、 そこまでの手抜きはできませんが、単にRGBのどれかが0x80以下のものを黒、それ以外を白という 単純な条件判断で綺麗に2値化できてしまいます。

以上の過程を経て抽出文字を複数個サンプリングして、 論理和をとってノイズが乗っていない生のフォントを抽出します。

さて、あとは、これを実際の画像と重ねて一致率を見ます。

一致するピクセルと、しないピクセルの比率を計測するわけです。 ノイズは線が加わるだけなので、もともとのフォントで黒の部分が白になることはありません。 元フォントの黒部分に対して判別対象が黒であることを確認すれば用が足ります。

さらに文字が16種に限られるため、ループ回数も少なくて済むため軽い。 このうち、もっとも一致率の高いものが元の画像であると判断するようにプログラムしてみました。

さて、テストとして、以下の画像を読み込ませます。

そして、結果はこの通り。

左端のフォントが論理和をとった画像。右は元になった画像です。 上図ではサンプル数が20個程度と少ないのでノイズが除去し切れていませんが、 かなり容易に文字が抽出できることがわかると思います。

このプログラムに何個かのCHAPCHA画像を読み込ませて見ましたが、全て認識することが出来ました。

以上ではてなのCAPTCHAを破ることができたわけですが、ポイントは以下の４つ。

文字の位置がドット単位で固定であるため切り出しが非常に容易

色が限られるため、2値化することが非常に容易

ノイズが加算に限られるためパターンマッチングが非常に容易

文字種が少ないため高い精度で認識しやすい

今回、検証のために書いたプログラムはJavaでおよそ200行程度です。 製作時間は1.5時間程度。swingによるUIがありますから、 純粋なCAPTCHA破りロジックは100行程度になります。 スパマーによる悪用の可能性があるため公開はしませんが、 プログラムに慣れた人間であれば短時間にCAPTCHA破りのコードを書くことができるわけです。

はてなのblogはシェアも大きいですから、コメントスパムの標的にされることは多いと思います。 その点リスクは高く、このように安易に破られるCAPTCHAの実装では、 早晩スパマーによってコメントスパムで荒らされるのではないでしょうか。

2008/03/10追記

費用対効果について「 はてながCAPTCHAの費用対効果で見落としていること」にて考察しました。

投稿日時 : 2007年10月26日 20:21