Алгоритм Captcha
Мало кто из нас никогда не встречался с CAPTCHA-картинкой, мы часто видим их.
Кратко рассмотрим алгоритм CAPTCHA-проверки посетителя, сделав упор на защиту от уязвимостей, не связанных с собственно распознаванием картинки:
Пользователь заходит на защищаемую страницу, мы создаем для него сессию. Лучше всего, если эту сессию будет создавать сама CAPTCHA-картинка (вернее, скрипт, которые ее выдает).
Скрипт генерирует случайный текст, записывает его в сессию и выдает картинку с этим текстом посетителю. Потом, при проверке, ответ, введенный посетителем, сравнивается с эталоном, сохраненным в этой сессии.
Важно, чтобы закодированный текст никак не вычислялся из данных, передаваемых браузеру. К примеру, плохая идея хранить текст не в сессии на сервере, а передавать его (пусть даже в кодированном виде) аргументом (через адресную строку или cookie) скрипту-картинке, с тем, чтобы скрипт текст раскодировал и выдал соответствующее изображение — угадать принцип кодирования не так сложно, на самом деле. Потом, если на сервере этот текст не хранится, а передается с запросами, его вполне можно подменить.
Если случайный текст будет генерироваться не при выдаче картинки, а при выдаче страницы с формой, появляется опасность, что бот сделает несколько запросов к скрипту картинки, чтобы получить несколько вариантов одного и того же текста (если картинка выдается со случайными искажениями — то есть разная от раза к разу, хотя и с одним и тем же закодированным текстом). Распознать текст, если есть несколько его вариантов, гораздо проще.
Генерация кода самой картинкой позволяет реализовать функцию "получить другой код, если этот плохо читается пользователем" — будет достаточно обновить только картинку.
Распространенной ошибкой является то, что при проверке правильности введенного текста его просто берут из сессии и сравнивают с ответом посетителя. Проблема в том, что злоумышленник может подсунуть нам номер несуществующей сессии и ввести пустой проверочный текст. И этот пустой текст будет равен пустому тексту из несуществующей сессии — все, заслон пройден.
Важно очищать сессию после каждой проверки (неважно, успешной или нет). Не стоит полагаться на то, что при обновлении страницы скрипт картинки сгенерит новый текст — бот может просто не запрашивать картинку, а вводить один и тот же ответ, который в самом начале прочитал и сообщил боту сам злоумышленник.
Рассмотрим применение этих принципов на примерах реальных CAPTCHA (звездочками у названия показана моя личная оценка защищенности - от 1 до 4):
Google ***
Нелинейное искажение надписи, смещение символов друг относительно друга, близкое расположение символов, различные шрифты.
Шумы не применяются. Правда, символы не всегда склеиваются без промежутков.
Mail.ru очень старая **
Поворот символов, небольшое варьирование шрифтов, низкий контраст с фоном. На мой взгляд - не очень хорошая CAPTCHA (символы, как правило, темнее шума, расположены обособленно)
Mail.ru старая ****
Билайн ***
Небольшие линейные искажения символов, разный размер. Символы помещены на фон с шумом в виде геометрических фигур (эллипсов) методом инверсии. Недостаток: цифры контрастнее фона.
Мегафон ***
Смещение символов, шум в виде линий и точек.
Параллельные линии могут быть отфильтрованы, с наклонными сложнее.
МТС старая **
Небольшой поворот, смещение символов. Изредка наползание их друг на друга. Шум легко убирается уменьшением резкости (blur). Довольно слабая CAPTCHA
МТС новая ***
Небольшой поворот, смещение символов. Изредка наползание их друг на друга. Шрифты. Значительный шум, как в виде фоновой текстуры, так и линий, накладывающихся на символы. Правда, изредка даже человек не всегда легко прочтет результат.
Rambler старая **
Разноцветные символы, поворот, смещение. Шум в виде точек и прямых линий.
Rambler старая **
Разноцветные символы, поворот, смещение. Шум в виде точек и прямых линий.
Смещение по высоте, нелинейное искажение символов, шум в виде пересекающих символы ломаных того же цвета.
MSN ****
Поворот и искажения символов, шумы в виде линий того же цвета, пересекающих символы.
Yahoo ***
Нелинейное искажение символов, шум в виде пересекающей символы ломаной.
Из недостатков – ломаная может быть отделена от символов.
Yandex ****
Склейка контурных символов, нелинейные искажения, шум в виде белых и темных линий.