#! /usr/bin/perl # ↑このパスはご利用環境によって変更しなければならない場合があります. # -- この check.txt は check.cgi に名前を変更してからご利用ください -- # ロボットチェッカー v1.00 # (c)2003 by CGI-RESCUE #【履歴】 # # 2003/02/02 v1.00 初リリース #【仕組み】 # # 1. 乱出力させた指定文字を識別ファイルに記録すると共に画像に変換して表示。 # 2. 画像に表示された指定文字を手動により入力させる。 # 3. 識別ファイルに記録した指定文字と入力させた文字列を比較して、所定の処理をする。 #【構成例】< >内はパーミッションの相当値 # # │ # ├ tmp/ <777> .. (参考)Webから見えない場所に配置するのが理想 # │ # ├ check.cgi <755> .. このプログラム #【利用範囲】 # # このまま利用する以外に、任意のスクリプトにこの仕組みを組み込む等して利用しても構いません。 # その場合は、プログラム内(※)部分は削除しないでのご利用が条件です。 #----------------------------------------------------------------------------------------------- # 作業ディレクトリ(このディレクトリのパーミッションは777相当値とすること) 最後は/で閉じること $tmp_dir = "./tmp/"; # 画像合成flyがある場所(パス) 参照 http://martin.gleeson.com/fly/ $flyprog = "/path/to/fly"; # 入力させる文字列の種類(英数字) @CHAR = ('a'..'k','m','n','p'..'z','A'..'H','J'..'N','P'..'Z','2'..'9'); # 見間違えしやすい文字数字を除いた文字列の例 # @CHAR = ('0'..'9'); # 数字のみの例 # @CHAR = ('a'..'z','A'..'Z'); # アルファベットのみの例 # 入力させる文字列の長さ(長くする場合には右端の切れに注意) $NUM = 5; # 入力成功した場合のアクセス先 $true = 'http://www.rescue.ne.jp/'; # 入力失敗した場合のアクセス先 $false = 'http://www.yahoo.co.jp/'; #----------------------------------------------------------------------------------------------- # 入力画面 sub InputStr { $size = $NUM + 10; # 入力域が入力数分全体が見えるように(IE対策!?) $maxlength = $NUM; print <<"EOF"; Content-type: text/html; charset=Shift_JIS\n
indicator
↑ここに表\示されている >< の間の$NUM文字を入力してボタンを押してください.
EOF } #----------------------------------------------------------------------------------------------- $ext = ".cgi"; # CGI偽装により識別ファイルの閲覧を禁止 $infile = $tmp_dir . "fly.$$"; # 画像合成一時ファイル名 if ($ENV{'QUERY_STRING'} eq "") { # 識別ファイルは16文字の $ID = &MakeStr(16,'a'..'z','A'..'Z','0'..'9'); # 識別ファイルに入力させる指定文字(乱文字)を記録 if (!open(WID,"> $tmp_dir$ID$ext")) { &PrintImage($!); exit; } print WID &MakeStr($NUM,@CHAR); close(WID); chmod(0666,"$tmp_dir$ID$ext"); &InputStr(); # 入力画面へ # 一定時間を経過した作業ファイルを削除 if (!opendir(DIR,$tmp_dir)) { &PrintImage($!); exit; } @files = readdir(DIR); close(DIR); foreach $file (@files) { next if $file eq '.'; next if $file eq '..'; if (-M "$tmp_dir$file" > 0.25) { unlink("$tmp_dir$file"); } # 有効期間6時間 } } elsif ($ENV{'QUERY_STRING'} eq "check") { read(STDIN,$buffer,$ENV{'CONTENT_LENGTH'}); # 標準入力のみ # URLデコード @pairs = split(/&/,$buffer); foreach $pair (@pairs) { ($key,$val) = split(/=/,$pair); $val =~ tr/+/ /; $val =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $in{$key} = $val; } # 識別ファイルから指定文字を取り出す if (!open(RID,"$tmp_dir$in{'ID'}$ext")) { &PrintImage($!); exit; } $PWD = ; close(RID); # 入力文字と指定文字の比較 if ($in{'entry'} eq "") { &PrintImage("PLEASE INPUT STRINGS"); } elsif ($PWD eq $in{'entry'}) { print "Location: $true\n\n"; } else { print "Location: $false\n\n"; } } elsif ($ENV{'QUERY_STRING'} eq "c") { &PrintImage("(c)2003 by CGI-RESCUE "); exit; } # 削除禁止(※) else { $ENV{'QUERY_STRING'} =~ s/\.//g; # 安全対策 $ENV{'QUERY_STRING'} =~ s/\///g; # 識別ファイルから指定文字を取り出す if (!open(RID,"$tmp_dir$ENV{'QUERY_STRING'}$ext")) { &PrintImage(""); exit; } $PWD = ; close(RID); # 右端切れ防止のために両端に記号を置く $STRING = '>' . $PWD . '<'; # 指定文字を画像化して出力 &PrintImage($STRING); } exit(0); sub MakeStr { # 指定長の乱文字生成ルーチン # &MakeStr(文字数,構成文字列); local($LOOP,@char) = @_; local($OUTPUT) = @_; $OUTPUT = ''; $LOOP--; srand(time|$$); foreach (0..$LOOP) { { local(@temp); push(@temp,splice(@char,rand(@char),1)) while @char; @char = @temp; } $OUTPUT = $char[($_)] . $OUTPUT; } $OUTPUT; } sub PrintImage { # 画像合成と出力 local($STRING) = @_; print "Content-type: image/gif\n\n"; open(FLY,"> $infile"); # 一時ファイルの作成 print FLY "new\n"; print FLY "size 512,32\n"; # 画像領域 横512 x 縦32(バイト) print FLY "fill 0,0,255,255,255\n"; # 領域を白(RGB=255,255,255)に print FLY "string 0,0,0,0,0,giant,$STRING\n"; # 指定文字を最大フォント(giant)で合成 close(FLY); # 画像出力 open(FOO,"$flyprog -q -i $infile |"); while() { print; } close(FOO); unlink($infile); # 一時ファイルの削除 } #__END_OF_SCRIPT__