多重投稿を防止するには?

[上に] [前に] [次に]
きょーこ [E-Mail] 1998/03/07(土) 19:39:03
掲示板に、ある特定の人達が同一内容を連続的に書き込みをして、元のメッセージがページ外へ押し出されてしまい困っています。そこで同一アドレスからは一定時間を置かないと書き込みできないようにしたいのですが、それは可能ですか。もしそうならば具体的な方法が知りたいのですが。

B-Cus 1998/03/08(日) 02:37:20
$message に本文が入っているとします。

# $prev_message に前回の書き込み内容を読み込む
$prev_message = "";
open(IN,"prev-message.dat");
while (<IN>){ $prev_message .= $_; }
close(IN);

if ( $prev_message eq $message ){
 print "二度書きです。"\n;
 終了処理
}

二度書きではないので、書き込み処理を行う。

# 今回書き込まれた内容を prev-message.dat に保存
open(OUT,">prev-message.dat");
print OUT $message;
close(OUT);

ってなところでしょうか。ただし改行の扱いなど、
(<BR>をつけるかどうか。一つの書き込みに対して
 一行で保存するかどうか)は実際のスクリプトに即して
変更してください。


また、1つの書き込みがとても大きいなら、MD5などの
メッセージ要約関数(2つの異なる文字列をMD5に通すと、
MD5の出力も異なる結果になる。特にMD5の結果が同じに
なる文字列を見つけるのは事実上不可能)を通して、
その結果を照合すれば前回と同じ書き込みかどうか
チェックできます。

また、MD5なら1件あたりの文字列の長さが短いので、
過去100件をチェック、っていうことも簡単でしょう。

$md5 = `/usr/bin/md5 $message`;

あるいは

$md5 = `/usr/bin/md5sum $message`;

あたりかな?

miyasiro 1998/03/08(日) 05:52:22
これって、イタズラ防止ですよね。先に書き込んだ人のリモート・ホスト(REMOTE_ADDR)やブラウザ(HTTP_USER_AGENT)の情報から、同一人と思われる人(cookie を使えれば確実なんだろうけど、受け入れないように設定されれば終わり?)の一定時間内の再書き込みを禁止しようということだと思ったのですが…
B-Cus さんの方法では、1回ごとに本文に例えば改行を1個ずつ増やすだけでも書き込めちゃうと思うのですが、それでも十分には面倒な作業になるのかな? それともこういうイタズラはオートでやるものなのでしょうか…にしても、書き込みの度にメッセージを少しずつ変化させるくらいの変更は簡単にできそうな気もします。
(MD5ってなんだろう? 固定長の文字列を返すhash関数みたいなものなのかな…)

B-Cus 1998/03/08(日) 06:07:23
> これって、イタズラ防止ですよね。先に書き込んだ人のリモート・
> ホスト(REMOTE_ADDR)やブラウザ(HTTP_USER_AGENT)の情報から、
> 同一人と思われる人(cookie を使えれば確実なんだろうけど、
> 受け入れないように設定されれば終わり?)の一定時間内の再
> 書き込みを禁止しようということだと思ったのですが…

僕もそういうつもりでいたずら防止策として書き込みました。
ただ本気でやろうとしたら、外部からアクセス可能なproxyの
リストを用意してそれらを順に使ったり、HTTP_USER_AGENT
はクライアント側が勝手に用意できる文字列だから、適当な
文字列を使ったり、もちろん本文だって毎回違うものにしたり、、、

やろうと思えばどれだけでも手の込んだことができるんで、
根本的には対応策はないといっていいでしょう。それでも
書き込みボタンを連打するような知識のない荒らしくらいは
撃退できるんじゃないかと思います。

> (MD5ってなんだろう? 固定長の文字列を返すhash関数みたいな
> ものなのかな…)

ですです。こんな感じ。

% echo 'test1' | md5sum -t
3e7705498e8be60520841409ebc69bc1  -
% echo 'test2' | md5sum -t
126a8a51b9d1bbd07fddc65819a542c3  -
% echo 'test3' | md5sum -t
3bc3be114fb6323adc5b0ad7422d193a  -

「md5sum 文字列」ではうまくいかない環境もあるようなので、
$md5 = `echo $message|md5`;
(あるいはmd5sum)がいいと思います。

B-Cus 1998/03/08(日) 06:24:39
ああ、でもきょーこさんの望んでいる対応策の答えにはなってない
ことに気づきました(ちゃんと読んでなかった(^^;)

考え方としては同じで、
open(IN,"prev-message.dat");
($prev_addr,$prev_time) = split(/ /,scalar(<IN>);
close(IN);

if ( $prev_addr eq $ENV{'REMOTE_ADDR'} &&
   $prev_time - time() < 60 ){
 print "60秒以内の書き込みなのでエラー\n";
 終了処理
}

open(OUT,">prev-message.dat");
print "$ENV{'REMOTE_ADDR'} ",time();
close(OUT);

こんなもんでどうかな? 実際に動かしてないのでscalarの
あたりとか怪しいな〜

miyasiro 1998/03/08(日) 14:51:19
>僕もそういうつもりでいたずら防止策として書き込みました。

すいません、「いたずら防止」の部分ではなく(これは大前提の確認のつもりでした)、同一人による書き込みを禁止したいという意図ではないのでしょうか、というつもりでした。

>ただ本気でやろうとしたら、外部からアクセス可能なproxyの
>リストを用意してそれらを順に使ったり、
>やろうと思えばどれだけでも手の込んだことができるんで、
>根本的には対応策はないといっていいでしょう。それでも
>書き込みボタンを連打するような知識のない荒らしくらいは
>撃退できるんじゃないかと思います。

proxyでの排除については知識がないのですが、いずれにしても、CGIでは、ある程度は可能だけど完全には無理なので、きょーこさんの質問を読んだときに、どの程度のレベルのものが必要なのか(どの程度根性のあるいたずら者なのか)を教えてもらわないと、具体例は書きにくいなぁと思ってたのです。(制限を厳しくすると、本来の書き込みをしてくれる人にも迷惑がかかるかも知れないし)

>HTTP_USER_AGENT
>はクライアント側が勝手に用意できる文字列だから、適当な
>文字列を使ったり、

あっ、なるほど、ブラウザの自己申告ですから、アテにはならないですね。

> print "60秒以内の書き込みなのでエラー\n";

私も、とりあえずはそんなものを考えてました。ただ、もっと長い時間を考えてたので、再度接続し直して来たらとか、いろいろ考えてたのですが、これでも書き込みボタンの連打に比べればはるかに面倒な作業になりますね。

>こんなもんでどうかな? 実際に動かしてないのでscalarの
>あたりとか怪しいな〜

scalarは大丈夫でした。ひょっとして万が一行数が返るかなとも思ったので、試してみました(苦笑)。
ただ、)やOUTが足りないとか、time()が逆とか、些細な問題はありました(笑い)。


>> (MD5ってなんだろう? 固定長の文字列を返すhash関数みたいなものなのかな…)
>ですです。こんな感じ。

ありがとうございます。ついでにもう一つ聞いていいですか? 本来は何につかうものなのでしょうか?(バイナリも渡せるならウイルスチェック用かなとも思ったのですが…)

P.S.
なんかまた質問者をほったらかしにしてるような気も…(苦笑)
割り込んですいません、こんな感じでご要望に叶うでしょうか?>きょーこさん

B-Cus 1998/03/09(月) 02:03:02
> ただ、)やOUTが足りないとか、time()が逆とか、些細な
> 問題はありました(笑い)

ははは、些細な問題です(^^;
もしわからなかったら、また聞いてください>きょーこさん


> 本来は何につかうものなのでしょうか?(バイナリも渡せるなら
> ウイルスチェック用かなとも思ったのですが…)

一方向ハッシュ関数である、というだけで、別に用途は
決まっていないんじゃないでしょうか。

というか、一方向ハッシュ関数があると、ユーザ認証や
チェックサム的なことができますよね。で、バイナリも
喰わせられます。FreeBSDではバイナリ配布している
ファイルのチェックサムとして使われています。

どうでもいいですが、perlにはcryptってのがあります
(というか、UNIXのcryptを実装してるだけですけど)。

--------------
print crypt("test1","XX")."\n";
print crypt("test1","YY")."\n";
print crypt("test2","XX")."\n";

XX55cakH2S5Dk
YYsWvkQDzFgfk
XXqUWMh1ACkzw
----------------
cryptはキーワード(XXとかYY)と組み合わせて使います。
しかしこれはログイン時の認証に使われている(いた?)
関係か、9文字以降は無視してしまいます。一方、MD5は
全データを読んで結果を返します。

結局、MD5はcryptより強力な一方向ハッシュ関数である、
という認識でいいと思います
# ちなみに開発元はRSAのようです。
# (NNの起動時に表示されますよね)

miyasiro 1998/03/09(月) 03:33:55
>一方向ハッシュ関数である、というだけで、別に用途は
>決まっていないんじゃないでしょうか。
>結局、MD5はcryptより強力な一方向ハッシュ関数である、
>という認識でいいと思います

あちゃ〜、UNIX TOOL の用途を聞くなんて、お恥ずかしいかぎりです(苦笑)。

>というか、一方向ハッシュ関数があると、ユーザ認証や
>チェックサム的なことができますよね。で、バイナリも

賢いウイルスは単純なチェックサムには引っかからないようにファイルに変更を加えるって話を聞いたことがあるもんで、それでウイルスチェッカを連想したのですが、別にこれに限る必要はぜんぜんありませんでした。とにかくcryptとの関係も含めた解説のおかげでたぶん理解できたと思います(暗号関係はちゃんとは分かってないのですが…)。勉強になりました、ありがとうございます。

># ちなみに開発元はRSAのようです。
RSAって社名でもあるのか…向こうの会社は、そのまんまやないか〜
# (NNの起動時に表示されますよね)
えっ、知らなかった。今度目を凝らして見てみます。

きょーこ 1998/03/09(月) 03:58:49
B-Cusさん、miyashiroさん、ありがとうございます。
言われたとおり早速やってみます。

きょーこ 1998/03/10(火) 02:12:01
[[解決]]
なんとかコードを埋め込むことに成功しました。
これで嫌がらせもかなりやりづらくなったと思います。
B-Cusさん、miyashiroさん、ありがとうございました。

[上に] [前に] [次に]