"Shade検索"Wiki

掲示板迷惑投稿対策

「投稿キー方式」を追加
スパム投稿について調べたことをまとめてみました。

他サイトからの投稿を拒否する


有名な掲示板CGIについてはCGIファイル名で検索して、狙ってくるケースが多いようです。
このため、オリジナルのファイル名を違う名前に変更しておくというのが、スパム投稿に対して意外と有効なようです。
ウチは掲示板スクリプトはすべてオリジナル名のままなので、迷惑投稿が多いのかもしれません。

不法投稿の多くは、まともに掲示板にやってきて、その投稿フォームから投稿するのではなく、どこか別のところからデータを送りつけることによって、掲示板CGIに投稿があったと勘違いさせているケースが多いようです。そうしたいわば遠隔投稿を防ぐ方法です。

掲示板設置URL以外からの投稿を拒否する


通常の投稿では、掲示板フォームを表示するCGIファイルがリンク元となるはずなのですが、
スパム投稿のリンク元を調べてみると、他のサイトに設置された不法投稿CGIらしきものから投稿されているケースがありました。
また、リンク元を残していない書き込みもありましたが、ブラウザ以外(不法投稿専用のソフト?)からの投稿なのかもしれません。
こうしたことから、リンク元が本来の掲示板CGIが設置されているURL以外になっている場合、投稿を拒否するという方法があります。
WEB上で公開されているCGIスクリプトでも、この方法で他のサイトからの投稿を拒否できるものもあるようなので、
これは有効にしておいた方がいいでしょう。

投稿フォームから隠しデータを送る


リンク元を掲示板設置URLと偽って投稿してくるケースもあるようです。その場合は
投稿フォームのinputタグに"hidden"を指定して、隠しデータを送るようにした上で、そのデータを送ってこない送信については他サイトからの投稿と見なしてブロックする。という方法があるようです。
具体的には投稿フォームを

 <form action="○○.cgi" method="post">
 <input type="hidden" name="hid" valu="abcde">
 ・
 ・
 </form>

のようにして、ログ書き込みの前に

 if ($FORM{'hid'} ne 'abcde') {
     #投稿拒否処理
 }

のような処理で拒否するといった感じです。$FORM{'hid'}は、フォームから送られてきたデータを格納しておくハッシュで、掲示板CGIによって違うと思います。

これはHTMLのソースを見ればどのようなデータを送っているかすぐわかるので、それほど強力なものではありませんが、わざわざ投稿フォームのソースまで調べないだろうなと思っていたら、明らかに他のサイトからの投稿の様なのに、ちゃんと隠しデータも送ってきているというケースもありました。
人力で調べているとは思えないので、不法投稿ツールにHTMLのソースを読んで、INPUTタグでvalueが指定されているものについては、そのまま送るといった機能があるのかもしれません。

上記2つの他サイトからの投稿拒否対策もかいくぐって投稿してくるケースもあります。

英文のみの投稿を拒否する


で、いまのところウチで一番投稿拒否の成功率が高いのは、英文チェックです。
ウチの掲示板は今のところ、海外のユーザーからの投稿はないので、コメントがすべて英文のみの場合は拒否するようにしています。
ちゃんとした方法なのかどうかわかりませんが、ウチではjcode.plの文字コード取得関数を使っています。
投稿されて、書き込まれるコメントが$comentだとすると、

$code = &jcode::getcode(\$coment);

でコメントの文字コードが得られます。この文字コードの種類は'jis'か'sjis'か'euc'ですが、
文字列に日本語が含まれていないと、いずれも返しません。これを利用して、CGIスクリプトがsjisを使っているなら、

 if ($code ne 'sjis') {
     # 投稿拒否処理
 }

の様にして、英文のみのコメントの投稿を拒否します。
スクリプトの文字コードがわからなかったら、

 if ($code ne 'jis' && $code ne 'sjis' && $code ne 'euc') {
     # 投稿拒否処理
 }

とでもしておけばいいと思います。
この方法はjcode.plを使っているCGIなら、使えるはずです。
いろいろな隙をねらって投稿しようとしても、日本語が含まれていなければ無条件で拒否するので、確実な方法といえるかもしれません。ただし、1文字でもどこかに日本語が含まれていれば、投稿できてしまいます。そのような対策を施したスパム投稿も出てくるかもしれません。
・・・と書いていたら、本当に出てきました。急にそのような投稿が増えたというほどではないので、英文拒否をすり抜けるためではなく、たまたま文字化けしてしまったということかもしれませんが、そのようなケースでもURL羅列している場合が多いので、その拒否も追加しました。

URLの羅列を拒否


http://www2u.biglobe.ne.jp/k_hiray/ps_db/search/
http://www2u.biglobe.ne.jp/k_hiray/ps_db/search/
http://www2u.biglobe.ne.jp/k_hiray/ps_db/search/
http://www2u.biglobe.ne.jp/k_hiray/ps_db/search/

のように、URLをたくさん羅列した投稿を拒否する方法です。
最近は、こうした拒否処理を設定できるような掲示板CGIも増えてきたようです。
コメント内容が$commentとすると、

 $url_num = ($comment =~ s/http/http/g);

で、$comment中に含まれる"http"という文字列の数が$url_numに代入されます。
$comment =~ s/http/http/gは、$commentという文字列中の"http"という文字を"http"という文字で置き換えるという処理ですが、この式は置き換えた回数を返すので、$commentの中身を変えずに含まれる"http"の数が得られることになります。
通常の投稿では2つか3つぐらいURLを入れられれば十分だと思うので、

 if ($urlnum >= 4) {
     # 拒否処理
 }

として、"http"という文字が4つ以上コメントに含まれる投稿を拒否します。


本来の投稿フォームから投稿される迷惑投稿については、地道にIPアドレスや禁止ワードで
プロテクトするしかないかもしれません。

前科のあるIPアドレスを拒否する


IPアドレスでプロテクトする場合は、通常のログにもIPアドレスを記録しておく必要があります。
スパム投稿されてしまった場合、そのログからIPアドレスを調べ、次回からそのIPアドレスからの
投稿は拒否するということになります。IPアドレスは.でつながれた4つの数字ですが、
ダイヤルアップなどの場合は、一番右端の数字は変わります。
なので、左3つの数字を含むIPアドレスを全部はじきたいところですが、そうすると
同じプロバイダの善良な投稿者もブロックしてしまう恐れがあります。
また、同じようなスパム投稿でも、プロキシサーバをいろいろ変更しているのか、
毎回IPアドレスを変更して投稿してくるケースもあるので、IPアドレスによるプロテクトは、
手間の割りには今いち効果が期待できないかもしれません。

禁止ワードを含む投稿を拒否する


投稿フォームから投稿される迷惑投稿を防ぐのは、やはり禁止ワードかもしれません。あらかじめ予想される禁止ワードのほかに、迷惑投稿に共通して含まれ、善良なユーザは余り使わないような単語を禁止ワードとし、コメントや題名にその単語が含まれていたら拒否するということになります。共通して書き込まれるURLなどがあったら、それも禁止ワードにすることもできます。
ウチの場合は、'完全無料','風俗','出会い','自由恋愛','副収入','精力剤','逆援助','ホスト会員','女性会員'などを禁止ワードにしています。

禁止ワードを含む投稿を拒否する設定ができる掲示板CGIもあるようですが、
ない場合は、禁止ワードを

 @reject_word = {'完全無料','風俗','出会い'};

の様にして指定した上で、投稿された内容をログファイルに書き込む前に

 foreach (@reject_word) {
     if (index($comment, $_) >= 0 || index($subj, $_) >= 0) {
         # 投稿拒否処理
     }
 }

のようにして、拒否します。$commentはコメント、$subjは題名です。
正規表現を使ってもいいと思います。

その他


想定されたデータ以外の送信を防ぐには、フォームのメソッドをpostに限定するという方法があります。これはURLからデータを送る方法を拒否することによって、フォームから送られると想定されてデータ以外を送られるのを拒否しようというものです。
WEB上で公開されている掲示板CGIでも、メソッドを選択できるものがありますが、メソッドをpostにしても、フォームのメソッドだけがpostになるだけで、URLからのデータ送信ができるものもあるようです。
post以外の送信を拒否するには、送信されたデータをデコードする際に$ENV{'QUERY_STRING'}は無視するとか、$ENV{'REQUEST_METHOD'}がpostでなければ、拒否するといった処理が必要になります。

投稿拒否処理

ログ書き込み中断


迷惑投稿と判断された場合は、ログ書き込みをやめて、スクリプトの実行を中断することになります。掲示板CGIの多くはエラー関数が用意されていると思うので、これを使うといいでしょう。たとえば、sub error というエラー関数があるCGIの場合、

 &error('不正な投稿です。');

というような感じでしょう。エラー関数の引数を2個入れるような場合は、
&error('ERROR!','不正な投稿です。');
のように書く場合もあるかもしれません。掲示板CGIの他の部分で使われているエラー関数の呼び出し方を参考にして書けば間違いないと思います。

不法投稿のログを残す


これで、投稿を拒否することができるはずですが、念のため不法投稿のログも取っておいた方がいいでしょう。今後の不法投稿対策のための資料になるし、万一善良な投稿者の書き込みをブロックしてしまった場合に、そのログから書き込みを復活させることができます。そのためには通常の掲示板ログの共通のフォーマットにしておいた方がやりやすいでしょう。たとえば、通常の掲示板のログの書式が
$number<>$date<>$name<>$email<>$subj<>$comment<>$url
だとしたら、

 open(OUT,">> reject.cgi")
 print OUT "$number<>$date<>$name<>$email<>$subj<>$comment<>$url\n";
 close(OUT);
 &error("現在書き込みできません。");

のようにして、不法投稿のログを残してから、正規のログへ書き込む前にスクリプトを中断することができます。不法投稿があるたびにreject.cgiという名前のファイルに追加書き込みすることになります。拡張子を.cgiにしているのは、WEBブラウザで内容を閲覧されるのを防ぐためです。
不法投稿のログの場合、さらに$ENV{'REMOTE_HOST'} (IPアドレス)、リンク元($ENV{"HTTP_REFERER"})なども記録しておくために、printの行は

 print OUT "$number<>$date<>$name<>$email<>$subj<>$comment<>$url<>$ENV{'REMOTE_HOST'}<>$ENV{"HTTP_REFERER"}\n";

のようにしておくといいかもしれません。

また、ブロックするごとにメールを送信するようにしておくと、いちいちFTPソフトでreject.cgiファイルをダウンロードしなくても不法投稿があったことを知ることができます。掲示板CGIには、メール送信関数が用意されているものもあるので、それを利用すれば簡単な改造ですむと思います。



5198


>>2010/01/25 01:27:00更新>>