Класс captchaCV создаёт captcha и проверяет введённой код. https://github.com/VladimirKheifets/JS-Class-captchaCV Демо: https://www.alto-booking.com/developer/captchaCV https://www.alto-booking.com/developer/captchaCV//?la=de https://www.alto-booking.com/developer/captchaCV/?la=ru Пимер: HTML: <html> <head> <link rel="stylesheet" href="captchaCV.css"> <script src="captchaCV.min.js"></script> <script src="index.js"></script> </head> <body> <form> <div id="captcha"></div> <br> <button type="submit">Senden</button> </form> </body> </html> index.js Код (Javascript): window.addEventListener("load", () => { let myCaptha = new captchaCV("captcha"); document.forms[0].addEventListener('submit', function(e){ e.preventDefault(); alert(myCaptha.verification()); }); }); captchaCV.css Код (CSS): #captcha{ display:table; } #captcha div{ display:table-cell; vertical-align:middle; text-align:center; min-width:30px; } #captcha span{ font-size: 25px; cursor:pointer; transform: rotate(0); margin: 0 0 0 0; position: relative; display:inline-block; line-height:30px; } #captcha span::before { content:"\1F5D8"; } #captcha span:hover{ animation: rotate 2s linear infinite; } @keyframes rotate { 100% { transform: rotate(720deg); } } #captcha canvas{ border: 1px solid #cccccc; } #captcha input{ height: 30px; width: 200px; }
Ну красиво, да. Только два момента: 1. На GitHub обычно выкладывают исходник, а не минифицированную версию. 2. Каптчу валидоровать на бэкенде нужно. Если эта библиотека только для рисования каптчи -- то не плохо бы уметь рисовать переданную строку.
Добрый день! Принципально то, что эта капча создаётся и проверяется на фронтенде Если Вы внимательно посмотрите описание и примеры, то увидите, что у класса есть два метода: create и valdation. Метод create вызывается из конструктора, а метод valdation из обработчика события submit, Удачи!
Какие области применения такой капчи? От чего она защищает, от человека? То есть это просто визуальный элемент, который можно использовать только в клиентских приложениях (со всеми вытекающими)?
Область применения такая же как и у любой капчи. Защита от человека. Попробуйте вставить эту капчу и отправить на сервер, например, контактный формуляр. Показать как? Можете ради интереса попробовать взломать код этой капчи, не человеком, а хакнуть программно. Может быть Вы считате, что необходимо обязательно использоаать гдлиб и рисовать на PHP?
1. Я вас, видимо, удивлю, но капча обычно применяется для зашиты от роботов ("для различения компьютеров и людей"). 2. Отправить на сервер, например, контактный формуляр, эта капча вообще никак не препятствует. Отправка на сервер, например, контактного формуляра -- это просто http-запрос. 3. Рисовать можно как угодно. Валидировать нужно на сервере.
Допустим, запускаем робота на эту капчу PHP: <?PHP echo htmlentities(file_get_contents("https://www.alto-booking.com/developer/captchaCV")); /* <html> <head> <!-- https://www.alto-booking.com/developer/captchaCV/?la=ru --> <link rel="stylesheet" href="captchaCV.css"> <script src="captchaCV.min.js"></script> <script src="index.js"></script> </head> <body> <form> <div id="captcha"></div> <br> <button type="submit">Senden</button> </form> </body> </html> */ echo "<br>"; echo htmlentities(file_get_contents("https://www.alto-booking.com/developer/captchaCV/index.js")); /* URL(window.location.href); var la = url.searchParams.get("la"); if(!la) la = "en"; if(data.dictionary[la]) dS = data.dictionary[la]; else dS = data.dictionary["en"]; //------------------------------------------------------- let myCaptha = new captchaCV("captcha", dS["placeH"]); document.forms[0].addEventListener('submit', function(e){ e.preventDefault(); err = myCaptha.verification(); alert(`${dS["msg0"]} ${dS["msg"][err]}!`); }); }); }); */ Сможет робот найти код, который требуется ввести в капчу? А DOM-элементы капчи найдёт робот? Так показать Вам как встроить эту капчу в контактный формуляр? Мы ж не ядерной физикой занимаемся, проверяется всё очень просто. Без синхрофазатронов.
Вы, очевидно, не понимаете сути. Роботу вообще не нужно вводить никакие коды, если используется такая капча. Да и человек может легко ее обойти, вот демонстрация: https://www.youtube.com/shorts/KvuICzuuXgU Удачи!
Добрый день! Я подключил капчу к простенькому контактному формуляру. Вот демонстрация: https://www.alto-booking.com/developer/captchaCV/feedback/ Легко обошли? Удачи!
Да: Код (Text): curl 'https://www.alto-booking.com/developer/captchaCV/feedback/' \ -H 'content-type: multipart/form-data; boundary=----WebKitFormBoundary86N2BnvskAqtD6al' \ --data-raw $'------WebKitFormBoundary86N2BnvskAqtD6al\r\nContent-Disposition: form-data; name="name"\r\n\r\ntest\r\n------WebKitFormBoundary86N2BnvskAqtD6al\r\nContent-Disposition: form-data; name="email"\r\n\r\ntest@test\r\n------WebKitFormBoundary86N2BnvskAqtD6al\r\nContent-Disposition: form-data; name="message"\r\n\r\ntest\r\n------WebKitFormBoundary86N2BnvskAqtD6al--\r\n'
Добрый день! Простите, Вы не обошли капчу, а открыли для себя HTML-код формуля. Это можно было сделать ещё легче и читабельнее из консоли браузера. HTML: <html> <head> <link rel="stylesheet" href="captchaCV.css"> <script src="captchaCV.min.js"></script> <script src="index.js"></script> <style> input[name='name'],input[name='email'],textarea{ display: block; width: 380px; margin: 10 0 10 0; padding: 3px; font-size: 16px; } body > div + div{ font-family: arial; font-size: 20px; padding-top: 30px } </style> </head> <body> <div align=center> <form> <input type="text" name="name" type="text" placeholder="name" required> <input type="email" name="email" placeholder="email" required> <textarea name="message" placeholder="message" required></textarea> <div id="captcha"></div> <br> <button type="submit">Senden</button> </form> </div> <div align=center></div> </body> </html> Также в браузере Вы можете легко увидеть и перезаписать JS. Вы писали, что можете легко отправить feedback не вводя капчу. Покажите, пожалуйста, сообщение, с сервере подтверждаюшее отправку с обходом капчи. Удачи!
Перечитайте ещё раз (или столько, сколько вам необходимо) мои сообщения. Я лишь повторю ещё один раз (надеюсь на понимание): ваша капча никак не препятствует роботу отправить спам. На этом моя участь окончена, я сделал все, что мог. Удачи, она вам точно понадобится Если нажмете на ссылку под словом "Да" в моём сообщении -- увидите. Если не открывается -- вот скриншот https://ibb.co/ffVqpK3
Простите, что надоедаю Вам, но хотелось бы узнать как Вы это сделали. Дело в том, что валидация кода капчи происходит на сервере перед отправкой. Здесь была ошибка PHP: if($_SESSION["cc"] ==$_SESSION["cv"]) { $res["err"]=0; $res["msg"] = $m1; $res["msg"] .= ".<br>Your message has been sent successfully."; $res["msg"] .= "<br>We will contact you promptly."; ... } Изменил на PHP: if(isset($_SESSION["cc"]) && isset($_SESSION["cv"]) && $_SESSION["cc"] == $_SESSION["cv"])
Если у вас все же есть валидация на сервере -- это правильный путь. Только есть вопросы к релизации: откуда берутся параметры в сессии. И почему-то сейчас все время ответ такой: Thank you for your feedback. Unfortunately your message was not sent. Please try again later again
Прежде всего хочу Вас поблагодарить за внимание, которое Вы уделили этой теме. Данные на сервер отправляются из класса через fetch JSON-request. Валидация происходит и на стороне клиента и на сервере. Если сравнение введённого кода на стороне клиента выполняется успешно, то на сервер отправляется fetch POST-request Проверка кода на на сервере блокирует взлом. При этом выдаётся это сообщение. Если Вы на странице введёте данные и код капчи, то формуляр закроется и выйдет нормальное сообщение.
Я добрался до ноутбука и смог посмотреть детальнее. К сожалению, такая реализация не обеспечивает необходимой функциональности. Клиент просит бэкенд сгенерировать капчу и она возвращается в отрытом виде: Код (Text): curl -X POST -d '{"nChars": 6}' https://www.alto-booking.com/developer/captchaCV/feedback/ {"randomChars":["I",6,"Y","K",4,"A"],"rightCode":"i6yk4a"} За пару запросов ChatGPT помог мне быстро собрать робота: PHP: <?php // Функция для извлечения кук из заголовков ответа function extractCookies($header) { $cookies = []; // Разбиваем заголовок по строкам $lines = explode("\r\n", $header); foreach ($lines as $line) { if (preg_match('/^Set-Cookie:\s*([^;]+)/i', $line, $matches)) { $cookies[] = $matches[1]; } } // Собираем куки в одну строку для заголовка Cookie return implode('; ', $cookies); } $url = 'https://www.alto-booking.com/developer/captchaCV/feedback/'; // 1. Отправляем GET-запрос и получаем заголовки вместе с телом ответа $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HEADER, true); $response = curl_exec($ch); // Определяем размер заголовка для разделения заголовков и тела $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE); $header = substr($response, 0, $header_size); $body = substr($response, $header_size); curl_close($ch); // Извлекаем куки из заголовков $cookies = extractCookies($header); // Функция для выполнения POST-запроса с заданными данными function doPost($url, $postData, $cookies = '') { $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Cookie: ' . $cookies ]); curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); $response = curl_exec($ch); curl_close($ch); return $response; } // 2. POST-запрос с запросом капчи $captcha = json_decode(doPost($url, json_encode(['nChars' => 6]), $cookies), true); // 3. POST-запрос с капчей doPost($url.'?', json_encode(['cv' => $captcha['rightCode']]), $cookies); // 4. POST-запрос с данными формы echo doPost($url, ['name' => 'test', 'email' => 'test@test', 'message' => 'test'], $cookies); Результат работы: https://ibb.co/cKJ89YqF
Добрый день! Большое спасибо за повощь в дороботке. Я проверял изменения внесённый в код и Вы выявили их узвимость. Вернул предыдущую версию. Ваш робот выдаёт
Теперь стало еще хуже: роботу теперь достаточно просто отправить два http запроса (cc и cv) с любым кодом: PHP: // 3. POST-запрос с капчей doPost($url.'?', json_encode(['cc' => '111111']), $cookies); // 4. POST-запрос с капчей doPost($url.'?', json_encode(['cv' => '111111']), $cookies); Полный код робота: PHP: <?php // Функция для извлечения кук из заголовков ответа function extractCookies($header) { $cookies = []; // Разбиваем заголовок по строкам $lines = explode("\r\n", $header); foreach ($lines as $line) { if (preg_match('/^Set-Cookie:\s*([^;]+)/i', $line, $matches)) { $cookies[] = $matches[1]; } } // Собираем куки в одну строку для заголовка Cookie return implode('; ', $cookies); } $url = 'https://www.alto-booking.com/developer/captchaCV/feedback/'; // 1. GET-запрос и получаем заголовки вместе с телом ответа $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HEADER, true); $response = curl_exec($ch); // Определяем размер заголовка для разделения заголовков и тела $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE); $header = substr($response, 0, $header_size); $body = substr($response, $header_size); curl_close($ch); // Извлекаем куки из заголовков $cookies = extractCookies($header); // Функция для выполнения POST-запроса с заданными данными function doPost($url, $postData, $cookies = '') { $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Cookie: ' . $cookies ]); curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); $response = curl_exec($ch); curl_close($ch); return $response; } // 2. POST-запрос с запросом капчи json_decode(doPost($url, json_encode(['nChars' => 6]), $cookies), true); // 3. POST-запрос с капчей doPost($url.'?', json_encode(['cc' => '111111']), $cookies); // 4. POST-запрос с капчей doPost($url.'?', json_encode(['cv' => '111111']), $cookies); // 5. POST-запрос с данными формы echo doPost($url, ['name' => 'test', 'email' => 'test@test', 'message' => 'test'], $cookies);
Ну я добавил установку user-agent и теперь проходит. Код (Text): curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'User-Agent: Robot', ]); Вы "лечите" не то. Дело не в конкретном роботе. Тут принцип неверен. 1. Код капчи должен генерироваться только на сервере. 2. На клиент передаваться должно либо изображение с кодом, либо какие-то опорные данные, по которым можно нарисовать капчу (капчи бывают не только формата ввода кода с изображения). Но ни в коем случае не сам код или любые данные, по которым его можно восстановить. 3. Ну и с клиента код не должен устанавливаться (cc и cv).
Это была временная заглушка, но по хошему в curl нужно имитировать браузер. Я про cc и cv понял поэтому сделал вариант2, Работаю дальше. За Ваш робот ещё раз спасибо. Пригодится для тестирования.
по хорошему нужно делать как пишет вам @brevis формировать изображение капчи на сервере..... клиент не должен знать его в открытом или другом виде ну и соответственно потом проверять так-же на сервере
Добрый день! Большое спасибо! Я акцептировал все замечания, доработал код и протестировал роботом разработанным коллегой brevis Актуальный результат PHP: Array ( [cc] => grkZ_w ) Array ( [err] => 1 [msg] => Thank you for your feedbackThank you for your feedback. Unfortunately your message was not sent. Please try again later again ) Робот PHP: <?php // Функция для извлечения кук из заголовков ответа function extractCookies($header) { $cookies = []; // Разбиваем заголовок по строкам $lines = explode("\r\n", $header); foreach ($lines as $line) { if (preg_match('/^Set-Cookie:\s*([^;]+)/i', $line, $matches)) { $cookies[] = $matches[1]; } } // Собираем куки в одну строку для заголовка Cookie return implode('; ', $cookies); } $url = 'https://www.alto-booking.com/developer/captchaCV/feedback/index.php'; // 1. Отправляем GET-запрос и получаем заголовки вместе с телом ответа $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HEADER, true); $response = curl_exec($ch); // Определяем размер заголовка для разделения заголовков и тела $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE); $header = substr($response, 0, $header_size); $body = substr($response, $header_size); curl_close($ch); // Извлекаем куки из заголовков $cookies = extractCookies($header); // Функция для выполнения POST-запроса с заданными данными function doPost($url, $postData, $cookies = '') { $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Cookie: ' . $cookies ]); curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); $response = curl_exec($ch); curl_close($ch); return $response; } // 2. POST-запрос с запросом капчи $captcha = json_decode(doPost($url, json_encode(['nChars' => 6]), $cookies), true); echo "<pre>"; print_r($captcha); // 3. POST-запрос с капчей doPost($url.'?', json_encode(['cv' => $captcha['cc']]), $cookies); // 4. POST-запрос с данными формы print_r(json_decode(doPost($url, ['name' => 'test', 'email' => 'test@test', 'message' => 'test'], $cookies),true));
Вы делаете ерунду. Либо вы действительно не понимаете, либо намеренно зачем-то убеждаете себя, что делаете не ерунду. Кодирование на клиенте никак не поможет. Добавляем одну функцию и робот опять работает: PHP: <?php // Функция для извлечения кук из заголовков ответа function extractCookies($header) { $cookies = []; // Разбиваем заголовок по строкам $lines = explode("\r\n", $header); foreach ($lines as $line) { if (preg_match('/^Set-Cookie:\s*([^;]+)/i', $line, $matches)) { $cookies[] = $matches[1]; } } // Собираем куки в одну строку для заголовка Cookie return implode('; ', $cookies); } function dec($strIn) { $A = str_split("V2SMJNZHD9KF4I6E13OW8LPBTAQCX5Y7GUR"); $outStr = []; $arr = str_split($strIn); foreach ($arr as $value) { $index = ord($value) - 90; $outStr[] = $A[$index]; } return implode('', $outStr); } $url = 'https://www.alto-booking.com/developer/captchaCV/feedback/index.php'; // 1. Отправляем GET-запрос и получаем заголовки вместе с телом ответа $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HEADER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'User-Agent: Robot', ]); $response = curl_exec($ch); // Определяем размер заголовка для разделения заголовков и тела $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE); $header = substr($response, 0, $header_size); $body = substr($response, $header_size); curl_close($ch); // Извлекаем куки из заголовков $cookies = extractCookies($header); // Функция для выполнения POST-запроса с заданными данными function doPost($url, $postData, $cookies = '') { $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Cookie: ' . $cookies, 'User-Agent: Robot', ]); curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); $response = curl_exec($ch); curl_close($ch); return $response; } // 2. POST-запрос с запросом капчи $captcha = json_decode(doPost($url, json_encode(['nChars' => 6]), $cookies), true); // 3. POST-запрос с капчей doPost($url.'?', json_encode(['cv' => strtolower(dec($captcha['cc']))]), $cookies); // 4. POST-запрос с данными формы print_r(json_decode(doPost($url, ['name' => 'test', 'email' => 'test@test', 'message' => 'test'], $cookies),true));