OXY NOTES

PukiWikiで日本以外の国からの編集を拒否する方法

鉄壁のガードをすり抜ける、何の意味もないスパム

今までspam_filter.phpを利用してほぼ100%スパムを撲滅できていました。

5年ほど運用していてすり抜けるのは片手で数える程度だったので、適宜IPを登録する程度で運用できていました。

利用していたフィルターの種類

atag() <a>タグの使用禁止
urlbl() 特定のURLを含む投稿を拒否
onlyeng() 英語のみの投稿を拒否
useragent() 特定のユーザーエージェントによる投稿の拒否
ipbl() 特定のIPによる投稿の拒否

しかしここ数日、<a>や特定のURLを含まず、世界中のIPで分散し、実在するユーザーエージェントをランダムで、英語のみなのになぜかonlyeng()フィルターを通過するスパムが数件続きました。

スパムによる投稿

Posts like this make the inetenrt such a treasure trovePosts like this make the inetenrt such a treasure trove
{Posts like this make the inetenrt such a treasure trove}

何の意味があってこんな文字列だけの無意味なスパムを投稿するのか理解に苦しみます。

スパムのログ

IP:192.64.64.114 TIME:"2015-07-07 (火) 04:33:38" REFERER:"http://aqwiki.net/?plugin=areaedit&amp;areaedit_no=0&amp;page=%E3%82%A2%E3%82%AF%E3%82%A2%E3%83%A1%E3%82%A4%E3%82%AF&amp;inline_plugin=1&amp;inline_preview=2&amp;digest=e4cdc6c6594656278545d09847301455" USER_AGENT:"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.111 Safari/537.36"

どうやらareaeditというプラグインのパラメータを利用して投稿しているようです。edit経由で無かったのでフィルターを通過したようです。しかしまた、マニアックな攻撃方法ですね…。

画像認証のreCAPTCHAを導入すれば簡単に遮断できるのですが、入力の手間が増えるのがいただけません。

スパムは99%が外国のIPから投稿され、今回もスロバキアやらウズベキスタンやらと馴染みの薄い国から機械的に投稿されているようです。恐らく世界中にある踏み台のPCやサーバから攻撃をしているものと思われます。
そこでタイトルにもある通り「日本のIPのみ投稿を許可する」ことにしました。

spam_filter.phpにはipcountry()というフィルターが用意されています。こちらは「ブラックリスト形式で登録したカントリーコードの国の編集を禁止する」というものです。
日本以外の国を全て登録するのは面倒なので「ホワイトリスト形式で登録できる」ように変更しました。


カントリーコードを利用してホワイトリスト形式で遮断する方法

まず100行目あたりにあるホワイトリストに登録するカントリーコードを登録します。

define('SPAM_FILTER_IPCOUNTRY_REG', '/(JP)/');

ちなみに編集画面(edit)以外でも有効にしたい場合はSPAM_FILTER_IPCOUNTRY_PLUGIN_NAMEに項目を追加してください。今回の攻撃はareaeditを使ったものだったので忘れず登録しておきます。

define('SPAM_FILTER_IPCOUNTRY_PLUGIN_NAME', 'tracker,recorder,edit,comment,pcomment,article,attach,areaedit');

次に400行目あたりにある「クライアントのIPの国をチェック」のコードを変更します。

// クライアントのIPの国をチェック
function ipcountry($reg = SPAM_FILTER_IPCOUNTRY_REG,
                   $pluginnames = SPAM_FILTER_IPCOUNTRY_PLUGIN_NAME)
{
    if (!$this->check_plugin($pluginnames)) return FALSE;

    // IPが設定されていない場合は調べられないので通す
    // 設定されてない場合は通さないに変更
    if (empty($_SERVER['REMOTE_ADDR'])) return TRUE;

    $country = $this->get_country_code( $_SERVER['REMOTE_ADDR'] );

	// 本来拒否する国のコードを指定するが逆に一致しなかった場合拒否に変更する。
	// あとローカルは許可する ::1
    if (preg_match($reg, $country) or $_SERVER['REMOTE_ADDR'] == "::1") {
		return FALSE;
    } else {
        $this->message .= 'ipcountry ';
        return TRUE;
	}

    return FALSE;
}

変更したのはIPが設定されていない場合は拒否。
続いてget_country_code()で取得したリストに含まれる場合と、ローカル(ローカルで作業する用)は許可。
それ以外の時にフィルター発動。という流れに変更しました。

続いて「APNIC」からget_country_code()で使用するIPとカントリーコードのリストを取得します。

ダウンロードできたら「delegated-apnic-latest」に改名してPukiWikiのルートディレクトリに保存します。

続いてルートディレクトリのpukiwiki.ini.phpで「ipcountry()」の設定を追加します。

define('SPAM_FILTER_COND', '#ipcountry() or #atag() or #urlbl() or #onlyeng() or #useragent() or #ipbl()');

これで日本以外の国からPukiWikiを編集することができなくなりました。