CAPTCHA によるコメントスパム対策

Posted by
ぴろり
Posted at
2005/06/01 22:41
Trackbacks
関連記事 (5)
Comments
コメント (9)
Post Comment
コメントできます
Category
MovableType カテゴリ

 スパムボットのようなコンピュータプログラムと人間を区別するために、CAPTCHA と呼ばれる仕組みが使用されています。Google や Yahoo! など大手サイトでもこの仕組みを利用して、プログラムからの攻撃に対する防御力を高めています。
 このエントリでは、この CAPTCHA のうち Gimpy と呼ばれる仕組みを使ったコメントスパムボットへの対策を紹介しています。

この記事を Delicious に追加する   このエントリーをはてなブックマークに追加  

背景

 CAPTCHA とは「コンピュータと人間を区別する完全に自動化された公開チューリングテスト」の接頭句で、例えば、複数枚の絵から連想される単語を答えると云ったような、人間には簡単に解ける問題でもコンピュータプログラムにはそれが難しい、という性質を利用したものです。
 Google のサイトの登録ページで見られるものは、CAPTCHA のうちでも Gimpyと呼ばれる仕組みで、MovableType でもコメントスパムボット対策として、これを利用したプラグインがあります。 James Seng's blogSolution for comments spamsは、 コメントの投稿時にランダムな数字列の画像から認証キーを入力するもので、 小粋空間 MT-SCode プラグインによるコメントスパム対策(その1)でその導入方法が詳細に解説されています。
 ただ、この仕組みはコメントスパムボット以外のプログラムに対しても非常に効果的ではありますが、MovableType のプラグインという形態のために再利用しにくいと言えます。せっかくですから、MovableType 以外の環境や、更には普通のログインシーケンスなどにも流用できるようにしたいものです。

Tiny Gimpy

 そこで、これをヒントに MovableType 以外にも様々に流用できるような Gimpy の廉価的実装を行いました。 仮にこれを Tiny Gimpy と名付け、MovableType などの環境に依存しないよう独立した CGI として動作するようにしています。
 以下にこの Tiny Gimpy を MovableType に導入する手順を紹介します。

今のところ非常に簡易的なモノなので Tiny ということで。

Tiny Gimpy
GetMD5Hash('TGimpy100.zip');
ver.1.00, '05/06/01, GetFileSize('TGimpy100.zip');bytes, Perl
  • 初版公開
  • 別途、GD ライブラリ必須

最新版のダウンロードやバグレポートはCAPTCHA の trac レポジトリでも行っています。

Step 0. 設置と動作確認

 Tiny Gimpy の本体である tgimpy.cgi は、チューリングテストのための画像生成 CGI と、 パスコードのチェック用ライブラリを一つのファイルで兼ね備えています。 tgimpy.cgi をブラウザから直接実行した場合、クエリ文字列と個別の設定ファイルから 一意の数字列を含む PNG 画像を生成・表示します。
 動作にはサーバに以下の Perl ライブラリがインストールされている必要があります。
  • CGI
  • GD
  • Digest::MD5
 とりあえず、tgimpy.cgi をサーバにアスキーモードでアップロードし、 パーミッションを 755 または 777 に設定した後、ブラウザから呼び出してみてください。 9 桁の数字列がランダムに表示されればひとまず成功です。

引数無しで与えた場合の実行結果

Step 1. パスの設定

 設定ファイル(後述)の保存先に合わせて、tgimpy.cgi を修正します。 tgimpy.cgi をエディタで開き、GetCfgPath をサーバに合わせて修正してください。 設定ファイル(次のStep.2で説明)はここで指定したディレクトリパスに保存します。

Step 2. 設定ファイルの作成

 アーカイブに添付の sample.cfg を好きな名前に変え(ここでは yourblog.cfg と仮定します)、 Step 1 で設定したディレクトリパスにアスキーモードでアップロードします。

Step 3-1. MovableType の修正 1

 個別エントリのテンプレートを修正し、tgimpy.cgi への呼び出しと、 コメント投稿フォームに認証用のフィールドを追加します。
<!-- 設定ファイル名の .cfg 以前の部分 -->
<input type="hidden" name="cfg" value="yourblog">

認証キー
<!-- エントリ ID をキーに認証用画像を表示 -->
<!-- cfg=yourblog の部分は上と同じ設定ファイル名に合わせてください -->
<img src="/cgi-bin/tgimpy/tgimpy.cgi?cfg=yourblog&key=<$MTEntryID$>">
を入力してください:
<input type="text" name="ans">

文字列"yourblog"を任意に変更した場合は、全ての箇所を同じにしてください。

Step 3-2. MovableType の修正 2

 (MT のインストールパス)/lib/MT/App/Comment.pm を修正します。 CheckAnswer 関数が用意されているので、 これを使って入力された認証キーが正しいか否かを判定し、 不正な場合はエラーメッセージを表示します。
sub post {
    my $app = shift;
    my $q = $app->{query};

    return do_preview($app, $q, @_) if $app->request_method() ne 'POST';

    ;### ここから追加
    require '/home/magicvox/www/cgi-bin/tgimpy/tgimpy.cgi';
    my $cfg = $q->param ('cfg');
    my $ans = $q->param ('ans');
    return $app->handle_error ("認証キーを入力してください")
            if (! &TGimpy'CheckAnswer ($cfg, $q->param('entry_id'), $ans));
    ;### ここまで追加

設定ファイル(*.cfg)について

 設定ファイルでは、TGimpy の動作について幾つかの項目をカスタマイズすることができます。
szCryptKey
秘密キーです。 tgimpy.cgi の結果は公開キー(エントリ ID)と秘密キーから計算しています。 この秘密キーの存在が、スパムボットの作成を困難にしています。 できるだけ長く、推測されにくい文字列を与えます。
nSizeX, nSizeY
tgimpy.cgi 呼び出し時に作成される認証用画像のサイズをピクセル単位で指定します。
nFigure
認証用キーのケタ数を 1 から 9 の間で指定します。

トラブルシューティング - 動かない時は?

症状:画像が表示されない
症状:tgimpy.cgi を直接呼び出すと Internal Server Error になる
原因:CGI の準備に何らかの問題があります
対策:tgimpy.cgi がアスキーモードで FTP 転送されているか確認してください
対策:tgimpy.cgi のパーミッションが 755 または 777 に設定されているか確認してください
対策:tgimpy.cgi の 1 行目 #!/usr/bin/perl の部分をお使いのサーバの Perl に合わせて変更してください
対策:サーバに必要な Perl モジュールがインストールされているか確認してください → Step.0
対策:GetCfgPath を修正した個所に余計なシングルクォーテーションや全角空白がないか確認してください → Step.1
対策:設定ファイルがアスキーモードで FTP 転送されているか確認してください
対策:設定ファイルの修正した個所に余計なシングルクォーテーションや全角空白がないか確認してください → Step.2
症状:tgimpy.cgi?cfg=yourblog&key=1 として直接実行した時、設定ファイルの nFigure で指定したケタ数で表示されない
症状:tgimpy.cgi?cfg=yourblog&key=1 として直接実行した時、設定ファイルの nSizeX, nSizeY で指定したサイズで表示されない
原因:設定ファイルが正しく読み込めていません
対策:GetCfgPath が正しく設定されているか確認してください → Step.1
対策:設定ファイルが正しく配置されているか確認してください → Step.2
対策:cfg=... で指定された文字列が設定ファイルと同じか確認してください → Step.2
症状:コメントを投稿すると Internal Server Error になる
原因:MovableType への修正箇所に問題があります
対策:MovableType(Comment.pm) の修正箇所が正しいか確認してください → Step.3-2
対策:MovableType(Comment.pm) の修正箇所に余計なシングルクォーテーションや全角空白がないか確認してください → Step.3-2
対策:MovableType(Comment.pm) の require '...' の行が、正しく tgimpy.cgi を指しているか確認してください → Step.3-2
症状:コメントを投稿しても必ず拒否される
原因:必要なパラメータが CGI に正しく渡っていません
対策:コメント投稿フォームに cfg フィールドがあるか確認してください → Step.3-1
対策:コメント投稿フォームの cfg フィールドの値が設定ファイルと同じか確認してください → Step.3-1
対策:コメント投稿フォームの ans フィールドがあるか確認してください → Step.3-1
対策:img タグの tgimpy.cgi の呼び出しパラメータである cfg と key の値が正しいか確認してください → Step.3-1
対策:ans を半角数字で入力されているか確認してください

既知の問題

  • コメントを直接投稿する場合の動作確認はありますが、事前にコメントのプレビューをした場合、 Tiny Gimpy に必要なパラメータを渡せません。
  • TypeKey 認証との併用は未検証です。

そしてボットは居なくなった

 この例では、キーとして MTEntryID を用いて tgimpy.cgi を呼び出しているため、 一つの記事に対していつでも同じパスコードが生成されています。 そのために、スパマーがこのパスコードを見た上でスパムボットを調整してやると、 そのスパムボットはその一つの記事に対してコメントすることが可能になってしまいます。
 しかし、もしスパムボットを他の記事にもコメントを投稿できるようにするならば、 スパマーはこの手順を同じ数だけ繰返さなければなりません。 (この手順を自動化すること自体が CAPTCHA によって不可能に近い)  そして管理者が秘密キーを 1 つ変えてしまうだけで、その苦労は全て無駄になってしまいます。 そんなことならば、わざわざスパムボットを使ってコメントを投稿するよりも、 人間が手動で直接にコメントを投稿して回った方が早いということになるわけです。 しかし、それは既に"スパムボット対策"ではなく、単なる"人間によるコメント荒らし対策"に他ならないのです。

この記事を Delicious に追加する   このエントリーをはてなブックマークに追加  


この記事を読んだ人はこんな記事も読んでいます記事リコメンデーションについて

カバー画像:MovableType のコメント欄でファイルをアップロードする

関連記事/トラックバック (全 5 件中、最新 5 件まで表示しています)

nlog(n) のスクリーンショット
タイトル
Tiny Gimpy で迷惑コメント対策
Trackbacked at
2014/04/15 00:06
from
nlog(n)
概要
CAPTCHA&#8482; による画像認証をつけて迷惑コメント対策をすることにした。...

孤独なサイドアタッカー のスクリーンショット
タイトル
CAPTCHA
Trackbacked at
2008/03/18 01:43
from
孤独なサイドアタッカー
概要
で、コメントスパム対策。 これまでキーワードによるスパム対策を行ってきた(つもり...

画像認証とスパム対策 WFSVIサービスの公式ブログ@はてな のスクリーンショット
タイトル
[WFSVIサービス]綺麗で、安全な画像認証コード(CAPTCHA)をご紹介します
Trackbacked at
2007/11/16 01:00
from
画像認証とスパム対策 WFSVIサービスの公式ブログ@はてな
概要
 アメリカSDDO国際株式会社(USA SDDO INTERNATIONAL CO.,LTD)が綺麗で、破られにくい画像認証コードのサービス(略にして、...

何にもないぶろぐ のスクリーンショット
タイトル
スパムコメント対策
Trackbacked at
2007/04/22 14:04
from
何にもないぶろぐ
概要
コメント入力にも画像認証(CAPTCHA)を導入させていただきました。

Open MagicVox.net のスクリーンショット
タイトル
CAPTCHAによるトラックバックスパム対策
Trackbacked at
2006/06/21 18:44
from
Open MagicVox.net
概要
 以前の記事で、コメントスパム避けのために コメント投稿欄 CAPTCHA テストを導入する方法を紹介しました。 今回、これをトラックバックスパム避けにも利用す...

この記事にトラックバックを送るには?

寄せられたコメント (全 9 件中、最新 5 件まで表示しています)

Posted by
nn
at
2014/11/29 19:15
ID
EHuNbvsE
TGimpy100 を導入して迷惑コメントが激減しました。ありがとうございました。
ただ,背景に例題のようなランダムドットが表示されないのです。
http://nlogn.ath.cx/archives/001627.html
原因は何だと思われますか。
GD::SecurityImage などを使わなくてもランダムドットは出せるのでしょうか。
Posted by
DayanDayan
at
2008/03/30 10:54
ID
jLc1ogsg
今までのスパムは何だったんだ?というくらい効果覿面。10日以上経っていますが、未だゼロ。
もっとも、普通のコメントも滅多になんですけどね(笑)
次はMT4化をしたいところですが、サーバが非力なせいか、Out of memoryになっちゃうんですよね。
自宅で公開サーバを立てればいいんですけど、それはそれでセキュリティ対策に
腐心しなくてはならなくて。セキュリティ対策するためにサーバ立てるんじゃないぞと^^;;
Posted by
ぴろりぴろり
at
2006/05/17 21:05
ID
mvvasm6g
> 万人向けとはいきませんね、確かに。
まぁ現状で万人向けか?って言われるとそれも疑問なんですけれど、
やはりHTML+テンプレートタグ程度で編集できるのが簡単と思いますね。
> 要はエントリーIDの代わりにハッシュ値を使う点
このハッシュ値を毎回ランダムにすれば、表示される数値は毎回変わりますね。
ただ、そのハッシュが一度きりの使い捨てであることを確実にする仕組みも作らないと
結局今のエントリIDを固定で使っている場合と実質は何も変わらないんですよね…
# うーん、説明下手でスミマセン
それでも毎回同じというのは見た目的に弱そうなので(笑)改善の余地はあると思いました。
Posted by
(o)(o)
at
2006/05/17 20:01
ID
I2kNJVSw
レイアウトの問題は確かにあります。慎重に要素にidを振っておいてCSSで制御するとか、必要な情報をJSONで渡して適当にJavascriptを使ってレンダリングするとか方法はありますが、万人向けとはいきませんね、確かに。
アルゴリズムの方はあまり難しくない感じがしています。例えば、時刻からランダムな文字列を作り、それをMD5でハッシュ化します。次に文字列に対応する画像を作り、ハッシュ値+拡張子という名前にしておきます。すると、CAPTCHA用のフォームはハッシュ値だけを使って作れます。
要はエントリーIDの代わりにハッシュ値を使う点以外はほとんどぴろりさんの方法で行けると思います。
Posted by
ぴろりぴろり
at
2006/05/17 17:36
ID
mvvasm6g
> これらを出力するJavascriptをCGIが返すようにする
フィールドや画像を埋め込む手間を省けると云う点では一理ありますね。
ただ、フィールドや画像のレイアウトを変更したいと思った時に、
テンプレート(実質は HTML)ではなくJavaScripを編集してレイアウト変更するというのは、
多くのユーザにとって敷居が高くなるかな?とも思います。
> 表示ごとにCAPTCHAコードを変えることができる
本当なら堅牢性の面からもこれは目指したいところなんですが…
ページごとに異なる隠しキーをどうやって扱うのか、という所で良い解決策が見えていません。
一応『ショボいけど導入の手間が掛からない』のバランスで言えば、今もアリかなと(笑

コメントを投稿する

 
 (必須, 匿名可, 公開, トリップが使えます)
 (必須, 匿名可, 非公開, Gravatar に対応しています)
 (必須)
スパム コメント防止のため「投稿確認」欄に ランダムな数字 CAPTCHAについて を入力してから送信してください。お手数ですがご協力のほど宜しくお願いいたします。