PukiWikiスパム対策で最強の名をほしいままにしている「spam_filter.php」
今回この素晴らしい機能を導入することにした。
簡単に機能紹介を。
- ngreg 正規表現のNGワードで編集内容に対するフィルタ
- url 内容にURLっぽいものが含まれているかチェック
- atag 内容に</a>や[/url]のようなアンカータグが含まれているかチェック
- onlyeng 内容が半角英数のみ(日本語が入っていない)かチェック
- urlnum 内容に含まれているURLが何個以上かチェック
- ipunknown クライアントのIPが逆引きできるかチェック
- ips25r クライアントのIPが動的IPっぽい(S25Rにマッチする)かチェック 書き込みは普通動的IPからなので、トラックバックスパムの判定に使う
- ipbl クライアントのIPかホスト名がブラックリストに入っているか確認
- ipdnsbl クライアントのIPをDNSBL(公開ブラックリスト)でチェック
- ipcountry クライアントのIPの国がどこかをチェック
- uaunknown HTTP_USER_AGENTが既知(pukiwiki.ini.phpで$agentsで指定)かチェック
- useragent 正規表現によるHTTP_USER_AGENTでのフィルタ
- acceptlanguage 正規表現によるHTTP_ACCEPT_LANGUAGEでのフィルタ
- filename 正規表現による添付ファイル名でのフィルタ
- formname form中に存在しないはずの項目(urlやemailなど)があるかチェック
- urlbl URLがブラックリストに入っているか確認 ただ、ここで標準で入れているURLのブラックリストよりも、本家のスパムフィルタのURLリストのほうが非常によく網羅されているので、そちらのほうが強力です。
- urlcountry URLのサーバのある国がどこかをチェック
- urldnsbl URLがDNSBLに入っているか確認
- urlnsbl URLのNS(ネームサーバ:ドメインの名前を管理しているサーバ)がブラックリストに入っているか確認 NSでブラックリストにしてあるため、ブラックリスト入りしている同じ業者が新しいドメインを取得しても、NSを変更しない限り防げるため、本家のURLブラックリストを使っている場合でも有効です。
- urlnscountry URLのNSの国がどこかをチェック
- akismet Akismetを利用したフィルタ
と、とんでもなく多機能で組み合わせることで実質ほとんどのスパムを防げる。スパムとのイタチごっこは嫌なので、これだけの機能が元からついてると嬉しい限りだ。
が、しかし、今回は「atag」だけを導入して、スパム側の出方を見ることにしたw
続いて当サイトの導入方法
(ちなみに詳しい情報は本家様にあるので参照して欲しい)
1.まずはダウンロード
「美麻Wikiでシステム的に修正している点」にある「spam_filter.php」と「plugin.php.patch」「init.php.patch」さらに1.4.7用パッチ済みファイル群「1.4.7.zip」(PukiWiki Plus!用のファイルなども公開されている)の全部で4つをダウンロード。
2.パッチを適応する
PukiWikiの「lib」ファイル内にある「plugin.php」「init.php」にそれぞれ「plugin.php.patch」「init.php.patch」のパッチを適応する。パッチの当て方は前回の投稿を参照して欲しい。
(1.4.7用パッチ済みファイル群「1.4.7.zip」の中にもパッチを当てたファイルが用意されているが、既にinit.phpなどは編集済みのためどこを更新したか覚えていないので、既にカスタマイズ済みの人はパッチを使うほうが安全に更新できる)
3.ファイルの移動
1.4.7用パッチ済みファイル群「1.4.7.zip」を解凍して「Netフォルダ」「delegated-apnic-latest」「dns_get_ns.cache」をPukiWikiのルートディレクトリへ。「dns_get_ns.cache」は属性を「777」に変更。(ちなみにロリポップだと777は動作しないので755に設定する)
解凍した「lib」フォルダ内にある「file.php」「recaptchalib.php」「akismet.class.php」を「lib」フォルダへ入れる。(file.phpは上書き。これは最終編集者の情報を知るためのパッチを当てたファイル。「前回の更新との差分をクリックすると見ることができる」)
「plugin.php」「init.php」についてはすでにパッチを適応したので今回は上書きしない。
4.pukiwiki.ini.phpにて設定をする
ルートディレクトリにある「pukiwiki.ini.php」に、どのフィルタを適応するか指定する。
define('SPAM_FILTER_COND', '#useragent() or #filename() or #atag() or #ngreg or (#onlyeng() and #urlnum()) or #urlbl() or #urlnsbl()');
こんな風に指定できるが、今回は</a>などの書き込みを規制する「#atag()」だけを導入するので、
// SPAM_FILTER define('SPAM_FILTER_COND', '#atag()');
このような記述を追加した。
5.導入したファイルを全てUTF-8へ変換
このままでは「Shift-JIS」になってるので「秀丸エディタ」などで「UTF-8」に変換する。
以上で通常の使用では問題なく動くはずだ。
さらに今回は「tracker.ini.php」や「recorder.ini.php」のスパムにも対応できるようにしたいので、「spam_filter.php」を開き、それぞれのフィルターの設定を変える。具体的には
define('SPAM_FILTER_URLNUM_PLUGIN_NAME', 'edit,comment,pcomment,article');</pre> ここへ「tracker,recorder」を追加する。 <pre>define('SPAM_FILTER_URLNUM_PLUGIN_NAME', 'tracker,recorder,edit,comment,pcomment,article');
のようにすれば良い。
「spam_filter.php」はフィールド名「msg」だけしか挙動を監視しないため「nameやtextarea」については動作しない。
そのため「#atag()」を例に出すと、
// 内容に</A>や[/URL]のようなアンカータグが含まれているかチェック function atag($reg = SPAM_FILTER_ATAG_REG, $pluginnames = SPAM_FILTER_ATAG_PLUGIN_NAME) { if (!$this->check_plugin($pluginnames)) return FALSE; if (preg_match($reg, $this->post_data['msg'])) { $this->message .= 'atag '; return TRUE; } return FALSE; }
このように記述されているが、
// 内容に</A>や[/URL]のようなアンカータグが含まれているかチェック function atag($reg = SPAM_FILTER_ATAG_REG, $pluginnames = SPAM_FILTER_ATAG_PLUGIN_NAME) { if (!$this->check_plugin($pluginnames)) return FALSE; if (preg_match($reg, $this->post_data['textarea'])) { $this->message .= 'atag '; return TRUE; } if (preg_match($reg, $this->post_data['msg'])) { $this->message .= 'atag '; return TRUE; } return FALSE; }
と、「textarea」用に追記。
以上で、「tracker.ini.php」や「recorder.ini.php」といったプラグインでも動作するように改造完了だ。他のプラグインでも同様に改造できると思われる。
(今回の改造などは素人考えでプログラムをいじってるので、あくまで備忘録として残しておくだけです。)
2014年10月5日追記:table_edit2プラグインでフィルターを有効にする方法
某掲示板で話題になっていたので追記。
英語のみでの投稿を禁止するonlyengフィルターを、全てのテーブルに対して有効にする方法。
この修正をすると、1行でも英語だけの行があるとエラーになる。
spam_filter.php
修正は2点だけ。
71行目辺り、onlyengフィルターにtable_edit2プラグインを追加
//// onlyeng - 内容が半角英数のみ(日本語が入っていない)かチェック define('SPAM_FILTER_ONLYENG_REG', '/\A[!-~\n ]+\Z/'); define('SPAM_FILTER_ONLYENG_PLUGIN_NAME', 'edit,comment,pcomment,article');
↓
//// onlyeng - 内容が半角英数のみ(日本語が入っていない)かチェック define('SPAM_FILTER_ONLYENG_REG', '/\A[!-~\n ]+\Z/'); define('SPAM_FILTER_ONLYENG_PLUGIN_NAME', 'edit,comment,pcomment,article,table_edit2');
291行目辺り、cell◯◯という名前のフィールドに対して全てフィルターを有効にする(◯◯は数字)
if (!$this->check_plugin($pluginnames)) return FALSE;
↓
if (!$this->check_plugin($pluginnames)) return FALSE; $array = $this->post_data; //table_edit2で入力されたデータを配列へ $keys = array_keys($array); //キーを正規表現で検索したいのでいったん取得 $cells = preg_grep('/cell[0-9]+$/',$keys); //cell◯◯の形式のキーを取得 foreach($cells as $cell){ //cell◯◯の形式のキーを持つtable_edit2の配列をループ if (preg_match($reg, $array[$cell])) { //一致した場合フィルターがTRUE $this->message .= 'onlyeng '; return TRUE; } }
何をしているかは解説に書いたので、応用してそれぞれのフィルターを有効にしてください。