コメントスパム対策法

近年スパム被害が増えています。
誰でも投稿できるブログや掲示板も狙われています。
ここでは手間のかからない、簡単な対処法をいくつか紹介します。

  • 主な対処法
    • 禁止ワードを設定
    • 日本語が使えない環境からの投稿を拒否
    • 半角英数字のみの投稿を拒否
    • 投稿できるURLの数を制限
    • プロキシサーバ経由の投稿を拒否
    • リファラーを参照してフォームを経由したか判断
    • フォームを表示してから投稿するまでの許容時間を設定する
    • ダミー項目を作り入力があった場合に拒否
    • ワンタイムトークンを埋め込む
    • フォームを解析されない様に、ロボットを排除
    • データ送信先を頻繁に変更
    • Captcha画像認証

検索ロボットを排除

HTML

  1. <meta name="robots" content="none,noindex,nofollow,noarchive" />
  2. <meta name="googlebot" content="noindex,nofollow,noarchive,nosnippet" />
  3. <meta name="libwww-perl" content="none,noindex,nofollow" />

ロボットを完全に排除するのは難しい様ですが、少しは効果があると思います。googlebotのsnippetは検索結果に表示される該当ページからの抜粋です。これがある方がクリック率が高まるそうです。これを削除(nosnippet)するとキャッシュも削除されます。

Googleページ削除

リファラーからフォームを経由したか調べる

PHP

  1. $from = $_SERVER['HTTP_REFERER'];
  2. $host = $_SERVER['HTTP_HOST'];
  3. if (!stristr($from, $host)) {
  4.   print '不正なリファラーです。';
  5. }

リファラーを持たない環境は結構あります。ノートン等のセキュリティソフトによって隠蔽されている可能性もあります。ドコモなど一部携帯でアウト。

逆引き不可能なIPアドレスを拒否

PHP

  1. $ip = $_SERVER['REMOTE_ADDR'];
  2. $host = getHostByAddr($ip);
  3. if ($ip == $host) {
  4.   print '逆引き不可能なIPアドレスです。';
  5. }
  6. // これでも可能
  7. if (!preg_match('/[a-z]/', $host)) {
  8.   print '逆引き不可能なIPアドレスです。';
  9. }

プロキシ経由を拒否

プロキシ特有の環境変数とホスト名を調べる方法です。
環境変数を吐かない匿名プロキシもあって、すべてを検出できる訳ではありません。
他にはプロキシリストを作成したり、ポートスキャンする方法もあります。

PHP

  1. $env = $_SERVER + $_ENV;
  2. $ip = $systems['REMOTE_ADDR'];
  3. $host = getHostByAddr($ip);
  4. // ドコモの携帯はproxyが存在するので注意
  5. // anonym=anonymous,anonymizer
  6. // prox=proxy,proxify
  7. $proxhost = preg_match(
  8.   '/anonym|cache|delegate|firewall|gateway|httpd|keeper|prox|squid|via|www/', $host);
  9. $bool_arr = array(
  10.   isset($env['HTTP_CLIENT_IP']),
  11.   isset($env['HTTP_FORWARDED']),
  12.   isset($env['HTTP_MAX_FORWARS']),
  13.   isset($env['HTTP_PROXY_CONNECTION']),
  14.   isset($env['HTTP_SP_HOST']),
  15.   isset($env['HTTP_TE']),
  16.   isset($env['HTTP_VIA']),
  17.   isset($env['HTTP_X_FORWARDED_FOR']),
  18.   isset($env['HTTP_X_LOCKING']),
  19.   isset($env['HTTP_XONNECTION']),
  20.   isset($env['HTTP_XROXY_CONNECTION'])
  21. );
  22. $proxvar = in_array(TRUE, $bool_arr);
  23. if($proxhost || $proxvar) {
  24.   print 'プロキシ経由です。';
  25. }

ネットワーク総合辞書 - プロクシとは
サイバーシンドローム

その他の変数

PHP

  1. // 使用言語(ja以外のen-US等は不可)
  2. $lang = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
  3. if (!stristr($lang, 'ja')) {
  4.   print '海外からのアクセスです。';
  5. }

PHP

  1. // 接続状況(none,close等は不可)
  2. $conn = $_SERVER['HTTP_CONNECTION'];
  3. if (!stristr($conn, 'Keep-Alive')) {
  4.   print '接続状況が不明です。';
  5. }

これらの方法は携帯では使えない場合が多い。

URL数を制限

PHP

  1. // URLを3つまでに制限する
  2. if (substr_count($message, 'http://') > 3) {
  3.   print 'URLは3つ以下に制限されています。';
  4. }

URLを載せる目的のスパムが多いので効果的。

ひらがなカタカナを含まない投稿を拒否

PHP

  1. if (!mb_ereg('[ぁ-んァ-ン]', $message)) {
  2.   print 'カナが含まれていません。';
  3. }

効果的ですが、鎖国的で残念な方法。

禁止ワードの入力を拒否

PHP

  1. // 投稿されたくないキーワードをカンマ区切りで設定
  2. $spamword = 'アホ,バカ';
  3. // 正規表現に変換
  4. $spamword = preg_quote($spamword);
  5. $spamword = str_replace(',''|', $spamword);
  6. if (mb_eregi($spamword, $message, $matches)) {
  7.   print $matches[0].'が含まれています。';
  8. }

(preg_quoteはShift_JISでは無効)

宣伝書き込み調査中

日本語のスパムが目立ち始めたので、NGワード集を作成してみました。

まとめ

スパムは、フォーム情報をスキャンして一方的に大量に送りつけられます。以前は英語のスパムが殆どで対処も楽でしたが、最近は日本語のスパムも目立つ様になってきました。フォームを探すだけでなく、手動で登録したり、弾かれても内容を変えてリトライさせるスパム生成アプリまで販売されています。

有名なスクリプトや一般的な対処法はすぐに狙われてしまいます。効果的で簡単な対処方法はなかなかありませんが、ちょっとした「ひねり」を加える事で被害を抑える事ができます。例えばフォームを表示してから投稿するまでの時間を計測して短すぎたら拒否するのも賢い手法といえます。また、セッションを活用するのも効果的です。今後良い方法を入手できたら紹介したいと思います。

コメントは受け付けていません。