はてなのCAPTCHAを破るプログラムは30分で書ける
CAPTCHAとは、スパムコメントなどを防止するための認証画像のことである。
それにしても、はてなのCAPTCHAはひどい。無いよりマシという考え方もあるのでそれについてはあまり議論する気は無いのだが、それにしてもこれを破るプログラムは30分あれば十分書ける。
具体的には、はてなのCAPTCHAには8つの好ましくない特徴と、2つの脆弱性がある。
■ 8つの好ましくない特徴
・画像自体のサイズが小さすぎる。→ こんなに小さいと探索量(計算量)が小さくて済む。
・フォントにゆがみがない → フォントはある程度変形させたほうが良い。変形させてあるとテンプレートマッチングがしにくくなる。
・フォントが固定。→ フォントは毎回変えたほうが良い。
・フォントを回転させていない → フォントは文字ごとにある程度ランダムに回転させた方が良い。
・フォントサイズが一定 → フォントサイズは文字ごとにある程度ランダムに変化させた方が良い。
・フォントの色がすべて同じ → 文字は文字ごとに色をわずかに変えたほうが抽出しにくくなる
・背景画像が単調 → これでは簡単に文字だけを抽出できてしまう。
・使われている文字の種類が少なすぎる。0〜9とa〜fまでの16種類しかない。
この8つの好ましくない特徴だけ見ても、これはCAPTCHAとしてはかなり出来が悪いと言わざるを得ない。何を思ってこんなひどいCAPTCHAを採用したんだろう。
しかしそれよりひどい決定的な脆弱性が二つある。
1) 文字の表示位置が毎回同じ
何とも信じられないことだが、文字の表示位置が毎回同じである。文字フォントの種類も同じ、文字のフォントサイズも同じなので、対象位置固定でテンプレートマッチングを行なえばほぼ確定する。
2) 画像を要求されるごとにスクラッチの位置が異なる
http://d.hatena.ne.jp/captcha?key=XXXXXXX
の部分がCAPTCHA画像だが、このURLの画像は要求されるごとにスクラッチの位置が異なる。
このように要求されるごとにスクラッチの位置を変える実装は好ましくない。(1回しか画像要求のリクエストに応えないようにするか、何度リクエストされても同じ画像を返すようにするのが普通の実装だと思う。)
これなら論理積をとるだけで綺麗に文字が抽出できる。
2階調化したあと2つの画像の論理積をとったもの。
わずかにノイズが残っている。
2階調化したあと3つの画像の論理積をとると…
ノイズは完全に消えた。
1)だけでもほぼ100%CAPTCHAを突破できるが、1)と2)とを組み合わせれば100%突破できる。
■ CAPTCHAは終わった技術なのか?
CAPTCHAは少し工夫するだけでBOTによる突破は非常に困難になる。仮に突破に成功するBOTが出現したとしても、CAPTCHAの特性を少し変更すれば、それに対応するBOTを書くには非常に時間がかかる作業であり、このいたちごっこは、(常識的には)CAPTCHA作成側のほうが圧倒的に有利である。
なぜならCAPTCHAを生成したり、そのアルゴリズムを変更したりするのは簡単にできるが、それを正しく認識するプログラムを書くのは遙かに大変だからである。
はてなのCAPTCHAは今回見たように100%の確率で突破できるプログラムを書くのは容易だが、だからと言ってすぐにこのCAPTCHAに修正すべきだと私は言うつもりはない。
はてなの運営側は、BOTによる書き込みが増えてきたらそのときに変更すればいいと考えているのだと思う。CAPTCHAはどうせ作成側が圧倒的に有利なのでそれくらいのゆるい運用でもいいという考え方も成り立つ…のかな。