freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

burpsuite官方靶场之验证篇
2023-08-22 03:28:59

0.写在前面

免责声明:涉及到的所有技术仅用来学习交流,严禁用于非法用途,未经授权请勿非法渗透。否则产生的一切后果自行承担!

1.基于密码登录的验证漏洞

1.1 基于不同响应的用户名枚举

1.1.1 达成目标

枚举出有效的用户名,然后暴破出相应的密码,最后在访问暴破出来的账户。

为此该靶场提供了相应的字典

1692548275_64e23cb317ca33c2f2d4c.png!small?1692548276150

1.1.2 攻击步骤

第一步,观察该页面,发现了一个醒目的My account1692548299_64e23ccb9b63ec15a1155.png!small?1692548301764


1692548322_64e23ce2a45b2c8aea1d3.png!small?1692548323264


先直接随机输入用户名试试,经过测试发现,必须得满足用户名和密码字段非空才行。

输入如下payload时,发现了一个有意思的报错

# payload

# username
a
# password
1

1692548413_64e23d3dbafdfb80a011f.png!small?1692548414303

因此可以大胆推测此处应该存在用户名枚举。

第二步,对用户名进行暴破。

抓取该登录的数据包,然后把此数据包发送到intruder,并且设置攻击方式以及变量。

1692548463_64e23d6fa91d48110bac5.png!small?1692548464386

1692548474_64e23d7a16791818911ab.png!small?1692548474612


1692548487_64e23d87b94e7522996dc.png!small?1692548488759


由此可以确定其用户名为adsl。

第三步,以adsl用户名为依据,暴破其密码。

根据前面现有的intruder,重新设置Positions的变量,以及重新设置其字典,然后进行暴破。

1692548608_64e23e001c65685e2a9dd.png!small?1692548608975

1692548619_64e23e0bc7c8ccf41fc35.png!small?1692548620377

1692548632_64e23e18d75da02049cc6.png!small?1692548634992

从上图可以得出其密码:freedom


最后尝试其登录

1692548702_64e23e5e8fa2b06a85559.png!small?1692548703192

1.2 巧妙利用不同响应进行用户名枚举

1.2.1 达成目标

枚举出有效的用户名,然后暴破出相应的密码,最后在访问暴破出来的账户。

为此该靶场提供了相应的字典。

1.2.2 攻击步骤

第一步,废话不多说,先看看My account。

1692548726_64e23e7641f819f6d603b.png!small?1692548727267

提交如下payload

# payload

# username
a
# password
1

1692548740_64e23e84c878b74584e99.png!small?1692548741699

尝试探查该关键词在进行暴破的时候,会不会有细微的差距。

第二步,进行一个多用户名,单一密码的暴力破解,该暴力破解需要观察上述图片响应页面的红字部分。1692548832_64e23ee0c757b6a57e83d.png!small?1692548833595

来到payloads,设置第1、2个参数的字典。1692548953_64e23f598c7bd889f89aa.png!small?1692548954062

1692548977_64e23f71459d4c20362d6.png!small?1692548977964

设置要从响应中所提取的值,为了进行观察。1692549019_64e23f9b84faaa73ca2bf.png!small?1692549020151

点击refetch response,然后选中你想要提取的信息即可。

1692549084_64e23fdc87eb884362ef3.png!small?1692549085254

最后观察到,选中部分的信息,和其他是有区别的,在于没有那一个英文句号。

1692549132_64e2400c45185422a033b.png!small?1692549133061

由此可以确定其用户名为apple。

第三步,对密码进行暴破。

回到Payloads,然后设置第一个参数也就是username的字典为apple。1692549151_64e2401f2fd9244dd0417.png!small?1692549151910

然后给第二个参数设置靠谱的字典,开始暴破。

1692549260_64e2408c41167b487c5b5.png!small?1692549261227

1692549288_64e240a8c20f0daa8ceec.png!small?1692549289742

显而易见,用户名为apple,密码为1234。

1692549309_64e240bdba1336ed24a68.png!small?1692549310635


1.3 利用响应时间进行用户名枚举

1.3.1 达成目标

枚举出有效的用户名,然后暴破出相应的密码,最后在访问暴破出来的账户。

给我的登录证书:wiener:peter

为此该靶场提供了相应的字典。

需要注意的是,该靶场使用了基于ip的针对暴力破解的防护。

1.3.2 攻击步骤

话不多说,直接从My account开干。1692549348_64e240e488e9a88d952f9.png!small?1692549350134


第一步,随意提交其账号和密码,主要是观察其报错。

# payload

a:1

1692549510_64e24186c24e0a42868d4.png!small?1692549511743

但看这一个报错信息是无法对用户名进行枚举的。

第二步,尝试提交大量的用户名和同一个密码,试图观察出在不存在的用户名和已存在的用户名之间的区别。

发送数据包至intruder,设置好相应的攻击方式,攻击的参数,相应的字典,以及要从响应中提取的关键词即可。

1692549538_64e241a250fe9d635a02f.png!small?1692549539410

1692549549_64e241adcbafb74dfb532.png!small?1692549550379

从上图可以发现,我们对用户名尝试的太频繁。目前可以推断出,因为对频繁请求其用户名有了保护措施,导致我们并不能观察出正确的用户名和不正确的用户所响应的内容的区别。

现在我们需要分析一下这个保护措施,到底是基于一个什么样的行为生效的呢,以及它是通过什么样的方法让攻击者不能再进行攻击?

首先,我们访问该靶场的时候是处于一个非登录的状态的;并且我上述的攻击行为是对大量的用户名进行了一次登录尝试。基于此,该网站目前对我这个行为的防护措施肯定不是基于账户对我进行锁定的,而是检测到我有高频次发起登录请求的动作,直接对我的出口ip进行了封锁。那么接下来尝试对次防护措施进行绕过。

第三步,绕过对ip进行封锁的防护。在进行绕过的时候,引入一个burp插件——BurpFakeIP。

抓取登录的数据包,然后点击右键选择Extension下面的fakeip然后加入随机的ip。

1692549578_64e241ca0c03ed0d70ada.png!small?1692549578925

在intruder界面设置其攻击的类型和要攻击的参数

1692549601_64e241e16919328ff0042.png!small?1692549602258

1692549610_64e241ea6be8a9dcd44d1.png!small?1692549611305

1692549618_64e241f2dcb19f46b1782.png!small?1692549619704

选择settings模块,然后从响应中提取所要观察的关键词,然后开始攻击。

1692550132_64e243f471efb8da5815e.png!small?1692550133471

最后观察其结果,发现其提取的关键词并未有任何的区别,但是针对ip进行封锁已经绕过了(没有You have made too many incorroct login...提示了)。

1692550149_64e244055e933889b2458.png!small?1692550150507


因此,我们得从响应的时间这个角度来对用户名进行枚举了。

第四步,再一次发起和第三步一样的用户名枚举,不过这一次得设置很长的password的参数值长度,并且在观察结果的时候不在提取其响应的关键词,而是添加Response Completed,取其数值最大的作为用户名

1692550170_64e2441a7bf44755e6ab0.png!small?1692550171397

Response Completed在左上方的Columns里面

1692550186_64e2442a0f808c006d018.png!small?1692550186983

第五步,针对att账户进行密码猜解。

1692550199_64e244372d12daf6abefc.png!small?1692550200054

设置要使用的密码字典

1692550252_64e2446c977e091faeb03.png!small?1692550253538

由此可以得知其账号密码为——att:1111

1692550269_64e2447d19d607477c96f.png!small?1692550272176

1692550278_64e244862ca1d254d2dce.png!small?1692550279141

1.3.3 小葵花课堂:X-Forwarded-For

该靶场对高频次登录动作的ip进行了封锁,为何X-Forwarded-For这样的header可以进行绕过?还有其他header有这样的效果么?

X-Forwarded-For是用来获取最初请求的客户端的ip,X-Forwarded-For会记录所经过的代理ip。

X-Forwarded-For: client-ip, proxy-ip1, proxy-ip2, proxy-ip3

这个header存在的意义就是为了获取其真实的ip,那么难道就不能通过Apache或者Nginx自身的配置来达到这个效果么?

如果仅通过自身其配置是不能达到此效果的,而且如果在客户端请求服务器的途中有正向代理、反向代理或者透明代理,或者其他的安全设备,那么会存在一个问题, 就是其代理设备会更改源ip地址,然后在进行发送请求,这就导致最后到达其请求的服务器的时候,其源ip地址已经是上一层的ip地址。而如果有X-Forwarded-For的存在就会解决这一个问题。但是X-Forwarded-For这个header本身就存在一个可以篡改的可能,这就导致攻击者可以伪造该header,以及来伪造其源ip,那么如果存在一个ip封锁的防护方式,就可以通过此方式进行绕过。

1692550354_64e244d28d8e313261a8a.png!small?1692550355702


还有其他的header有这样的效果么?

当使用FakeIP这个插件的时候,会发现它会往数据包插入大量的header。

1692550370_64e244e266ee0efe14977.png!small?1692550371296

X-Forwarded-For
X-Forwarded
Forwarded-For
Forwarded
X-Requested-With
X-Forwarded-Proto
X-Forwarded-Host
X-remote-IP
X-remote-addr
True-Client-IP
X-Client-IP
Client-IP
X-Real-IP
Ali-CDN-Real-IP
Cdn-Src-Ip
Cdn-Real-Ip
CF-Connecting-IP
X-Cluster-Client-IP
WL-Proxy-Client-IP
Proxy-Client-IP
Fastly-Client-Ip
True-Client-Ip




补充:

X-Originating-IP
X-Host
X-Custom-IP-Authorization

1.3.4 其他header

X-Forwarded

该header和前面的X-Forwarded-For是一样的作用,但是区别在于它是用来获取原始请求的主机名和协议的。

X-Forwarded: host=*, proto=https


Forwarded-For

和X-Forwarded-For是一样的,只是Forwarded-For更加的标准化。


Forwarded

Forwarded的作用和X-Forwarded-For是一样的,区别在于它能获取其原始请求的主机头,协议,端口和ip。

Forwarded: for=192.0.2.60;proto=http;host=example.com


X-Requested-With

X-Requested-With用来说明该http请求是用了什么机制发起。

例如:

# 表明发起了一个Ajax请求
X-Requested-With: XMLHttpRequest

# 非规范性用法
X-Requested-With: ip

# 正是因为服务器端没有严格验证这个header,这样的用法可以用来伪造请求的ip


X-Forwarded-Proto

该header传递的是原始请求使用的协议,至于后面跟上ip地址的用法也是属于非规范性的用法。


X-Forwarded-Host

用来获取其原始的主机头。


X-remote-IP

一个非标准的header,用来获取客户端的原始ip。


X-remote-addr

同上。


True-Client-IP

同上。


X-Client-IP

同上。


Client-IP

同上。


X-Real-IP

同上。


Ali-CDN-Real-IP

是阿里云CDN自制的一个请求头,当用户通过阿里云的cdn访问其源服务器是,利用该header可以保留其源ip地址。


Cdn-Src-Ip

cdn服务商自定义的header,作用和Ali-CDN-Real-IP是一样的。


Cdn-Real-Ip

同上


CF-Connecting-IP

cloudflare自定义的一个header,作用同Cdn-Real-Ip、Cdn-Src-Ip、Ali-CDN-Real-IP。


X-Cluster-Client-IP

是负载均衡和集群系统自定义的header,作用也是用来传递真实ip。


WL-Proxy-Client-IP

是weblogic服务器集群中反向代理服务器(weblogic proxy plug-in)自定义的一个header。


Proxy-Client-IP

是一些反向代理服务器自定义的header,作用也是避免ip变为反向代理的ip,获取其原始的ip。


Fastly-Client-Ip

是Fastly CDN自定义的header,作用同上。


True-Client-Ip

是一些反向代理或者负载均衡系统自定义的Header,作用是获取其原始的ip。


X-Originating-IP

同上。


X-Host

同上。


X-Custom-IP-Authorization

一些网站为了安全性自定义的非标准的header,作用是基于客户端ip的访问授权。


1.3.5 小葵花课堂:正向代理、反向代理和透明代理

首先,代理的本质是一个中间件,位于客户端和服务器之间。


正向代理(vpn,科学上网),位于客户端这边。

用来代理客户端访问外网,突破访问限制;对客户端访问进行过滤和缓存;保护客户端的隐私,隐藏其ip。


反向代理(nginx负载均衡等),位于服务器这边。

保护服务器的安全,隐藏其真实的ip;进行负载均衡;对真实服务器进行缓存,以提高访问的速度。


透明代理(防火墙、上网行为管理、路由NAT转发等),位于客户端和服务器之间。透明代理就是字面的意思,它是透明的,看不到其存在,不像正向代理一样需要对代理地址和端口进行配置。还需要注意的是,它会保持原本的ip地址。

加速网络访问,通过缓存提高性能;过滤内容;记录监控网络流量。

1.3.6 参考文档

[burpsuite靶场解答] https://portswigger.net/web-security/authentication/password-based/lab-username-enumeration-via-response-timing

[X-Forwarded-For的一些理解] https://www.nginx.org.cn/article/detail/417

[X-Forwarded-For详解、如何获取到客户端IP] https://blog.csdn.net/philip502/article/details/122356712

[透明代理、正向代理、反向代理原理及区别] https://www.cnblogs.com/-abm/p/9894289.html

[什么是透明代理] https://xtls.github.io/Xray-docs-next/document/level-2/transparent_proxy/transparent_proxy.html#%E4%BB%80%E4%B9%88%E6%98%AF%E9%80%8F%E6%98%8E%E4%BB%A3%E7%90%86


1.4 有缺陷的暴力破解防护之ip封锁

1.4.1 达成目标

暴破其carlos的密码,然后进行登录。给出了一个存在的账户和密码:wiener/peter。

1.4.2 攻击步骤

话不多说,直接开干。

1692550676_64e246145f85677c9960f.png!small?1692550677293


第一步,直接对carlos进行暴破。

1692550701_64e2462d32309ff764045.png!small?1692550702264

1692550709_64e24635d413fff6fcb89.png!small?1692550710885

提取其响应的关键词

1692550721_64e24641d7342a709a49d.png!small?1692550722768

暴破发现,由于提交了大量的密码尝试,导致ip被封锁。

1692550766_64e2466ea6689d10329de.png!small?1692550767729


第二步,尝试利用fakeip插件来进行绕过。

抓取登录数据包,然后添加一个header试图进行绕过。

1692550790_64e24686c6a7590cc3320.png!small?1692550791774

1692550799_64e2468f5119efbd6c457.png!small?1692550800397

发现不能绕过。

1692550825_64e246a987db4098d8cc9.png!small?1692550826490


第三步,通过登录,发现用一账号登录失败3次就会封锁ip,该靶场给了一个存在的用户名和密码,那么可以尝试在尝试carlos的密码之后,在登录存在的账号密码(wiener/peter),看是否能够重置其登录失败的次数。

首先,得先生成一个用户名字典和和一个密码字典。这个用户名字典的用户名就包含了carlos和wiener,这两个用户名得交替出现;密码字典就是在原有的密码字典中插入其wiener的密码。因此必须得做到wiener和其密码(peter)对应。要做到一个carlos猜解密码和一个wiener正常登录交替进行。因此生成相应字典的代码如下:

用户名字典的生成。

# generate str for dict
str1 = 'carlos\n'
str2 = 'wiener\n'

def generate_repeat_dict():
"""base str to generate dict"""
count = 200
str = ''
while count > 0:
if count % 2 == 0:
str = str + str1
else :
str = str + str2
count -= 1
return str

# writelines方法是将字符串列表写入文件,而write是将单个字符串写入文件。
with open ('write file path', 'w') as f :
f.writelines(generate_repeat_dict())
f.close()

生成对应的字典之后,再进行攻击。

# 要插入的字典
payload = 'peter'

# realines,以列表的方式获取每行文本内容
with open('old dict', 'r') as f:
lines = f.readlines()
f.flush()

new_lines = []

for line in lines:
new_lines.append(line.strip()+'\n')
new_lines.append(payload.strip()+'\n')

with open('new dict', 'w') as f:
f.writelines(new_lines)
f.close()

攻击类型选择pitchfork,这样用户名和密码可以使用不同的字典。

1692550944_64e24720be23180cf9727.png!small?1692550945536

还需要注意这里的线程得设置为1,这样才能顺序执行一个针对carlos的密码猜解,一个是wiener的正常登录,保证他们的交替执行。

1692550961_64e2473130949b0646719.png!small?1692550962115

1692550970_64e2473ad656b6eda3ad6.png!small?1692550972086

1692550978_64e247429d79df05ce208.png!small?1692550979426


1.5 利用账户锁定进行用户名枚举

1.5.1 达成目标

枚举用户名,然后暴破密码进行登录。

1.5.2 攻击步骤

第一步,通过观察其返回的响应报错或者响应的时间,来尝试用户名枚举。

观察其响应的报错。

1692550996_64e247545c081e9016dfe.png!small?1692550997222

观察结果,未果。

1692551010_64e247621d4bb3988e99d.png!small?1692551010930

观察其响应时间。

1692551024_64e247700090773852bcf.png!small?1692551024780

也未果。

1692551036_64e2477c05d607a32313a.png!small?1692551036777


第二步,想到该靶场说是利用其账户锁定,那么我有一个大胆的假设:假设多次输入存在的同一个账号的错误的密码会导致其账号锁定,而一个不存在的账号就算是多次输入错误的密码也无任何的反应,那么就可以利用该账户锁定来进行用户名枚举。前提是这个账号锁定不是永久的锁定。

首先,验证一个不存在的账号多次输入一样的密码会有何响应。

1692551077_64e247a59795e6e506c74.png!small?1692551078408

执行一个并发攻击,也代表着是重复的数据包,也就意味着传递的账户和密码是一样的,也就达到了同一个不存在的账户多次输入了错误的密码这一个条件。

1692551087_64e247af29dbd78948100.png!small?1692551087720

对此,没有防护措施,而是显示错误的账户或者密码。

1692551104_64e247c0b04a18ddc83ad.png!small?1692551105474

那么接下来,只需要生成一个针对一个用户名重复好几次的字典,以及一个大量重复的密码字典(这个密码字典不求正确)

# 一个用户名重复五次的字典

with open('存在的用户名字典', 'r') as f:
lines = f.readlines()
f.flush()

new_lines = []

for line in lines:
new_lines.append(line.strip()+'\n')
new_lines.append(line.strip()+'\n')
new_lines.append(line.strip()+'\n')
new_lines.append(line.strip()+'\n')
new_lines.append(line.strip()+'\n')

with open('新生成的用户名字典', 'w') as f:
f.writelines(new_lines)
f.close()
# 对应的完全一样的随机的错误密码

password_list = []

password = '13241nfajf'
count = 0
while count < 504 :
password_list.append(password.strip()+'\n')
count += 1

with open('生成的密码字典', 'w') as f:
f.writelines(password_list)
f.close()

抓取登录数据包,然后使用intruder模块结合生成的字典进行攻击。

1692551133_64e247ddeb954baff6385.png!small?1692551134863

通过观察结果发现,对该账户进行了锁定,这就证明了存在该账户:amarillo。并且从观察其响应发现当尝试登录了三次之第四次就会锁定该账户一分钟。但是有没有可能,虽然账户是锁定状态,一旦尝试到了正确的密码,还是能够登录成功。

1692551153_64e247f1368c3b94a3708.png!small?1692551154046


第三步,对上述的假设进行尝试。

1692551186_64e248126a4fb3af6c97c.png!small?1692551187440

1692551196_64e2481c848859fdfc2c1.png!small?1692551197247

1692551213_64e2482d229cd98e1fa40.png!small?1692551214145

现在得知账户名和密码:amarillo/ginger

1692551227_64e2483b82d7c88bed371.png!small?1692551228422


1.6 暴力破解防护,单个请求多个证书

1.6.1 达成目标

暴破carlos的密码已进行登录。

1.6.2 攻击步骤

一样的登录界面,开干。

1692551244_64e2484c6f3dea8cd7bc7.png!small?1692551245212


第一步,抓取登录的数据包,该数据包传输的json,因此构造出如下的证书。

1692551257_64e248592e645aa10baea.png!small?1692551258120

# 这样的payload在json的语法中是被允许的,但这也意味着,对于网站来说提交了一个密码的列表,针对这个网站它会对密码逐一进行尝试,因而导致其猜解密码成功

{"username":"carlos","password":["123456",
"password",
"12345678",
"qwerty",
"123456789",
"12345",
"1234",
"111111",
"1234567",
"dragon",
"123123",
"baseball",
"abc123",
"football",
"monkey",
"letmein",
"shadow",
"master",
...
"moscow"]}

第二步,右键点击请求,然后选择show response the browser。复制其url然后在浏览器访问。

1692551555_64e249830fa163c439dbe.png!small?1692551556122


2.多因素验证漏洞

2.1 双因素验证的简单绕过

2.1.1 达成目标

该靶场给出了属于自己的账户和受害者的账户:

Your credentials: wiener/peter

Victim's credentials carlos/montoya

虽然获得了账户和密码,但是因为存在双因素认证,需要绕过双因素来访问carlos的账户页面。

2.1.2 攻击步骤

还是这个页面,直接开干。

1692551567_64e2498fe8e667657f7b0.png!small?1692551568846


第一步,因为提供了一个供我们自己使用的账户,因此我们观察一下它的登录流程。

当键入了账户和密码之后,发现回来到一个新的页面,这个页面的url和前面的是不一样的。

1692551587_64e249a37ba15d650c443.png!small?1692551588605

点击Email client会访问自己账户的邮箱,这个登录页面会发送四位的验证码至邮箱。

1692551602_64e249b2088b2cbd1ed65.png!small?1692551603568

键入对于的验证码即登录成功。在这个登录成功的页面,注意其url,发现该url传递了用户名的参数,此时的参数值就是登录的用户名。

1692551730_64e24a321faf633e491c8.png!small?1692551731293


第二步,大胆猜测一下:是否当键入了密码的时候,是否已经处于一个登录的状态了,那么可以尝试直接跳过其接收验证码的页面,直接访问登录后的页面。

登出现在已经登陆的账户,然后登录其carlos。

1692551743_64e24a3f50c8726daa9e1.png!small?1692551744353

在上述页面的url输入框输入/my-account?id=carlos

1692551756_64e24a4c4ed4846177744.png!small?1692551757296


2.2 存在逻辑缺陷的双因素认证

2.2.1 达成目标

Your credentials: wiener/peter

Victim's credentials: carlos

尝试访问carlos的账户页面

2.2.2 攻击步骤

依旧是这个页面,开干。

1692551845_64e24aa5e3e65775dabfb.png!small?1692551846774

第一步,观察其验证的流程。该靶场的验证流程和上一个靶场其实是一样的。因此,在这里我们观察下它的数据包。

剔除不重要的数据包,画框的就是其验证相关的数据包。观察每个验证相关的数据包会发现,它的cookie有一个verify的参数,参数值为用户名。并且get请求login2这个数据包,就是用来请求其验证码的。

1692551863_64e24ab71457586fd2de5.png!small?1692551864697


第二步,获取其get /login2这个数据包,然后更改其cookie的verify的值为carlos,并重放该数据包。

发现能正常返回,但是我们不知道其验证码,但考虑到其验证码为4位,因此尝试暴破。

1692551878_64e24ac6b83dc7e58cdfc.png!small?1692551879737

点击login,抓取该数据包,然后对其验证码进行暴破。

1692551897_64e24ad9a3fbaef8a4810.png!small?1692551898552


1692551907_64e24ae3b9991b30542f4.png!small?1692551908832

1692551930_64e24afa3c3db2543f0e3.png!small?1692551931143

1692551943_64e24b071a2dace52d1ef.png!small?1692551944260

1692551951_64e24b0f0599076272702.png!small?1692551952235


2.3 暴力破解绕过双因素认证

2.3.1 达成目标

Victim's credentials: carlos/montoya

该靶场已经给出了其要攻击的账户和密码。但是由于该登录是一个双因素验证,因此在第二阶段的验证会往该用户的邮箱发送验证码。我们需要做的就是暴破该验证码。

2.3.2 攻击步骤

还是一样的地方,开干。

1692551992_64e24b38c076034bddf34.png!small?1692551993786

在这里直接略过对这个验证机制的分析了,因为它和前面一个靶场的验证机制一样的:第一步输入用户名和密码,第二步输入接收到的验证码即可登录成功。只是在这个靶场中,没有了属于自己的账号,只存在一个攻击目标的账号和密码,因此可以直接通过第一步的验证机制,直接来到第二步验证机制。


第一步,通过登录攻击目标的账号密码,直接来到第二阶段的验证机制,然后点击登录进行抓包尝试暴破其验证码。

1692552018_64e24b525ed5d4b0d3f92.png!small?1692552019191

发现其请求数据包有csrf token,因此重复发包几次,发现返回400状态码。

1692552031_64e24b5fc2aabf28fb5ca.png!small?1692552032919


第二步,虽然知道了该靶场的验证机制,但是对与该靶场的数据包是怎么样的其实是未知的。并且经过上面的步骤发现该靶场发送的数据包多了个csrf的参数。因此我们再从数据传输的角度来看一看该验证机制。

下面的四个数据包就是该靶场双因素认证的关键数据包。我们一个个的数据包进行观察。

1692552064_64e24b80ca72b8485b29b.png!small?1692552065689

第一个数据包,用来请求第一阶段的登录页面,在其响应里面,发现了csrf token。

1692552080_64e24b90dba8123eafae7.png!small?1692552082139

第二个数据包,对第一阶段执行登录操作,发现该数据包传递了csrf参数,该参数值就是上一个数据包响应的csrf的值。该数据包的响应状态码是302,意味着它会进行跳转,也就是下面的第三个数据包。

1692552093_64e24b9d8c6c15591b468.png!small?1692552094991

第三个数据包,用来请求/login2页面,也就是第二阶段的验证页面。观察发现它的响应也有一个csrf。

1692552107_64e24babbc723f131172c.png!small?1692552109313

第四个数据包,对第二阶段执行提交验证码的操作。在提交验证码的过程中发现,还提交了csrf,也就是上个响应的csrf。

1692552119_64e24bb72fc8e659a12d3.png!small?1692552120140

综上,该双因素的验证机制就是在第一阶段进行登录的同时,会提交在该阶段生成的一次性的csrf,在校验账户密码的同时也会校验其csrf。在第二阶段验证其验证码的同时也会验证其提交的csrf。

在了解了其验证机制后, 其实不难发现第一阶段提交账户密码,第二阶段提交验证码都是依赖于它的上一个请求的。那么也就意味着如果要对验证码进行暴破,首先得先保证自己处于通过一阶段验证,然后获取到了上一个数据包的响应的csrf。

那么基于上述的描述,我们必须的使用burpsuite里面的macros。


第三步,针对该验证机制,配置好macros。

macros所在位置。

1692552135_64e24bc7eaec72aaeaa81.png!small?1692552137163

选择add,添加一个macro,然后就会自动弹出Macro Recorder,Macro Recorder主要是用来获取你想要的数据包的(数据包从HTTP history或者从web browser中获取),选择你想要的数据包。在该靶场中,我们刚好需要的就是画框中的数据包,然后点击ok。

1692552212_64e24c1439faf828ec397.png!small?1692552213533

然后就来到了Macro Editor。该Editor罗列了我们需要四个数据包,也依次进行了编号。

经过之前的分析,我们知道第二个数据包的请求参数csrf是从第一个数据包的响应中获取的;第四个数据包的请求参数csrf是从第三个数据包的响应获取的。

1692552227_64e24c237e845864020a7.png!small?1692552228536

因此为了能够让第二个数据包的csrf和第四个数据包的csrf能够获取到其值,我们需要选中第2个数据包/第4个数据包点击右边的Configure item。

1692552244_64e24c344f70d039b0225.png!small?1692552245469

然后就是设置其csrf的处理方式,在第一个选择框中选择Derive from prior response,也就是从先前的响应中获取其值,第二个选择框选择从第几个响应获取,选择完成后点击ok。

1692552261_64e24c455a5abe44b7df1.png!small?1692552262298

配置完成后,点击右下角的Test macro,观察我们的配置能否正常的运行。

1692552272_64e24c5011ed6bea7d8c4.png!small?1692552272951

通过观察其状态码,能够发现其正常运行。

1692552283_64e24c5b901ad795b3bd9.png!small?1692552284947

至此,针对该验证机制的macro配置完毕。


第四步,利用配置好的macro,对验证机制的第二步的验证码进行暴破。

首先,来到setting,然后在Session handling rules这里点击add。

1692552297_64e24c698ae960a1051da.png!small?1692552298519

然后,选中Details,在Rule description这里写下关于该规则的描述,用来分辨不同的规则。在Rule actions这里添加一个行为,针对此靶场选中运行我们之前设置好的macro。

1692552309_64e24c75868a1b28dd149.png!small?1692552310175

接下来选择Scope,Tools scope这里默认就行;在URL scope这里选择你要执行其macro的范围,因此我选择了该靶场双因素认证所涉及到的url。最后点击ok即可。

1692552322_64e24c828138140491f4b.png!small?1692552323338

在配置完毕之后,就是暴破了。回到macro editor,选择第四个数据包,把它发送到intruder模块。

1692552336_64e24c900f4d8691cb5c6.png!small?1692552337225

1692552346_64e24c9a99cf453680234.png!small?1692552347675

在intruder模块需要注意的是,在Resource pool这里,我们得配置成单线程暴破。因为对于此验证码的暴破涉及到多个请求得依次执行才行,如果选择了多线程,就不能保证其顺序,那么csrf的参数值不能进行更新。

1692552363_64e24cab17e0931c98fd7.png!small?1692552363990

结果如下

1692552378_64e24cba5b66ae41a6c2e.png!small?1692552379247

1692552390_64e24cc664509f10a2105.png!small?1692552391264

2.3.3 token

因为这个靶场使用了一个参数叫做csrf,csrf其实就是一个anti-csrf token。因此在这里我们探讨下token。

token就是一串字符串。根据其生成方式,这一串字符串可能是随机值,也有可能是一串有意义的加密值。anti-csrf token就是一串随机值;而jwt里面生成的token就是携带了有意义的信息的加密值。它俩的作用也是有差别的。

随机生成的token,就比如这个anti-csrf token,就是为了防止其请求伪造的攻击,也就是防止csrf(cross-site request forgery 跨站请求伪造)。csrf简单来说就是通过伪造其受害者的请求,来伪造成受害者向服务器发起请求,从服务器的角度看,它和正常的请求并无区别。

而这个anti-csrf token,就是给用户请求中加入了一个随机的值,并且这个值在每次请求时是不一样的,这就意味着,对于用户的整个请求,加入了不可预测的变数,依据这个特征从而抵御csrf。

而jwt里面的token,是对其用户相关的信息进行加密而生成的,当每次访问需要登录后才能访问的页面时,数据包就会携带这个token。

那么,现在问题来了,明明可以通过输入账户密码,然后服务器端生成相应session的方式来验证用户的身份,为什么要偏偏搞出个token?

这是因为,从用户的层面来看,如果每次访问其要验证身份才能访问的网页都要输入其账号密码, 那么严重影响用户的体验;从服务器层面来看,每次都要查询其账户和密码,会对服务器造成一定的负担。并且token是放在用户的浏览器的,而session是要放在服务器的,那就意味着session会占用服务器的内存。

我们还可以考虑一个情况,当服务器需要扩展的时候,也就是不止一台服务器为用户提供同样的服务,如果用session,还会涉及到多台服务器之间同步session,而如果使用token,就会避免这个问题。

注:关于jwt和csrf是什么请自行查阅了解,因篇幅受限,这里就不进行展开了。

2.3.4 参考文档

[Burp Suite宏的用法] https://blog.csdn.net/qq_50785772/article/details/109722186

[如何利用burpsuite的intruder和Macro进行带验证码的密码爆破] https://blog.csdn.net/u013250169/article/details/117327602

[burpsuite官方文档之sessions] https://portswigger.net/burp/documentation/desktop/settings/sessions

[burpsuite官方文档之macro editor] https://portswigger.net/burp/documentation/desktop/settings/sessions/macros


3.在其他验证机制的漏洞

3.1 暴破保持登录状态的cookie

3.1.1 达成目标

Your credentials: wiener/peterVictim's username: carlos

暴破carlos的cookie来访问my account页面。

3.1.2 攻击步骤

还是一样的页面,开干。

可以肯定的是该登录主界面对多次登录请求进行了账户锁定。

1692552451_64e24d03e36a927ddfa56.png!small?1692552452761


第一步,观察主界面发现,它有个保持登录的复选框。这也就意味着它会生成一个持久性的cookie。刚好该靶场给了一个可以正常登录的账户,那么我们可以观察正常用户选择了stay logged in之后,它的cookie的生成方式,如果其cookie的生成方式很明显可以被推断出来,那么就好办了。

1692552464_64e24d10b4d35b10f8a20.png!small?1692552465891

当选中复选框进行登录之后,发现其响应的数据包会有一个set-cookie的header,其中就包含了持久性的cookie。

1692552478_64e24d1e2e9e86b50b0fd.png!small?1692552479203

该cookie是由其用户名:一串32位的字符串经base64编码组成,这个字符串是是密码的md5形式

1692552487_64e24d27e715ae5e5a948.png!small?1692552488811

也就是说这个持久的cookie,是base64(用户名:md5(密码))。


第二步,抓取home页面的数据包,对其cookie的stay-logged-in参数进行爆破。

1692552501_64e24d35e7120b7519c1c.png!small?1692552502919

1692552508_64e24d3cbfe7d2539f90c.png!small?1692552509702

设置其字典,以及对该字典的处理方式

1692552526_64e24d4e50e5f71946d7e.png!small?1692552527104

1692552535_64e24d57d497964435763.png!small?1692552536957

1692552543_64e24d5f9342283ffeed5.png!small?1692552544500


3.2 离线密码破解

3.2.1 达成目标

Your credentials: wiener/peter

Victim's username: carlos

获取carlos的持久性cookie,并且破解其密码。登录carlos账号,并且删除这个账户。

3.2.2 攻击步骤

这次不是针对登录页面开干了。


首先登录给定的账户,抓包发现它的持久性生成cookie和上一个靶场一样。

来到Home页面。

1692552573_64e24d7dd6a9c094fc512.png!small?1692552575651

点进去

1692552589_64e24d8d6b6c231d29fcc.png!small?1692552590610

1692552601_64e24d996ed6052b19896.png!small?1692552602458



1692552609_64e24da1218fa74781297.png!small?1692552610062

来到攻击服务器,查看其日志。

1692644290_64e3b3c24bd1f2dbe9246.png!small?1692644290954

发现cookie。

1692644304_64e3b3d06e2fe6cbebc00.png!small?1692644305824

1692644316_64e3b3dc3593faddacde7.png!small?1692644316964

把该cookie放置到浏览器(在注销的状态下,在home界面进入开发者模式,选中存储,往对应的cookie值放置上面的参数值。)

1692644331_64e3b3eb56269081444e0.png!small?1692644332059

然后点击删除账户,进入到如下页面

1692644340_64e3b3f4b91b3dbcf282c.png!small?1692644341545

因为得到了密码的md5值,那么直接把该md5放到相应的网站进行查询。

1692644350_64e3b3fec620f357dafb1.png!small?1692644355773

1692644367_64e3b40f1e5fefc19bc49.png!small?1692644367760


3.3 重置密码的逻辑缺陷

3.3.1 达成目标

Your credentials: wiener/peter

Victim's username: carlos

重置carlos的密码,然后登录访问My account页面。

3.3.2 攻击步骤

观察My account页面,发现有一个重置密码的功能。

1692644383_64e3b41fc441d961c3919.png!small?1692644384557

因为给我们了一个已知的账户,因此我们对该账户进行重置密码。

在这里提交我们要重置密码的账户,也就是wiener。

1692644426_64e3b44a215be246917f3.png!small?1692644426968

得点开邮件看看。

1692644448_64e3b460750c3f73ee0ff.png!small?1692644449500

观察邮箱发现,提供给了我们一个用于重置密码的临时的Url,该url通过临时的token来识别其用户。

1692644505_64e3b4999f2c589909130.png!small?1692644506640

我们试着输入一个新密码,点击提交,抓包看看。

1692644517_64e3b4a5934bf06e803dd.png!small?1692644518512

该数据包在数据部分提供了用户名参数,我们试着把该参数改成carlos。

1692644526_64e3b4aea53c9bae54bd3.png!small?1692644527510

1692644593_64e3b4f19773639419437.png!small?1692644594587

登录carlos

1692644604_64e3b4fc1ae529598366a.png!small?1692644604716


3.4 经过中间件的密码重置中毒

3.4.1 达成目标

拥有的账户:wiener/peter。

我们需要重置carlos账户的密码,然后进行登录。

3.4.2 攻击步骤

很明显,该页面有个重置密码的功能。

1692644619_64e3b50bebda48c316010.png!small?1692644620887

第一步,来到重置密码的页面,输入我们carlos账户,然后对其进行抓包

1692644630_64e3b5161405975a09f44.png!small?1692644630952


1692644645_64e3b525bfb735838fb7e.png!small?1692644646484

第二步,因为该靶场的重置密码经过了中间件,因此我们为该数据包添加一个header,也就是X-Forwarded-Host。

1692644680_64e3b54832766d57171fc.png!small?1692644681115

1692644732_64e3b57c33f82ff9280ef.png!small?1692644733325


第三步,访问其划线的url,进行重置密码。

1692644744_64e3b5881b5edc13bad8f.png!small?1692644745040

使用重置的密码登录carlos。

1692644752_64e3b5901df79599f244b.png!small?1692644753006

3.4.3 密码重置中毒

3.4.3.1 概念

在弄清楚密码重置中毒之前,我们得先弄清楚正常的密码重置功能是怎么运作的。

正常的密码重置流程如下:

  1. 用户键入想要重置密码的用户名或者email,然后点击密码重置按钮,发送其重置密码的请求。

  2. 该站点会检查其用户是否存在,若存在,该站点会产生一个临时的、独一无二的、高熵值的token(保证其随机、不可预测),它会和后端的账户联系起来。

  3. 该站点会发送一个重置密码的链接email给该用户,分配给该用户的token(也就是第二步的)会以参数的形式放在其url中。其重置的链接形式类似于:https://normalUrl/reset?token=tokenvalue

  4. 当用户点击该重置链接时,站点会检查该token是否有效,以及对应的是哪个用户。当这一切都没问题了,那么用户就会进入重置密码的界面,然后就可以重置密码了。


ok,如上的就是正常的密码重置流程;现在我们来讨论一下密码重置中毒。


密码重置中毒是基于密码重置这一功能产生的(废话- -)。它的攻击方式是攻击者利用其用户的名字点击重置密码生成token,因此会直接向其用户email发送一个带有其token的重置密码请求,但是在生成该请求往其用户发送之前,攻击者可以对该数据包进行截断,并对其发送的http数据包中的host更改为攻击者自己的host。当用户收到其链接进行点击的时候,那么攻击者就能收到其token,从而进行密码重置了。

3.4.3.2 靶场:基本的密码重置中毒

目标:

自己的账户,wiener/peter;我们要攻击的账户,carlos。carlos会无差别的点击所收到的邮件,我们需要做的就是,向carlos发送重置密码的邮件,然后在我们自己的服务器上面接受,重置其密码,然后登录。


观察该页面,发现有一个忘记密码的功能。

1692644791_64e3b5b7f255fb3a590c2.png!small?1692644792729

向carlos发送重置密码的邮件,然后抓取数据包

1692644805_64e3b5c542ad6446b3ef0.png!small?1692644806237

于此同时,来到我们的攻击服务器

1692644813_64e3b5cdd39934dad6e0f.png!small?1692644814837

把该Host复制到截获的重置密码的数据包上面。

1692644821_64e3b5d5bcfd4c1961562.png!small?1692644822724

1692644836_64e3b5e4903657064c5ba.png!small?1692644837576

查看其服务器的日志,发现了一个重置的url。

1692644849_64e3b5f16c916c10839a2.png!small?1692644850481

跳转到重置密码页面。重置完密码之后,用该密码登录即可。

1692644860_64e3b5fc546f9385e61aa.png!small?1692644861333

1692644870_64e3b606ce46b7550fe91.png!small?1692644871365

3.4.4 补充知识:X-Forwarded-Host

该header用来指定客户端发起请求的host指定的初始的域名。

当客户端的请求在经过代理服务器的时候,会存在更改其header的情况,就有可能更改其host,而对于目的主机的web服务器可能会有根据不同的主机名,进行区别对待。这个时候X-Forwarded-Host的存在就有必要了。它会保留原有的host。


3.5 通过改密码进行暴力破解

3.5.1 达成目标

Your credentials: wiener/peter

Victim's username: carlos

改密码功能存在暴力破解漏洞。通过其暴力破解来获取carlos的密码,然后进行登录。

3.5.2 攻击步骤

还是一样的页面,开干。

1692644887_64e3b617f11d56ed60968.png!small?1692644888773


第一步,在登录界面使用wiener进行登陆后,发现了一个改密码的功能界面。

1692644895_64e3b61fbb4cddad1753d.png!small?1692644896555


第二步,对其更改密码功能进行抓包,发现它有username的参数。

1692644901_64e3b625bb3cd47491be5.png!small?1692644902905


第三步,把username的参数值改为carlos,然后暴破其密码。

需要注意的是,我的新密码和确认密码是不一样的,这是因为在不一样的情况下,如果当前密码不正确会显示其当前密码不正确;如果当前密码是正确的情况下会显示新密码不匹配。

1692644907_64e3b62b4ad79fd2e5828.png!small?1692644908076

1692644911_64e3b62f4f939e5fcd571.png!small?1692644912322

1692644916_64e3b6347d944c54356cc.png!small?1692644917073


# 渗透测试 # web安全
免责声明
1.一般免责声明:本文所提供的技术信息仅供参考,不构成任何专业建议。读者应根据自身情况谨慎使用且应遵守《中华人民共和国网络安全法》,作者及发布平台不对因使用本文信息而导致的任何直接或间接责任或损失负责。
2. 适用性声明:文中技术内容可能不适用于所有情况或系统,在实际应用前请充分测试和评估。若因使用不当造成的任何问题,相关方不承担责任。
3. 更新声明:技术发展迅速,文章内容可能存在滞后性。读者需自行判断信息的时效性,因依据过时内容产生的后果,作者及发布平台不承担责任。
本文为 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
  • 0 文章数
  • 0 关注者
文章目录