>исключительно прямым обращением к /cgi-bin/wwwboard.pl, можно ли как-то защититься от этой
>напасти, может скрипт сам немного видоизменить на предмет проверки не напрямую
>ли было выполнено обращение к скрипту.
Самое простое - проверять переменную окружения:
HTTP_REFERER
Эта переменная содержит адрес страницы с которой вызвали текущую страницу.
Для языка PERL это будет делать такой код:
$U_referer=$ENV{'HTTP_REFERER'};
unless ($U_referer || index($U_referer, '/wwwboard/messages/') == -1){
print "Location: http://ваш_адрес.ru/\n\n";
exit;
}
Это можно вписать в любое место скрипта "/cgi-bin/wwwboard.pl", ниже строки "#!/usr/bin/perl".
Здесь:
index($U_referer, '/wwwboard/messages/')
в кавычки впишите "кусочек" адреса, который бы присутствовал во всех страницах, с которых можно добавлять сообщения и ответы. Если этот кусочек не будет найден внутри строки адреса с которого перешли на добавлялку, то пользователя будет редиректить на главную страничку (хотя можно и не на главную - куда пожелаете, адрес впишите вместо "http://ваш_адрес.ru/").
НО!
Это не поможет избавиться от всех ботов-писателей.
Некоторые боты весьма хороши, и выдают всё что нужно, включая и верное заполнение HTTP_REFERER.
Самый верный вариант - использовать тактику: "Введите число, которое вы видите на картинке".
Только этот вариант посложнее в реализации, и здесь... Хотя чем чёрт не шутит! Даю код (постейший, и без картинок, но он справиться :), который это сделает (в виде рабочего скрипта, как встраивать - разбирайтесь сами):
#!/usr/bin/perl
use CGI
$indat = new CGI;
# получаем данные переданные нам:
$zzz_inpnumDEC=$indat->param('inpnumdec');
chomp($zzz_inpnumDEC);
$zzz_inpnumDEC++; $zzz_inpnumDEC--;
$zzz_inpnumDEC=~tr/678345912/123456789/;
$zzz_inpnumTXT=$indat->param('inpnumtxt');
chomp($zzz_inpnumTXT);
$zzz_inpnumTXT++; $zzz_inpnumTXT--;
# генерируем последовательность для вывода
@zzz_txtnum=('один', 'два', 'три', 'четыре', 'пять', 'шесть', 'семь', 'восемь', 'девять');
$zzz_outnum1=int rand(9);
$zzz_outnum2=int rand(9);
$zzz_outnum3=int rand(9);
$zzz_outTEXTnum=$zzz_txtnum[$zzz_outnum1].', '.$zzz_txtnum[$zzz_outnum2].', '.$zzz_txtnum[$zzz_outnum3];
$zzz_outDECnum=($zzz_outnum1+1).($zzz_outnum2+1).($zzz_outnum3+1);
$zzz_outDECnum=~tr/123456789/678345912/;
unless ($zzz_inpnumTXT){
# это первый вызов, просто выведем форму запроса данных
print "Content-Type: text/html\n\n";
print "<FORM ACTION='http://ваш_сайт.ru/cgi-bin/tstu.cgi' METHOD=POST>\n";
print "<input type='hidden' name='inpnumdec' value='$zzz_outDECnum'>\n";
print "Введите подряд эти циферки: $zzz_outTEXTnum<br>в поле:<br>\n";
print "<input size=3 type=text name='inpnumtxt'><br>\n";
print "<input type=submit value='Показать результат'>\n";
print "</form>";
# довольно работы
exit;
}
# это вызов из заполненой формы, нужно всё проверить
# сверяем верно ли отреагировал юзер
$zzz_REZULTAT='Введено верно.';
if ($zzz_inpnumTXT != $zzz_inpnumDEC){
# Ошибка ввода
$zzz_REZULTAT='Вы шиблись, и будете наказаны!';
}
# и снова выдать форму
print "Content-Type: text/html\n\n";
print "<h1>$zzz_REZULTAT</h1>\n";
print "<FORM ACTION='http://ваш_сайт.ru/cgi-bin/tstu.cgi' METHOD=POST>\n";
print "<input type='hidden' name='inpnumdec' value='$zzz_outDECnum'>\n";
print "Введите подряд эти циферки: $zzz_outTEXTnum<br>в поле:<br>\n";
print "<input size=3 type=text name='inpnumtxt' value='$zzz_inpnumTXT'><br>\n";
print "<input type=submit value='Показать результат'>\n";
print "</form>";
# довольно работы
exit;
Шанс, что бот сам "угадает" число: 1 из 999, шанс, что бот прочитает что написано и переведёт в десятичку: не в этом столетии (особенно если число "один" написать так "единичка" :)
Естественно, что никому не надо говорить вот эту последовательность:
$zzz_outDECnum=~tr/123456789/678345912/;
Что бы изменить механизм шифрования верного результата, просто поменяйте местами циферки во второй последовательности, например:
$zzz_outDECnum=~tr/123456789/459126783/;