Як це працює captcha

А для затравки - якщо ви вважаєте, що така перевірка капчи буде працювати:
if ($ _ POST [ 'captcha'] == $ _SESSION [ 'captcha']) return true; (Приклад з практики)
то ви глибоко помиляєтеся.

Згідно своїм визначенням, captcha - це автоматизований публічний тест Тьюринга (тест який може пройти людина, але не комп'ютер). У статті я буду розглядати свойтсва капчи на прикладі самого распространненость її виду - тексту на картинці, хоча майже все написане однаково можна застосувати до будь-якого виду капчи.

Два головних властивості капчи

Будь-яка капча повинна володіти двома властивостями, без яких вона не буде працювати:

Стійкість до розпізнавання - властивість, що захищає капчу від розпізнавання алгоритмом - наприклад системою розпізнавання тексту. Гарантує те, що людина зможе прочитати текст на картинці, а комп'ютер немає.
Антиприклад: стандартна капча форумів phpBB 2.x такою властивістю не володіла - через відносну простоту розпізнавання з'явилися скрипти, які спамили все підряд форуми змушуючи веб-майстрів міняти капчу на більш стійку.

Стійкість до вгадування - властивість капчи, що не дозволяє вгадати її значення за невелику кількість спроб (менше 1000). Якщо набір можливих значень капчи невеликий, програмі не складе труднощів вгадати її підбором замість розпізнавання.
Антиприклад: арифметична капча на кшталт «1 + 2» (перебір чисел від 1 до 20 незабаром дасть результат).
Антиприклад: вибрати з декількох картинок ту, на якій зображений котик.

Перевірка капчи

Значення для перевірки повинно зберігатися на сервері, а не передаватися разом з картинкою в браузер. Для зіставлення відвідувача і правильного значення капчі необхідно використовувати якийсь ключ, який передається разом з капчі (ідентифікатор сесії, номер капчи і т.п.)
Антиприклад: якщо передавати саму капчу і значення для її перевірки (в тому числі зашифроване), то людині досить один раз розпізнати таку капчу і далі використовувати комбінацію «відповідь» - «значення для перевірки» в своєму скрипті (за посиланням на початку поста якраз такий випадок)

Перед перевіркою відповіді - треба переконатися, що він не порожній. В іншому випадку, зловмисник може не завантажуючи картинку або видаливши ідентифікатор поточної сесії, передати пусте значення і пройти капчу, тому що відбудеться порівняння двох порожніх рядків (в PHP неіснуюче значення дорівнює порожній рядку).
Антиприклад: вже згаданий мною код if ($ _ POST [ 'captcha'] == $ _SESSION [ 'captcha']) return true;
Причому цей код був написаний досвідченим програмістом.

Після перевірки, збережене значення капчі необхідно видалити. Якщо не зробити цього, зловмисник зможе використовувати дане значення знову необмежену кількість разів. Так, при оновленні сторінки з формою оновлюється і капча (або при генерації форми, або при генерації картинки), ось тільки скрипт може не завантажувати форму знову (треба згадати, що це не актуально якщо на сайті використовуються одноразові csrf-токени для форм).
Антиприклад: гіпотетична форма логіна, в якій досить один раз ввести капчу правильно, і далі підбирати пароль скриптом, уникаючи перегенерации капчи на сервері.

куленепробивна капча

Захист від перебору. Якщо ваша капча стійка до розпізнавання, але не дуже стійка до перебору (наприклад на ній треба прочитати всього 3-4 цифри), бажано обмежити число неправильних відповідей «з одного ip» / «для одного логіна» / etc. Такі обмеження необхідно перевіряти ДО перевірки самої капчи (тобто навіть у разі правильно введеної капчі, при наявності обмеження вона не повинна вважатися пройденою) інакше воно не буде перешкоджати перебору.

Захист від DoS. При генерації капчи на своєму сервері, треба розуміти що це зручний вектор проведення DoS атак (яку, на відміну від DDoS, може влаштувати будь-який школяр). Для захисту можна обмежити число генерації капчи для одного ip, кешуванням капч і т.д. Детальніше про це

Захист від розпізнавання. Якщо ви вибираєте капчу, або раптом збираєтеся написати її самі, бажано розуміти яка капча більш захищена від розпізнавання. Існують готові універсальні скрипти розпізнавання капчі, що працюють за принципом OCR. а в разі якщо ваш сайт зацікавить спамерів є ризик, що будуть використовувати / писати скрипт конкретно під вашу капчу. Останнє правда відноситься більше до сайтів рівня Яндекс або vk, а ось варіант із захистом від банальних OCR бажано передбачити.

Захист від антігейтов. Якщо говорити формально, то капча як тест Тьюринга не зобов'язана захищати вас від антігейтов, так як в цьому випадку її буде розпізнавати людей. З практичної ж точки зору, це питання дуже актуальне і захищатися якось треба.
Тут немає і не може бути «золотого стандарту» (бо в такому випадку антігейти впровадять його підтримку), тому ви вільні доповнювати капчу будь-якими хитрощами, щоб зробити її розпізнавання через антігейт неможливим. наприклад:
- нестандартна капча (збір пазла, поворот зображення, клік по області на фото і т.п.);
- кирилична капча - найпростіше рішення, але має ряд мінусів: підходить тільки для проектів з російськомовної аудиторією, є антігейти з підтримкою кирилиці;
- використання віртуальної клавіатури поруч з капчі для введення нестандартних символів або фігур (може бути незручно користувачам мобільних);
- використання CSS або JS капчи (генерація картинки за допомогою купи div з позиціонуванням, або з використанням canvas)
і так далі.

Не просіть ввести капчу, якщо ви вже переконалися, що перед вами людина. Тут однак, треба бути обережним, щоб форму можна було використовувати скриптом необмежену кількість разів після однократного введення капчі людиною.
Приклад: форма реєстрації. Якщо я десь реєструюся, і забув ввести поле «поштовий індекс», але правильно ввів капчу - не треба показувати мені нову. Витратьте 10 хвилин на те, щоб зберегти десь у себе, що ось цю конкретну форму зараз намагається заповнити жива людина. Ваші десять хвилин заощадять багато годин людству.