2003年11月03日

コメントスパム対策

やっぱりコメントスパムが流行っているようですねぇ・・・

ベイズフィルタは積んでみましたがそれでも機械的にspamが送られてくるのはなんだかいやな感じがしてならないのでもう一枚対策を入れてみました。

方法を簡単に説明すると、コメント投稿用のフォームをスパム投稿ボットが認識できないようにする方法で、具体的にはフォームのオブジェクトの名前をアクセスIPごとのハッシュにすることでオブジェクト名を決め打ちでpostしてくるボットは完全にはじけます。
また、フォームの順番でメッセージを入れてくるボットもあるかもしれませんが、その場合、テンプレートでダミーを用意したり順番を入れ替えれば人間の手が入らない限りは100%はじけます。
ただ、この方法だとコメントの入力には必ず別ウィンドウを開く必要がありますし、ケースによってはspamされる可能性もありますので、実装する際はよく検討してから行ってください。

(というかいじる範囲が広くて実装する人はたぶん居ないと思うので自分用メモとして残しておきます(^^;)

まずperlでDigest::MD5が使える必要があります。
よくわからない人はサーバー管理者に問い合わせるか、サーバ管理者なら

# perl -MCPAN -e shell
cpan> install Digest
とかしてください。

さてそれがOKならソースファイルを二つ改造します。
もちろん失敗しても良いように作業前には必ず元のソースをコピーしておいてください。

追加するところが多いので、diffの結果そのまま掲載

MovableType Version 2.64 日本語化済 lib/MT/App/Comments.pm
13a14,16
> use Digest::MD5 qw(md5_hex);
> my $MyUniqMsg = '適当な単語を入れてください';
> 
38a42
> 
67a72,77
> 
>     my $hauthor = "a".md5_hex("$entry_id"."$MyUniqMsg"."Name"."$user_ip");
>     my $hemail = "a".md5_hex("$entry_id"."$MyUniqMsg"."Email"."$user_ip");
>     my $hurl = "a".md5_hex("$entry_id"."$MyUniqMsg"."Url"."$user_ip");
>     my $htext = "a".md5_hex("$entry_id"."$MyUniqMsg"."Comment"."$user_ip");
> 
71c81
<         (!$q->param('author') || !$q->param('email'))) {
---
>         (!$q->param($hauthor) || !$q->param($hemail))) {
75c85
<     if (!$q->param('text')) {
---
>     if (!$q->param($htext)) {
82,83c92,93
<     $comment->author(remove_html(scalar $q->param('author')));
<     my $email = $q->param('email') || '';
---
>     $comment->author(remove_html(scalar $q->param($hauthor)));
>     my $email = $q->param($hemail) || '';
94c104
<     my $url = $q->param('url') || '';
---
>     my $url = $q->param($hurl) || '';
105c115
<     $comment->text($q->param('text'));
---
>     $comment->text($q->param($htext));
209,210c219,230
<     for my $f (qw( entry_id author email url text )) {
<         $comment->$f(scalar $q->param($f));
---
> 
>     my $user_ip = $app->remote_ip;
>     my $hauthor = "a".md5_hex("$entry_id"."$MyUniqMsg"."Name"."$user_ip");
>     my $hemail = "a".md5_hex("$entry_id"."$MyUniqMsg"."Email"."$user_ip");
>     my $hurl = "a".md5_hex("$entry_id"."$MyUniqMsg"."Url"."$user_ip");
>     my $htext = "a".md5_hex("$entry_id"."$MyUniqMsg"."Comment"."$user_ip");
> 
>     my @msgarr = qw( entry_id author email url text );
>     my $count = 0;
>     for my $f ('entry_id',"$hauthor","$hemail","$hurl","$htext") {
>         my $ff = shift @msgarr;
>         $comment->$ff(scalar $q->param($f));
もう一つ
MovableType Version 2.64 日本語化済 lib/MT/Template/Context.pm
19a20,22
> use Digest::MD5 qw(md5_hex);
> my $MyUniqMsg = '適当な単語(ただし上のと同じもの)を入れてください';
> 
217a221,226
> 
>     $ctx->register_handler(NamTagHdn => \&_hdlr_entry_nam_tag_hidn);
>     $ctx->register_handler(EmlTagHdn => \&_hdlr_entry_eml_tag_hidn);
>     $ctx->register_handler(UrlTagHdn => \&_hdlr_entry_url_tag_hidn);
>     $ctx->register_handler(CmtTagHdn => \&_hdlr_entry_cmt_tag_hidn);
> 
848a861,884
> }
> sub _hdlr_entry_nam_tag_hidn {
>     my $args = $_[1];
>     my $e = $_[0]->stash('entry')
>         or return $_[0]->_no_entry_error('MTNamTagHdn');
>     "a".md5_hex(sprintf("%d", $e->id)."$MyUniqMsg"."Name"."$ENV{'REMOTE_ADDR'}");
> }
> sub _hdlr_entry_eml_tag_hidn {
>     my $args = $_[1];
>     my $e = $_[0]->stash('entry')
>         or return $_[0]->_no_entry_error('MTEmlTagHdn');
>     "a".md5_hex(sprintf("%d", $e->id)."$MyUniqMsg"."Email"."$ENV{'REMOTE_ADDR'}");
> }
> sub _hdlr_entry_url_tag_hidn {
>     my $args = $_[1];
>     my $e = $_[0]->stash('entry')
>         or return $_[0]->_no_entry_error('MTUrlTagHdn');
>     "a".md5_hex(sprintf("%d", $e->id)."$MyUniqMsg"."Url"."$ENV{'REMOTE_ADDR'}");
> }
> sub _hdlr_entry_cmt_tag_hidn {
>     my $args = $_[1];
>     my $e = $_[0]->stash('entry')
>         or return $_[0]->_no_entry_error('MTCmtTagHdn');
>     "a".md5_hex(sprintf("%d", $e->id)."$MyUniqMsg"."Comment"."$ENV{'REMOTE_ADDR'}");
これで<$MTNamTagHdn$> <$MTEmlTagHdn$> <$MTUrlTagHdn$> <$MTCmtTagHdn$>という4つのタグがテンプレートで使えるようになったので次にテンプレートを4つ書き換えます。
なお、必ず、テンプレートのバックアップを事前にとっておくようにしてください。

とりあえず、私が使っているテンプレートをそのまま乗せておきます。
(右クリックから「対象をファイルに保存」でダウンロードしてください)

これで一度完全リビルドをかけて、ちゃんと投稿できれば作業完了です。

なお、この方法では同じエントリに連投された場合には効果ありませんのであしからず。
(あくまで流行のスパムボット対策ですし)

というか、誰かTrackBackスパムへの有効な方法知りませんか?<やられるとコメントの数倍対応が難しそうなんですが・・・

2.661用のパッチはこちら

Posted by Takuchan at 2003年11月03日 00:01 | トラックバック(1)