ZAPAnet総合情報局 > ZAPAブログ2.0 > Nucleusにもスパムコメントが!

Nucleusにもスパムコメントが!

2006年05月07日 プログラミングTIPS
F-boardのスパム対策を施した矢先、今度はこのブログのシステムNucleusにもスパムコメントが飛んできました。

早速対策を施しましたので、メモを残しておきます。

今回のスパムの特徴は、
・投稿者のHNが日本語ではない
・投稿内容が英語でどこかのサイトへのURLが書かれている
・投稿時のIPアドレスが毎回異なる
・継続的だが不規則な投稿サイクル
だったため、
・半角のみの投稿制限
・複数URLの書き込み制限
・禁止語句制限
など、いろいろと改善方法を取ることができましたが、今回取ったのはとても簡単な方法で、「投稿前のチェックボックスを一つ追加」しただけです。(F-boardのスパム対策と同じ方法です)
チェックボックスにチェックが入っていないとエラーになって投稿できないようにしました。
スパムのスクリプトはわざわざうちのサイトに設置してあるコメントフォームの特徴までは捉えていないはずと考え、この方法にしました。

もしダメなら、
・投稿前にランダムに文字列画像を生成して、その文字列を投稿者に入力してもらう
・投稿前に「ひらがな文字」を入力してもらう
方法などを考えています。

この機能を実現するためには、本当はNucleusのプラグインとして作成した方が良いのかもしれませんが、プラグインの作り方をよく知らないのでコアファイルの方をいじりました。変更したのは、以下の4ファイルです。

・COMMENTS.php
・japanese-euc.php
・commentform-notloggedin.template
・commentform-loggedin.template

まず、コメントフォームから投稿されたときにチェックボックスがチェックされているか確認するために、nucleus/libs/COMMENTS.phpに赤字の部分を追加しました。
チェックボックスがチェックされていないときには、エラーメッセージを出力するようにしています。
COMMENTS.php (nucleus/libs/)

function addComment($timestamp, $comment) {
global $CONF, $member, $manager;

$blogid = getBlogIDFromItemID($this->itemid);

$settings =& $manager->getBlog($blogid);
$settings->readSettings();

if (!$settings->commentsEnabled())
return _ERROR_COMMENTS_DISABLED;

if (!$settings->isPublic() && !$member->isLoggedIn())
return _ERROR_COMMENTS_NONPUBLIC;

if($_POST['zcheck'] != 1)
return _ERROR_COMMENTS_NOCHECK;


// member name protection
if ($CONF['ProtectMemNames'] && !$member->isLoggedIn() && MEMBER::isNameProtected($comment['user']))
return _ERROR_COMMENTS_MEMBERNICK;

続いて、チェックボックスがチェックされていないときのエラーメッセージ内容の設定です。
nucleus/language/japanese-euc.php(EUC版を使っているので)に、以下の赤字の定義をします。
japanese-euc.php (nucleus/language/)

// errors
define('_ERROR_COMMENT_LONGWORD', 'コメントには半角で90文字以上の語を使わないで下さい');
define('_ERROR_COMMENT_NOCOMMENT', 'コメントを入力してください');
define('_ERROR_COMMENT_NOUSERNAME', '正しくないユーザ名です');
define('_ERROR_COMMENT_TOOLONG', 'コメントが長すぎます(半角で5000文字まで)');
define('_ERROR_COMMENTS_DISABLED', 'このBlogへのコメントは現在使用できません');
define('_ERROR_COMMENTS_NONPUBLIC', 'このBlogへコメントを追加するにはメンバーとしてログインしなければいけません');
define('_ERROR_COMMENTS_MEMBERNICK','あなたが使おうとした名前は既に使われています。他の名前を選んでください。');
define('_ERROR_COMMENTS_NOCHECK','チェックボックスがチェックされていません。チェックしてから投稿してください。');
define('_ERROR_SKIN', 'スキン エラー');
define('_ERROR_ITEMCLOSED', 'この記事へコメントすることはできません。');

最後に、投稿フォームにチェックボックスを一つ追加します。
ログインしているメンバーとログインしていないメンバー用に二つのファイルを修正します。
nucleus/forms/commentform-notloggedin.template、commentform-loggedin.templateに赤字の部分を追加しました。("zcheck"の名前に関しては、自分の好きな名前で構いませんが、変更する場合にはCOMMENTS.phpの方も変更します)
commentform-notloggedin.template (nucleus/forms/)

<br />
<input type="checkbox" value="1" name="remember" id="nucleus_cf_remember" <%formdata(rememberchecked)%> /><label for="nucleus_cf_remember"><%text(_COMMENTFORM_REMEMBER)%></label>
<br />
<input type="checkbox" name="zcheck" value="1">←上記投稿内容を確認したら、ここをチェックしてください。
<br />

<input type="submit" value="<%text(_COMMENTFORM_SUBMIT)%>" class="formbutton" />
</div>
commentform-loggedin.template (nucleus/forms/)

<a id="nucleus_cf"></a>
<form method="post" action="#nucleus_cf">
<div class="commentform">
<%errordiv%>

<input type="hidden" name="action" value="addcomment" />
<input type="hidden" name="url" value="<%formdata(destinationurl)%>" />
<input type="hidden" name="itemid" value="<%itemid%>" />
<label for="nucleus_cf_body"><%text(_COMMENTFORM_COMMENT)%></label>:
<br />
<textarea name="body" class="formfield" cols="70" rows="10" id="nucleus_cf_body"><%formdata(body)%></textarea>
<br />
<%text(_COMMENTFORM_YOUARE)%> <%formdata(membername)%>
<small>(<a href="?action=logout"><%text(_LOGOUT)%></a>)</small>
<br />
<input type="checkbox" name="zcheck" value="1"> ←投稿内容を確認したらチェックしてください。
<br />

<input type="submit" value="<%text(_COMMENTFORM_SUBMIT)%>" class="formbutton" />
<%callback(FormExtra,commentform-loggedin)%>
</div>
</form>


これで、チェックボックスがチェックされていない投稿は投稿できないようになりました。
もし何か不具合を発見したら連絡いただけると助かります。

スパムコメントが無くならないようであれば、次の対策を施したいと思います。