* 同一spamを投稿されにくくする工夫 [#i5ea33e9]

- ページ: [[BugTrack2]]
- 投稿者: [[teanan]]
- 優先順位: 普通
- 状態: 提案
- カテゴリー: プラグイン
- 投稿日: 2007-10-06 (土) 11:13:23
- バージョン: 

** メッセージ [#jcf07afd]
同じ内容のコメントspamをたくさんのページに投稿される場合があります。現状のcommentプラグインは無防備ですので、spam投稿のコスト(投稿者の手間)を少しでも高くするための工夫を施しましょう。

** パッチ [#x0d1fc85]
PukiWiki-1.4.7_notb(comment.inc.php v1.36)からの差分です。

 --- comment.inc.php.orig	Sat Jan 28 23:54:51 2006
 +++ comment.inc.php	Sat Oct 06 10:48:42 2007
 @@ -18,6 +18,8 @@
  define('PLUGIN_COMMENT_FORMAT_NOW',  '&new{$now};');
  define('PLUGIN_COMMENT_FORMAT_STRING', "\x08MSG\x08 -- \x08NAME\x08 \x08NOW\x08");
  
 +define('PLUGIN_COMMENT_MIXTURE', 'comment_mixture');
 +
  function plugin_comment_action()
  {
  	global $script, $vars, $now, $_title_updated, $_no_name;
 @@ -51,9 +53,11 @@
   	$postdata    = '';
  	$comment_no  = 0;
  	$above       = (isset($vars['above']) && $vars['above'] == '1');
 +	$hash        = isset($vars['hash'])? $vars['hash'] : '';
  	foreach (get_source($vars['refer']) as $line) {
 		if (! $above) $postdata .= $line;
 -		if (preg_match('/^#comment/i', $line) && $comment_no++ == $vars['comment_no']) {
 +		$check = plugin_comment_gethash($vars['refer'], $comment_no);
 +		if (preg_match('/^#comment/i', $line) && $comment_no++ == $vars['comment_no'] && $hash === $check) {
 			if ($above) {
 				$postdata = rtrim($postdata) . "\n" .
 					$comment . "\n" .
 @@ -93,6 +97,7 @@
  
  	if (! isset($numbers[$vars['page']])) $numbers[$vars['page']] = 0;
  	$comment_no = $numbers[$vars['page']]++;
 +	$hash = plugin_comment_gethash($vars['page'], $comment_no);
  
  	$options = func_num_args() ? func_get_args() : array();
  	if (in_array('noname', $options)) {
 @@ -118,6 +123,7 @@
    <input type="hidden" name="plugin" value="comment" />
    <input type="hidden" name="refer"  value="$s_page" />
    <input type="hidden" name="comment_no" value="$comment_no" />
 +  <input type="hidden" name="hash"   value="$hash" />
    <input type="hidden" name="nodate" value="$nodate" />
    <input type="hidden" name="above"  value="$above" />
    <input type="hidden" name="digest" value="$digest" />
 @@ -130,4 +136,12 @@
  
  	return $string;
  }
 +
 +function plugin_comment_gethash($page, $comment_no)
 +{
 +	global $page_title;
 +	return md5($page_title . $page . $comment_no . $_SERVER['REMOTE_ADDR'] .
 +			PLUGIN_COMMENT_MIXTURE);
 +}
 +
  ?>

** 仕組み [#q86e5046]
- commentプラグインによる入力フォームを表示する際、"hash"にページ名やREMOTE_ADDR等から導き出す md5 のハッシュ値を指定します。
- コメントが投稿された場合、指定されたhashが正しいものかをチェックします。不一致であれば、コメント挿入の処理を行いません。

** ポイント [#w8cb7ea9]
- spam発信者が同一雛型を使って、複数ページへ投稿することをブロックする
-- 発信者が複数ページへ投稿するためには、全てのコメントフォームごとに異なった hash を指定する必要があります。
-- hash は REMOTE_ADDR を含んでいるため、IPを切り替えて投稿してくるようなspam発信者は、その度に hash を更新する必要があります。

- spamが投稿されるようになった場合、簡単に対処したい
-- hash の生成には、commentプラグインで共通の混ぜ物('PLUGIN_COMMENT_MIXTURE')を入れてありますので、spamが来るようになった場合、この定義を変更するだけで対処することができます。

--------
- お疲れ様です。戦略も付記いただきたいのですが、これはあらかじめ comment form を与える過程でクライアントに "クライアントごとの REMOTE_ADDR と、サイトの秘密の文字列などから生成した hash" を渡しておいて、それを含んだ HTTP POST のみ許可する といったものでしょうか。異なるIPから渡してきたり、複数のIPから渡してくる奇妙なPOSTはブロックされます。また hash はページ名も含んでいるので、異なるページから生成したひな型もブロックされます。  -- [[henoheno]] &new{2007-10-06 (土) 21:41:18};
-- 戦略上の欠点として、事前に REMOTE_ADDR ごとに異なる内容の通常コンテンツを与えておく必要があります。これがproxyサーバーのキャッシュを汚してしまうので、(HTTPで)proxyサーバーにコンテンツを覚えないよう伝える必要があるでしょう。 -- [[henoheno]] &new{2007-10-06 (土) 21:46:07};
-- なお、MD5 hash は数字列になりうるので、$hash === $check として型も区別させないと、意図に反して true を返す可能性が生じますです (See [[BugTrack2/236]]) -- [[henoheno]] &new{2007-10-06 (土) 21:47:27};
--- ご指摘のとおりです、ありがとうございます。パッチ修正しておきます (^^; -- [[teanan]] &new{2007-10-06 (土) 22:07:28};
-- 説明不足で申し訳ありません。簡単ですが、仕組みとポイントを列挙いたしました。Proxyが効かなくなるのも、問題になるかもしれませんね… -- [[teanan]] &new{2007-10-06 (土) 22:28:40};
-- いえこちらの反応が早すぎたのでしょう (^^; -- [[henoheno]] &new{2007-10-06 (土) 23:39:22};
- Proxyサーバーについては、REMOTE_ADDRがProxyサーバーのアドレスになるため、問題ないような気がします。 -- [[teanan]] &new{2007-10-07 (日) 11:39:36};
-- うほ、そうかもしれない。このhashに何を含めるかで色々条件が変わりますね XD -- [[henoheno]] &new{2007-10-07 (日) 22:16:57};
- 文字を連結する値の区切りが空文字列の場合、意図しないhashの一致が起こる可能性が生じます(例として "ABC" + "" 、"AB" + "C"、 "A" + "BC"、"" + "ABC" の答えはどれも同じなので、hash値は全て同一)。\0とか md5() はどう扱ったかなぁー -- [[henoheno]] &new{2007-10-08 (月) 22:10:42};
- おっと、今のままではspam投稿で無変更で更新されてしまいます。素直にexitしたほうが良いかも。 -- [[teanan]] &new{2007-10-09 (火) 19:00:18};
-- ブロックしたコンテンツは、「spamとして分析して、状況をメール通知してからexit()なりブロック通知」する流れに乗せていただけるイメージでやっていただけると、他の機構と連携できるのでありがたいです :) 変なpostをしてきたIPを記憶しておいてから継続的にブロックとかする道に繋がります。Unixの世界における梃子の原理とかいう奴ですね -- [[henoheno]] &new{2007-10-09 (火) 22:19:51};

#comment

** 投稿チェック処理の汎用化と特化 [#n7444014]
- 汎用化: この件、comment番号にこだわらなければ、commentプラグインに限らないあらゆるformに(強制挿入することで)適用できる気がします。強制挿入については、現在の手法が好ましいとは思いませんが既に encode_hint がやっています。そうした汎用hashのチェックはプラグインに渡る前に処理できます -- [[henoheno]] &new{2007-10-07 (日) 23:15:54};
-- 特化: プラグインごとにさらに厳しくチェックしたい場合、そうしたhashを関数で取得できるようにしておいて、各プラグインが独自に comment 番号などをmixした別のhashを生成する形にすれば両立できそうです -- [[henoheno]] &new{2007-10-07 (日) 23:18:05};
-- 各プラグインが独自に付加するものと、encode_hintのように自動付加するものが混在する場合、hashのチェック処理が簡単に出来なさそうな気がします。自動付加とプラグインによる付加を区別できるよう、別の名前で値を渡せば何とかなるかもしれませんが、重複するかもしれませんね・・・ -- [[teanan]] &new{2007-10-08 (月) 13:08:28};
-- もしくは、プラグインの呼び出し処理で plugin_***_gethash() をインタフェース関数として共通で定義し、その関数が存在する場合はプラグイン側の処理を呼ぶようにすると、うまくいくかもしれません。 -- [[teanan]] &new{2007-10-08 (月) 13:12:36};
- formの中に収める hidden の名称が "hash" となっているのが、既存の何かの名称とぶつかるかもしれない件については、いずれにせよ固有の名称にした方が良いのでしょう。この機能が一体何/どんな目的なのかを一言で表したのが多分望ましいんですが、teananさん的にはどんな形になるでしょう。その答えは多分このBugTrackのタイトルにも「○○する工夫」とか「~のために○○する」みたいに結実して行くと思うのです -- [[henoheno]] &new{2007-10-08 (月) 22:07:05};
-- 上手く説明できなくて申し訳ありません、ちょっと違います。既存の何かと重複するのではなく、プラグイン毎にさらに厳しくチェックしたい場合、そうではないフォームに対しencode_hintのような方式で hashを付けたとします。データがpostされた際、そのhashの正当性を確認する処理がうまく書けるか、ということです。 -- [[teanan]] &new{2007-10-09 (火) 19:10:42};
-- 解決方法としては、おそらくhenohenoさんと認識は同じで、「そうしたhashを関数で取得できるように」、plugin_***_gethash()のようなインタフェース関数をプラグインに設けるとうまくいきそうです。 :) -- [[teanan]] &new{2007-10-09 (火) 19:20:04};

#comment

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Site admin: PukiWiki Development Team

PukiWiki 1.5.4+ © 2001-2022 PukiWiki Development Team. Powered by PHP 8.2.12. HTML convert time: 0.138 sec.

SourceForge