ЖУР.КОМ: крупнейший каталог электронных журналов компьютерной тематики
Защити свой WWW-сервер
Докучаев Дмитрий aka Forb
Спецвыпуск Xakep, номер #041, стр. 041-088-3
print "Content-type: image/jpeg\n\n";
print $image->jpeg; ## И выведем картинку на экран
Скрипт несложен. Более того, это лишь часть сценария, который тебе следует написать ;). В идеале число должно быть рандомное, а также следует продумать алгоритм сравнения числа на картинке и цифры, введенные пользователем. Если все совпало – пропускать, иначе отшивать :). Вообще, этот метод полезно сочетать с обычной парольной авторизацией. Тогда никакой хакер не посягнет на твою территорию.
Настало время поговорить о том, как вообще организовывается защита. По большому счету, ты мало что сделал – само изображение без скрипта, выполняющего проверку, не дает ничего. Так как же написать такой чудесный сценарий?
Во-первых, я не сказал, как сгенерировать случайное число. Это достигается функцией rand. Если ты не хочешь получить число с плавающей точкой, используй функцию int для последующего получения целой части от цифры. Итоговая команда будет следующей:
$number = int rand 31337;
Магический номер означает предел случайного числа. Диапазон кода колеблется от 0 до этого предела.
Картинка должна быть вставлена в logon-страницу, где запрашиваются логин и пароль на вход (или другие параметры). Ни в коем случае не делай поле hidden с номером на картинке – твоя защита будет бессмысленной, так как по этому полю в форме хакер быстро узнает код и напишет консольный брутфорс ;).
Разумнее будет создавать для каждой сессии свой MD5-код, который будет занесен в hidden. Прежде чем авторизовать пользователя, запишем в файл (название = коду MD5) персональный цифровой код, и уже затем будет производиться его сравнение с введенной цифрой.
Конечно, сгенерировать MD5 можно и консольной командой md5 –s строка, но разумнее будет использовать модуль Perl под названием Digest::MD5. Вот как выглядит простенький скрипт, который генерирует хеш по строке "time().$$" (текущее время в raw-формате, а также процесс скрипта). После создания уникального номера происходит его запись в файл.
#!/usr/bin/perl
use Digest::MD5;
$chrootdir="/home/user/nonwebbrowseabledir/"; ## Каталог, который не будет виден через Web.
$salt=Digest::MD5->new; ## Новый метод для MD5.
$string=time().$$; ## Уникальная строка, по которой ведется шифрование.
$hash = $salt->add($string); ## Формируем хеш.
$id=$hash->hexdigest; ## Шифруем методом ASCII-HEX.
open(FILE,">$chrootdir$id") || die "Can't open file for write: $!\n"; ## Открываем файл для записи.
print FILE $number; ## number – Заранее сгенерированный номер, который будет виден на изображении.
close(FILE); ## Закроем файл.
print "Content-type: text/html\n\n"; ## Выводим контент документа.
print "<HTML><FORM>.....\n"; ## Пишем произвольные данные для формы.
print "<input type=hidden name=hash value=$id>"; ## Заносим id в форму для последующей проверки.
После того как юзер передаст все данные скрипту (неважно каким методом), тебе необходимо, помимо сравнения логина и пароля, включить в свой код проверку правильности номера на картинке. В моем примере это реализуется открытием файла "$chrootdir$id" ($id пришло сценарию в качестве параметра), извлечь из документа номер и сравнить со вторым параметром формы (который ввел пользователь). После решения о допуске клиента в систему, удали файл, который недавно открывал. В противном случае у тебя в каталоге будет куча ненужного мусора.