为了好玩而编写机器人 - 绕过 hCaptcha
简介: 在本文中,您将了解如何轻松绕过验证码和机器人程序保护或以其他方式无效。 我还没有看到关于这个主题的足够好的资源,特别是关于绕过 hCaptcha,所以我决定写这篇文章来展示验证码是多么无效。 该网站每月的页面浏览量超过 2 亿次,应用程序下载量超过 100 万次,您可以使用机器人进行的操纵和诈骗数量是疯狂的(您也需要代理),尤其是在像我这样拥有大量流量的网站上测试。 编写机器人 我去了公司
简介:
在本文中,您将了解如何轻松绕过验证码和机器人程序保护或以其他方式无效。
我还没有看到关于这个主题的足够好的资源,特别是关于绕过 hCaptcha,所以我决定写这篇文章来展示验证码是多么无效。
该网站每月的页面浏览量超过 2 亿次,应用程序下载量超过 100 万次,您可以使用机器人进行的操纵和诈骗数量是疯狂的(您也需要代理),尤其是在像我这样拥有大量流量的网站上测试。
编写机器人
我去了公司的注册页面,它包含了通常的员工、电子邮件、密码、隐私政策,当然还有验证码。
如您所见,验证码是来自一家名为“Intuition Machines Inc”的公司的 hCaptcha,它被大量网站用于“保护”免受机器人、DDoS 攻击等。
我要做的第一件事是使用 undetected-chromedriver;它是一个自定义的 selenium chromedriver,可以修补 chromedriver 的二进制文件。它也可以通过编辑二进制文件手动完成,但在我们的例子中是不必要的。
对于 hCaptcha,我们可以使用名为 2captcha 的服务;这是一种基于人的反验证码服务。该服务通过提供注册 url(例如example.com/signup)和一个站点密钥来工作,然后它将我们的请求发送到他们的系统,他们的一名员工解决了我们的验证码,最后我们得到了验证码令牌。
编写代码
进口:
import logging
import os
from random import randint
from time import sleep
import undetected_chromedriver as uc
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from twocaptcha import TwoCaptcha
创建类并添加机器人的信用:
class Registration:
def __init__(self):
self._email_address = "example@gmail.com"
self._password = "BotsForEver21!"
self.driver = uc.Chrome()
在进行注册之前,我将添加一个新的实用程序方法,该方法将帮助我将电子邮件和密码插入相关表单:
def _insert_element(self, element, element_data, typing_speed=0.4):
try:
ActionChains(self.driver).move_to_element(element).click().perform()
for c in element_data:
element.send_keys(c)
sleep(typing_speed)
except Exception as e:
logger.exception(e)
- typing_speed 用于模拟像用户一样的真实打字(每个字符 0.4 秒)。
添加实用程序方法后,我们就可以开始编写寄存器函数了;我们可以很容易地找到 email 和 password 元素,因为它们有自己的 id(user_email 和 user_password)。
def register_user(self):
try:
self.driver.get("https://www.somebigwebsite.com/signup")
sleep(randint(5, 7))
# insert email
email_element = WebDriverWait(self.driver, 50).until(
EC.presence_of_element_located((By.ID, "user_email"))
)
self._insert_element(
element=email_element,
element_data=self._email_address,
)
sleep(randint(4, 13)) # thinking about a password...
# insert password
password_element = WebDriverWait(self.driver, 50).until(
EC.presence_of_element_located((By.ID, "user_password"))
)
self._insert_element(
element=password_element,
element_data=self._password,
)
sleep(randint(2, 5)) # agree or not?
# agreements
agree_element = WebDriverWait(self.driver, 30).until(
EC.presence_of_element_located((By.ID, "tos_agreement"))
)
agree_element.click()
sleep(randint(2, 3))
except Exception as e:
logger.exception(e)
好的,现在我们已经将机器人凭据插入到表单中,我们已经到了需要解决 hCaptcha 的地步。根据我的经验,解决 hCaptcha 总是比 reCAPTCHA 有点棘手和困难。
为了通过验证码,我们需要获取验证码令牌。
创建一个新函数来解决验证码:
def _solve_captcha(self):
try:
solver = TwoCaptcha(os.getenv("TWO_CAPTCHA_KEY"))
captcha_token = solver.hcaptcha(
sitekey=os.getenv("SITE_KEY"), url=self.driver.current_url
)["code"]
return captcha_token
except Exception as e:
logger.exception(e)
现在回到我们的 register_user 函数,我们可以使用 _solve_captcha() 函数,并注入验证码_token,但是我们应该在哪里注入验证码_token?
让我们打开开发工具并找出答案。在开发工具中搜索“h-captcha”会得到以下信息:
<textarea id="g-recaptcha-response-03i18g8r8ezr" name="g-recaptcha-response" style="display: none;"></textarea>
<textarea id="h-captcha-response-03i18g8r8ezr" name="h-captcha-response" style="display: none;"></textarea>
我将尝试通过将验证码_token 注入 h-captcha-response 元素来以“传统”方式进行操作,并希望这将被接受:
def _inject_captcha_token(self, captcha_token):
try:
self.driver.execute_script(
"""
document.getElementsByName('h-captcha-response')[0].innerHTML = arguments[0]
""",
captcha_token,
)
except Exception as e:
logger.exception(e)
在将验证码_token 注入到 h-captcha-response 后,它应该看起来像这样:
<textarea id="h-captcha-response-09xrd587ap08" name="h-captcha-response" style="display: none;">P0_eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.....</textarea>
即使在注入后,注册按钮也无法点击:
<button id="sign-up-button" disabled="disabled" data-target="captcha.submit sign-up.submit" type="submit" data-view-component="true" class="dark:focus:tw-outline-none dark:focus:tw-text-white dark:hover:tw-bg-primary-400 dark:hover:tw-text-white dark:tw-text-white disabled:tw-opacity-50 focus:tw-outline-none focus:tw-text-white hover:tw-bg-primary-700 hover:tw-text-white tw-bg-primary-500 tw-border tw-border-transparent tw-font-medium tw-inline-flex tw-items-center tw-leading-4 tw-rounded-md tw-text-white tw-justify-center tw-flex tw-w-full tw-py-3.5 tw-text-sm">
Sign up
</button>
让我们让它可点击:
signup_button_element = WebDriverWait(self.driver, 30).until(
EC.presence_of_element_located((By.ID, "sign-up-button"))
)
# make the button clickable:
self.driver.execute_script(
'arguments[0].removeAttribute("disabled");', signup_button_element
)
删除 disabled 属性后,按钮是可点击的,我们可以简单地做:
signup_button_element.click()
我们点击了注册底部,但不幸的是我们得到了“HCaptcha 验证失败”。错误 :(
我们对于它可以做些什么呢?我们的验证码解决方案未被接受。
让我们退后一步,看看手动解决验证码后 html 元素会发生什么,然后我们将尝试将其转换为代码。经过一番研究,我发现了一个有趣的 iframe,它在解决验证码后会发生变化
<iframe src="https://newassets.hcaptcha.com/captcha/v1/5ddf2f3/static/hcaptcha.html#frame=checkbox&id=0ni43p29wple&host=www.findout.com&sentry=true&reportapi=https%3A%2F%2Faccounts.hcaptcha.com&recaptchacompat=true&custom=false&tplinks=on&sitekey=.....:)&theme=light" title="widget containing checkbox for hCaptcha security challenge" tabindex="0" frameborder="0" scrolling="no" data-hcaptcha-widget-id="0ni43p29wple" data-hcaptcha-response="" style="width: 303px; height: 78px; overflow: hidden;"></iframe>
我尝试将验证码_token 注入“data-hcaptcha-response”,但效果不佳,我得到的只是验证再次失败。
这比我想象的要复杂。我又试了一次,我想看看为什么它失败了。在 HTML 中搜索和挖掘之后,我发现了一个新的隐藏元素,一旦成功解决了验证码,就会添加该元素。
<input type="hidden" name="response_token" value="P0_eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...">
现在我知道我所要做的就是将验证码_token 注入到响应_token 中,因此我创建了一个隐藏的输入元素并注入了验证码_token。
def _inject_captcha_token(self, captcha_token):
try:
js_script = f"""
let captchaElement = document.getElementById('captcha')
let inputElement = document.createElement('input');
inputElement.setAttribute('type', 'hidden');
inputElement.setAttribute('name', 'response_token');
inputElement.setAttribute('value', "{captcha_token}");
captchaElement.appendChild(inputElement)
"""
self.driver.execute_script(js_script)
except Exception as e:
logger.exception(e)
我再次运行脚本,我们的机器人注册终于成功了 :)
现在我们所要做的就是确认我们的帐户(当然这也可以很容易地自动化)。
结论
我们看到即使在更大、更“安全”的网站上绕过验证码等安全机制是多么容易。您也可以使用机器人在平台上执行自动化任务。
我希望你喜欢阅读这篇文章!
更多推荐
所有评论(0)