О уязвимости звуковых капч

Для защиты от автоматического перебора на сайтах ставится капча… Небольшая картинка с цифрами или буквами. Картинка искажена и зашумлена. Предполагается что определить какие символы изображены на картинке под силу только человеку. Более подробно — читаем Вики.

В некоторых случаях капчи в виде картинки недостаточно. Поэтому ставят дополнительно звуковую капчу. Когда это необходимо:

  1. Картинку искажают алгоритмы, которые не в курсе человеческих способностей. Поэтому  алгоритмы иногда могут переборщить и превратить картинку в совсем нечитабельную человеком. Это не обязательно сильные искажения. Иногда достаточно малейших изменений чтобы не отличить цифру 7 от 1. А в некоторых сервисах три неверных попытки и аккаунт блокируется. Поэтому ставится дополнительно возможность послушать капчу.
  2. Если сайт будут использовать люди с плохим зрением. Как правило это государственные сайты, поскольку они должны охватывать по-возможности все социальные слои.

Под картинкой как правило появляется кнопочка «прослушать» с соответствующим текстом или иконкой.  Поскольку ломать пытаются в основном графическую капчу, то про защиту звуковой порой забывают.  Т.е. распознать звуковую капчу в некоторых случаях не составляет труда. Более того для этого не потребуются изучения хитрых алгоритмов.

Рассмотрим пример из жизни (из моральных соображений название сайта написать не могу).  На одном из государственных сайтов стоит звуковая капча…

Реальный пример:

Анализ

После исследования капчи выяснилось:

  1. Капча состоит из 5 цифр из диапазона: 1 — 9
  2. Нет явных и слышимых человеческим ухом искажений
  3. Звуки одинаковых цифр в разных капчах не отличаются
  4. Звук каждой капчи имеет разную длину

Поскольку отсутствуют слышимые искажения (2), то можно предположить что их нет вообще и чтобы распознать капчу достаточно сравнения по образцу. (3) говорит нам о том, что капча на сервере склеивается из 9 звуковых шаблонов цифр. Как должен работать алгоритм:

  1. Для каждой позиции от 0 до 4 (у нас всего 5 цифр в капчи) выполняем:
  2. Смещаемся в капче на длину предыдущего определенного звука
  3. Ищем какой из девяти шаблонов совпадает со звуком начинающимся с текущего положения
  4. Нашли, переходим к следующем

Подготовка шаблонов для сравнеия

Для успешной работы алгоритма нам понадобятся звуки из которых склеивается капча. Вырезать мы будем эти звуки из полученных примеров капчи. Для этого нам нужно знать длительность звука каждой цифры в капче. Как оказалось звуки капчи всегда разной длины, а значит и звуки цифр из которых капча склеивается разные по длительности. Тут нужно качать несколько звуков капч и составлять систему уравнений вида:

1)  x1*n1 + x2*n2 + .. + x9*n9 = длина_примера_звука_капчи_1
2)  x1*n1 + x2*n2 + .. + x9*n9 = длина_примера_звука_капчи_2

3)  x1*n1 + x2*n2 + .. + x9*n9 = длина_примера_звука_капчи_9

По поводу уравнений — тут не все звуки капчи подойдут. Лучше конечно найти капчи с максимальными повторениями…  Я, например, искал капчи в которых есть 4 повторения одной цифры и одно повторение другой. Тогда уравнения решит и пятиклассник. Например вот такие:

  1. последовательность: 79777, а уравнение: x7*4 + x9 = 2880

  2. последовательность: 86888, а уравнение: x8*4  +  x6 = 3420

  3. последовательность: 41144, а уравнение: x4*3 + x1*2 = 3348

  4. последовательность: 55655, а уравнение: x5*4 + x6 = 2556

  5. последовательность: 62662, а уравнение: x6*3 + x2*2 = 3060

  6. последовательность: 45544, а уравнение: x4*3 + x5*2 = 3204

И так далее. Потом решаем и получаем следующие длительности:

Звук Длительность (мс)
1 540
2 504
3 504
4 756
5 468
6 684
7 540
8 684
9 720

Далее устанавливаем утилиту sox. С помощью нее будем вырезать звуки. Почему именно ее? Потому что она вырезает и не меняет формат wav файла. Можно воспользоваться и другими вариантами, но для Linux это наиболее быстрый метод. Поставить sox можно одним из способов:

  • Для OpenSuSE в консоли:  sudo zypper install sox
  • Для Ubuntu в консоли: sudo apt-get install sox
  • Для других систем: качаем с официального сайта, разбираемся и самостоятельно ставим

Далее просто вырезаем с помощью утилиты sox соответствующие шаблоны из звуков капчи. Так, например, чтобы вырезать из капчи (6) звуковой шаблон четверки набираем в консоли:

sox 45544.wav 4.wav trim 0 0.756

Тут 45544.wav — файл из которого вырезаем, 4.wav — файл куда сохраняем. 0 — смещение от начала в секундах. 0.756 — длина вырезаемого участка (получена из решения уравнений).

Так делаем со всеми цифрами из диапазона 1-9. В результате проделанной работы у нас на выходе должны появится девять звуковых файлов. В табличке представлены результаты проделанной работы:

Звук Длительность (мс) Послушать
1 540
2 504
3 504
4 756
5 468
6 684
7 540
8 684
9 720

Осталось дело за малым — написать алгоритм распознавания шаблонов внутри звука капчи и вычисления последовательной позиции.

Алгоритм распознавания звуковой капчи

Во время написания алгоритма оказалось что звук цифры в зависимости от положение внутри звука капчи меняется. На слух это не заметить. Но при побайтовом сравнении звуки не совпадают. Есть много предположений с чем это связано (sox что-то передал, кодированный звук в фйалах разных длин может не совпадать и т.д.). Дабы не лазить в изучение звуковых алгоритмов можно реализовать небольшую хитрость. А именно — посчитаем какой процент звука шаблона совпадает с соответствующим звуком в капче.

Методом проб и ошибок выяснилось, что достаточно чтобы совпадали 40% звука шаблона и звука в капче.  Тогда мы можем сказать, что обнаружили совпадение совпадение.

Суть такая — побайтово пробегаемся по звуку капчи и сравниваем по шаблонам. Если обнаружили шаблон, то записываем его и смещаемся на длину шаблона.

Еще одна тонкость — суммарная длина всех шаблонов в капче и длина самой капчи иногда не совпадают. Величина разности небольшая, но все же это влияет на распознавание. Разбираться в чем косяк я не стал, а просто добавил величину patternShift (методом проб и ошибок — 10 оказалось вполне достаточно) . Теперь после обнаружения какого-либо шаблона курсор смещается на длину шаблона минус patternShift.

В результате получился алгоритм, который распознает 100% звуковой капчи на исследуемом сайте. Пояснения сразу после кода.

Пояснения:

  • все шаблоны находятся в папке «resources/patterns» относительно проекта
  • для того чтобы распознать звуковую капчу, достаточно ее передать в функцию detectPattern(inputStream: InputStream) . В результате мы получим строку с распознанными символами.
  • Почему на вход подается InputStream вместо звукового файла? Дело в том, что фнкция используется в основном для получения звуковых данных с веб-сайта. А с веб сайта звуковой поток забирается в память как раз с помощью класса AudioInputStream. На диске хранить данные нет смысла. Получили, распознали и забыли. Вот непосредственно тот участок кода, который использует наш алгоритм в боевых условиях:

Послесловие и методы противодействия

Безусловно при неограниченных ресурсах можно автоматически распознавать практически любую капчу. Однако не у всех такие ресурсы есть, да и тратиться не каждый захочет. Поэтому нет никакого смысла создавать параноидальную защиту от автоматического распознавания… Достаточно ограничиться решением следующей задачи:

Обеспечить такую защиту от автоматизированного распознавания капчи, что стоимость обхода такой защиты превышала бы экономическую выгоду злоумышленника от последствий обхода такой защиты.

Как то так…

Что это значит на деле?  В нашем конкретном примере. На написание проекта на Scala, который 100% распознает капчу был потрачен суммарно день. Использовался обычный компьютер. Если разработчик опытный, то трех часов хватит. Очевидно, что такая защита не достаточна.

К примеру, на написание распознавателя средненькой графической капчи уйдет гораздо больше времени. Однажды мне дали задание содрать базу данных с чужого сайта за денежку. Там стояла графическая капча. Я потратил множество времени на изучение предметной области и на реализацию. Но в итоге результат и близко не стоял к необходимому. От задания я отказался, поскольку те деньги что мне предлагали явно не оправдывали потраченное время.

Отсюда вывод — к существенному усложнению задачи распознавания звуковой капчи приведет зашумление и искажение звуков. Такой подход у меня точно отобьет желание проверять капчу.

 

3 Комментариев

  1. Жестовая капча может использоваться в качестве альтернативного варианта вместо аудиотестирования, что позволит людям с проблемами восприятия звуков или не имеющим аудиооборудования пройти тест.

  2. Жестовая капча может использоваться в качестве альтернативного варианта вместо аудиотестирования, что позволит людям с проблемами восприятия звуков или не имеющим аудиооборудования пройти тест.

  3. Ёмоё. Даже не смог попробовать. Вылезло окошко с жуткими тормозами, хотя компьютер мощный. Очень резко вылезла табличка что пробный период истёк. Не понятно куда что вводить.

Добавить комментарий