安全工具:使用 BurpSuite Turbo Intruder 插件进行暴力破解

  Turbo Intruder是BurpSuite的第三方插件,该插件能利用其内置的或自行编写的Python脚本实现一些BurpSuite Inturder模块无法实现的功能,且由于其性能优秀,主要用于大量HTTP请求和测试条件竞争漏洞场景中。

  参考:Trubo Intruder的Github主页BurpSuite官方网站关于Turbo Intruder的文章

  在BurpSuite拓展应用商店中,搜索Turbo Intruder安装即可(注:需要最新版BurpSuite,旧版本可能提示无法安装)

image-20230921163004815

  安装完成后可在BurpSuite最上方功能栏自定义Turbo Intruder字体大小等设置。

  用户可参考Turbo Intruder中自带的Python配置脚本或访问Github示例脚本,修改并实现特定功能。

  一般来说,通过Python脚本配置Turbo Intruder至少需要如下两个函数及其子内容:

  • queueRequests():用于创建请求队列
    • engine = RequestEngine():用于配置数据包发送引擎
    • engine.queue(request, key):将字符填充至HTTP请求包中并通过引擎发送,
      • 第一个参数是要重放的数据包,此处为target.req即发送至Turbo Inturder的数据包,也可以自定义数据包,直接复制整个数据包并作为字符串,参数填写字符串名称即可。
      • 第二个参数是要填充的内容(此参数可选),若前面参数的请求数据包中存在要填充的位置(使用 %s 代替),该参数就会填充至数据包响应位置,若有多个要填充的位置,需要将填充的数据组合为列表后,作为该参数传递即可。
  • handleResponse():用于处理响应数据包
    • table.add(req):用于将满足条件的响应数据包添加至前端展示列表中

  最基本的Python配置脚本如下:

python

# basic.py

# 创建请求队列
def queueRequests(target, wordlists):
    # 配置引擎参数
    engine = RequestEngine(endpoint=target.endpoint,	# endpoint为上面数据包中所有使用'%s'填充的位置
                           concurrentConnections=5,		# 并发连接数(同时发送多少个数据包)
                           requestsPerConnection=10,	# 每次连接请求数(在一个TCP连接中发送多少请求)
                           pipeline=False				# HTTP pipelining(多个连续的请求无需等待响应即可发送)
                           )
	# 自定义endpoint的字典文件路径
    for word in open('C:\Users\NOA\Desktop\users.txt'):
        # 调用数据包发送引擎,发送数据包
        engine.queue(target.req, word.rstrip())

# 处理响应
def handleResponse(req, interesting):
    # currently available attributes are req.status, req.wordcount, req.length and req.response
    # 可以根据响应包的状态,添加至前端显示结果(table)中。
    if req.status != 404:
        table.add(req)

  用户还可以通过使用装饰器快速对响应数据包进行处理,参考Github Turbo Intruder Decorators

  以PortSwigger靶场中用户名枚举为例,该漏洞通过给出的用户名密码列表进行登录暴力破解,以用户名暴力破解为例,可根据登录包响应长度判断用户名是否存在,该漏洞通过BurpSuite的Intruder模块可以解决,此处使用Turbo Inturder以演示其基本用法。

  将需要重放的数据包发送至Turbo Inturder中:

image-20230922091944081

  打开Turbo Intruder窗口后,上方HTTP请求部分,使用 %s 填充要进行暴力破解的位置。下方选择系统预设的Python脚本basic.py,自行修改脚本参数(如连接数、每次连接的请求数、填充位置的字典、响应处理等)后,点击最下方的Attack进行攻击。

image-20230922092639875

  点击Attack后会刷新当前窗口,显示攻击进度及结果,此处点击Length对相应包进行长度排序,发现与其他数据包长度存在差异的包,该请求包中的用户名即为实际存在的用户名。

image-20230922093117225

  如果想要重新设置上述攻击请求,点击最下方Halt,然后点击相同位置的Configure即可返回请求编辑页面。

  条件竞争漏洞需要找到“冲突”,即对共享资源执行两个/多个并发操作。

  以PortSwigger靶场:通过条件竞争漏洞绕过速率限制为例:

  漏洞分析:正常手工测试,同一个账号连续3次登录失败会锁定账号1分钟。但提交账号登录和账号登陆失败计数器之间存在条件竞争,可以通过短时间内提交多次登录请求,干扰账号登录失败计数器。

  先不使用Turbo Intruder,使用BurpSuite中的Repeter模块测试条件竞争漏洞:

  1. 将数据包发送至Repeter模块,使用Ctrl+R将该数据包复制多份,然后将这些数据包添加至组中:

    image-20230922143147096

  2. 点击左上角橙色Send按钮的下拉列表,选择**Send group in parallel(single-packet attack)后,点击Send group(parallel)**发送数据包。

    image-20230922143305039

  3. 观察到“Invalid username or password”的数据包响应大于3个,后续数据包才出现“You have made too many incorrect login attempts. Please try again in 48 seconds”即证明:但提交账号登录和账号登陆失败计数器之间存在条件竞争漏洞,可以通过短时间内提交多次登录请求,干扰账号登录失败计数器。

    注:下面的截图是后续补的,所以和上面的图在请求体内容中可能不同,但漏洞是同一个。

    image-20230922144852115

    image-20230922144902398

    image-20230922144925094

    image-20230922144940308

  但问题是:上述数据包都是复制的同一个数据包,提交的密码也都是同一个。且上述操作使用的是Repeter模块,BurpSuite中用于暴力破解的Intruder模块暂不支持Single Package Attack。故需要使用Trubo Intruder进行暴力破解攻击。

  1. 将数据包发送至Turbo Intruder中,设置占位符,自定义配置Python脚本如下:

    python

    # 创建请求队列
    def queueRequests(target, wordlists):
    	# 单包攻击(single-packet attack):用于条件竞争漏洞
        # 如果攻击目标支持HTTP2协议,使用Engine.BURP2引擎并设置并发连接数为1。
        engine = RequestEngine(endpoint=target.endpoint,
                               concurrentConnections=1,
                               engine=Engine.BURP2
                               )
    
        # 从剪切板读取用户密码列表
        passwords = wordlists.clipboard
        # 使用用户密码列表中的每一项构造请求队列
        # gate "参数会在调用 engine.openGate() 之前暂缓执行每个请求的最后部分(最后一字节?)
        for password in passwords:
            engine.queue(target.req, password, gate='1')
        # 当请求队列被构建好后
    	# 调用engine.openGate(),发送指定gate中的所有请求
        engine.openGate('1')
    
    # 处理响应:将响应结果添加至前端显示列表中。
    def handleResponse(req, interesting):
        table.add(req)
  2. 复制密码字典到剪切板(因为上面的代码中需要从剪切板读取字典),点击最下方Attack开始攻击。

    image-20230922150233874

  3. 开始攻击后,根据HTTP响应代码和响应包长度可以判断是否成功,此处302重定向即证明“12345678”为正确密码。

    image-20230922150335189