Привет,
Многие, наверное, слышали о моём споре с Женей Д., что я сломаю его каптчу до конца месяца, которую он лично разработал для нашего сайта.
Признаюсь, когда спорил, даже толком в код не посмотрел, а действовал по принципу – ПОЛОМАТЬ МОЖНО ВСЁ. Я просто пошутить хотел, а Женя всё по-серьёзному решил спорить. И завязался спор на тортик до конца месяца, что я сломаю его творение. J
Сразу хочу сказать, что сама каптча написано высококлассно и защищена практически от всех известных атак по каптчам. Споры разделились относительно можно нашу каптчу поломать распознаванием или нельзя. Мнения были разные. Но в эту сторону я даже не смотрел – во-первых, знаний по распознаванию образов и нейронным сетям ещё не хватает, а во-вторых, есть хорошая пословица – "Двери крепки, да петли хлипки".
Немного о самой каптче. Это серверный хэндлер, который генеряет текст для каптчи и кладёт его в сессию и по этому тексту генеряет картинку. Страница регистрации содержит ссылку на этот хэндлер. Т.е. по загрузке страницы на клиенте идёт ещё один запрос на сервер в хэндлер для получения картинки. Пользовать заполняет форму, разгадывает каптчу и отсылает запрос на сервер. На сервере введённый текст для каптчи сравнивается с тем, что лежит в сессии, и если всё верно регистрация продолжается.
Всё стандартно. И работает отлично.
А потом глянул в код и нашёл таки 2 узких места.
Уязвимость номер 1.
Что будет, если загрузить страницу регистрации, а запрос на генерацию каптчи забанить? С каким значением будет сравнивать сервер пользовательский ввод? Вот здесь и была уязвимость. Женя сравнивал пользовательский ввод с... константой. Т.е. если в сессии ключа нет, то сравнивал с "EmptyText". Ну, дальше, все сообразили, что надо ввести пользователю, чтобы пройти регистрацию.
Почему была? Только-только похвалился Жене, что уже нашёл дыры, Женя ещё раз всё пересмотрел, переписал (даже к сессию стал ложить не сам текст, а только его хэш), и этой дыры больше не оставил. А жаль... это самый простой способ похачить.
Уязвимость номер 2.
Связана с неодноразовостью самой каптчи. Что это значит? Один раз разгдав каптчу, пользователь может зарегистрировать 1000 пользователь под одной и той же каптчей. Из сессии ведь никто не удаляет текст каптчи, оставшейся после предыдущей регистрации пользователя.
Дабы, подтвердить это, я написал небольшой экспоит для всем хорошо вам известного сайта, где наша каптча лежит.
Что скриптик делает:
- Предоставляет красивый итерактивный интерфейс на WPF
- Делает запрос на страницу регистрации на сервер, чтобы получить ASP.NET Session кук
- И делает ещё один запрос на сервер в хэндлер генерации каптчи, дабы получить картинку (ессно с куком полученным на шаге 2)
- Пользователь вручную разгадывает каптчу (один разок всего)
- Скрипт посылает 10(0)(00) постов запросов на сервер использую разгаданную каптчу и сессионный кук, иммитируя настоящую страницу регистрации
- Сервер успешно создаёт всех юзиков
Даже залогиниться могу под этими аккаунтами
Вот, собственно, и всё. Можно сказать, что это проблема не каптчи, а кода, который каптчу юзает (к примеру, сессию после регистрации нужно полностью убивать, или явно вызывать перегенерять текст). Но... Основная цель каптчи как компоненты для регистрации пользователей - это предотвратить построение ботов для автоматической регистрации пользователей. Цель недостигнута – вышеуказанный скрипт не что иное как настоящий бот.
Поэтому эта дыра каптчи, которую надо исправлять. Как? Сами догадаетесь, как одноразовость каптчи организовать.
А ещё это значит, что скоро мы все дружно большой тортик поедим, который нам Женя Д. в салодком фальварке купит.
PS. Я на мыло лично вышлю (если кому интересно) сердцы скрипта по автоматическому созданию юзиков на нашем сайте.