今天依然是在Freebuf首发的一个专题,也是Portswigger最近才出的新专题,主要是由2023美国黑帽大会中的一个议题衍生而来,burp为此还进行了一次重大更新,就是原生支持并发了。
声明
该系列共三篇,26个专题(截止2023.8.10),其中有21个专题的大部分内容已于2021年7-9月首发于安全客,由于某些原因,该系列后续更新部分梨子打算转投Freebuf社区(下称"社区")。因后续更新部分的部分内容为这21个专题中的,故在转投社区时会将更新部分一并加入对应的专题中,所以会与发布于安全客的版本略有出入,会更完整,望周知。
注:该专题为Freebuf首发
本系列介绍
PortSwigger是信息安全从业者必备工具burpsuite的发行商,作为网络空间安全的领导者,他们为信息安全初学者提供了一个在线的网络安全学院(也称练兵场),在讲解相关漏洞的同时还配套了相关的在线靶场供初学者练习,本系列旨在以梨子这个初学者视角出发对学习该学院内容及靶场练习进行全程记录并为其他初学者提供学习参考,希望能对初学者们有所帮助。
梨子有话说
梨子也算是Web安全初学者,所以本系列文章中难免出现各种各样的低级错误,还请各位见谅,梨子创作本系列文章的初衷是觉得现在大部分的材料对漏洞原理的讲解都是模棱两可的,很多初学者看了很久依然是一知半解的,故希望本系列能够帮助初学者快速地掌握漏洞原理。
服务器端漏洞篇介绍
burp官方说他们建议初学者先看服务器漏洞篇,因为初学者只需要了解服务器端发生了什么就可以了
服务器端漏洞篇 - 条件竞争专题
什么是条件竞争?
条件竞争是一种和业务逻辑缺陷密切相关的漏洞。当网站在处理不过来同时发过来的请求时,就会存在多个不同的线程同时与相同的数据进行交互,从而导致应用程序做出匪夷所思的行为。
这里梨子要介绍一个概念,叫"竞争窗口",表示可能发生碰撞的时间段,比如与数据库的两次交互之间的几分之一秒。条件竞争的危害和其他逻辑漏洞相似,是与端点密切相关的。
好了,了解到条件竞争和竞争窗口的概念以后,我们开始今天正式的学习啦!!!
利用条件竞争突破限制
条件竞争最知名的利用类型就是突破某种限制。比如梨子去网购,结账的时候可以使用优惠券,使用优惠券的过程大概是这样的:
检查梨子是否使用过这张优惠券
将折扣应用于购买的商品
在数据库中将优惠券的状态修改为"已使用"
如果梨子后面还想使用这张优惠券,经过上面的流程以后会不让梨子使用这张券。我们看这样一张图应该就可以明白了。
现在思考一下,如果梨子在还没用掉这张优惠券的时候几乎同时发起使用请求两次,会发生什么?还是看这样一张图。
正如我们所见,应用程序通过一个临时子状态进行转换:也就是说,在请求处理完成之前进入然后再退出的状态。这个临时子状态在我们第一次请求时进入,然后在数据库更新完优惠券的状态时结束。这里就会产生一个窗口期,梨子可以在窗口期内多次使用这张优惠券,因为窗口期结束以后才更新优惠券的状态。这种攻击方式可以有很多变种,比如:
多次兑换礼品卡
对产品进行多次评价
提取或转账超过账户余额的现金
重复使用单个验证码
绕过反暴力破解速率限制
突破限制属于"time-of-check to time-of-use" (TOCTOU)缺陷的一种子类型,这个缺陷梨子实在找不到有什么合适的中文解释。
使用Burp Repeater检测和利用突破限制条件竞争
检测和利用突破限制条件竞争的过程比较简单,大概是这样的:
寻找有用的一次性或者限制请求速率的端点
连续快速地多次请求这个端点,看看能不能突破限制
难点就在于寻找所谓的"竞争窗口",这种窗口一般也就几毫秒,甚至更短。我们看下面的图片理解一下:
Burp2023.9添加了一个强大的新功能!!!好诶好诶,这个功能就是让我们可以轻松地发送一组并行请求,从而大大减少网络抖动的影响。Burp会自动调整以适应不同服务器支持的HTTP版本:
对于HTTP/1,它使用经典的末字节(last-byte)同步技术
对于HTTP/2,它使用单数据包攻击技术,这项技术是由PortSwigger Research在Black Hat USA 2023首次演示的哦!!!好厉害呀!!!跟着梨子学到热乎的新技术了吧,嘻嘻嘻。
单数据包攻击可以让我们使用单个TCP数据包同时完成20-30个请求,从而完全消除网络抖动的干扰。像这张图上画的。
虽然有的时候同时发两个请求就可以利用漏洞,但是发送大量这样的请求有助于减轻内部延迟,也称为服务器端抖动。
配套靶场:突破限制条件竞争
这道题是什么呢,要梨子买下那件"Lightweight L33t Leather"夹克才能通关,那怎么办呢?快跟着梨子学起来!!!我们先登录进来。
我靠,只有50刀啊,那怎么办啊,没关系,梨子注意到这个20%的折扣了,梨子可以并发多次,看看是不是可以打很多次折,梨子先把夹克放购物车里,购物车长这样。
梨子要点这个"Apply"才算使用这个促销代码,正常来讲我们只能用一次,我们把拦截打开,然后重复发20个到Repeater里先,然后把这个包丢掉,不要放行,不然就相当于用掉了,这个一定要注意哦。
然后梨子把这20个请求包放到一个请求包组中,这是个新的知识点哦,大家注意听哦。
我们点击这个加号会有个"Create tab group",然后把这20个请求包都选上。
然后我们随便进入一个标签,在Send按钮旁边有个下拉选项,我们选最后一个。
这样burp就会帮我们并行地发出这一组20个请求包了,发射!!!我们现在刷新一下购物车。
成了!!!好家伙,一下子减了这么多,24刀拿下1337刀的夹克!!!激不激动,开不开心!!!
使用Turbo Intruder检测和利用突破限制条件竞争
除了Repeater可以使用单数据包攻击技术外,我们还可以用Turbo Intruder插件实现,这个插件可以直接从BApp Store下载。这款插件扩展性更强,支持自写的python脚本,但是也需要对python有一定的了解才行。如果想要使用Turbo Intruder发起单数据包攻击,梨子需要科普以下几个知识点:
要确保目标支持HTTP/2,单包攻击与HTTP/1不兼容
要为请求引擎设置engine=Engine.BURP2和concurrentConnections=1配置选项。
对请求进行排队时,通过使用engine.queue()方法的gate参数将它们分配给所命名的gate来对它们进行分组。
要发送给指定分组中的所有请求,要使用engine.openGate()方法打开相应的gate。
代码示例如下:
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=1,
engine=Engine.BURP2
)
# queue 20 requests in gate '1'
for i in range(20):
engine.queue(target.req, gate='1')
# send all requests in gate '1' in parallel
engine.openGate('1')
这里我们可以直接用Turbo Intruder内置的模板脚本"race-single-packet-attack.py"
配套靶场:通过条件竞争绕过速率限制
这道题是说,应用程序对暴力破解速率做了限制,我们需要突破这个限制去爆破,我们把登录请求发到Turbo Intruder,编写这样的脚本:
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
)
# assign the list of candidate passwords from your clipboard
passwords = wordlists.clipboard
# 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)
然后我们在password处写入%s设置这里为变量位置,然后复制题目给的密码本,wordlists.clipboard就是会在并发的时候读取我们的剪贴板作为字典,好神奇!!!
然后,Attack!!!
成功了!没成功的小伙伴多试几次哦。然后我们直接把响应发到浏览器就可以了,一定要发响应哦,用账号密码去登的话会失败哦。现在我们就可以删除carlos了!!!
隐藏的多步骤序列
实际上,明面上看是一个请求,但是可能背后需要通过多个步骤的请求序列完成,但是这个序列对于梨子这样的用户是隐藏起来的,在用户侧只能看到进入序列之前和从序列出来即发出请求以及得到响应这两个动作,burp称中间的这个序列为"子状态"。
如果我们能够发现可以与相同数据交互同时交互多次的缺陷就会允许我们利用子状态中的逻辑缺陷来实现某些意想不到的效果,例如突破限制。
例如我们遇到有缺陷的MFA的应用程序的时候,这里我们第一步是输入账号密码,然后后端校验,然后再校验第二种身份信息,但是如果MFA机制出现缺陷的话,会在账号密码正确时即返回有效的用户凭证,即我们无需通过校验第二种身份信息即可访问应用程序及目标账户。这个是梨子在身份验证专题讲过的哦,是不是都忘得差不多了?该打!!!以下伪代码演示了网站是如何受到变种的条件竞争攻击的:
session['userid'] = user.userid
if user.mfa_enabled:
session['enforce_mfa'] = True
# 生成并发送MFA码给用户
# 浏览器跳转到MFA码校验窗口
如上所示,这就是所谓的子状态内部,在这个子状态中,用户暂时拥有有效的登录会话,未强制执行MFA。攻击者可能同时发出一个登录请求和一个指向敏感的端点的请求来利用这个漏洞。
方法论
为了检测和利用隐藏的多步骤序列,burp在这里建议使用以下方法,该方法是从PortSwigger Research的白皮书《Smashing the state machine: The true potential of web race conditions》中总结的,新鲜热乎的知识,快学!!!我们先看这样一个图。
1 - 预测潜在的碰撞
把每个端点都测试一遍是不切实际的。正常映射目标站点后,我们可以通过问自己以下问题来减少需要测试的端点数量:
这个端点的安全性是否至关重要?很多端点不涉及关键功能,因此不值得测试。
有没有碰撞的可能?为了成功碰撞,我们通常需要两个或更多请求来对同一条记录操作,例如密码重置的场景:
上图中的第一个示例,为两个不同的用户请求并行密码重置,这种不太可能出现碰撞,因为它会导致对两条不同的记录的更改,但是,第二种就可以实现两个不同的用户请求编辑同一条记录。
2 - 探寻线索
要探寻线索,我们需要首先对端点在正常条件下的行为进行基准测试,我们可以在Repeater中通过对所有请求进行分组并且使用"Send group in sequence (separate connections)"来测试,这个会按顺序发送分组中的每个包。
接下来,使用单数据包攻击(如果不支持HTTP/2,则使用末字节同步)一次性发送同一组请求,以最大限度地减少网络抖动。我们可以通过使用"Send group in parallel"进行这一步测试,用Turbo Intruder也可以。
任何东西都可能成为线索,只需要寻找我们在基准测试期间观察到的情况是否存在某种形式的偏差就行。包括一个或多个响应的变化,但也可能会产生二阶效应,例如不同的电子邮件内容或后续应用程序行为的明显变化。
3 - 证明这个猜想(concept)
尝试了解正在发生的事情,删除多余的请求,并确保可以复现。
高级的条件竞争可能会导致不寻常且独特的基元,因此想达到最大危害的路径并不是显而易见的。我们应该把每个条件竞争串联起来看,而不是当成单独的漏洞。
多端点条件竞争
也许这些条件竞争最直观的形式是涉及同时向多个端点发送请求的条件。比如线上购物中的经典逻辑缺陷,我们把商品添加到购物车或购物车,付款,然后在强制浏览到订单确认页面之前将更多商品添加到购物车。关于更多业务逻辑漏洞的知识,请还没看过的小伙伴快去梨子之前的专题里补课!!!
当在处理单个请求期间执行支付验证和订单确认时,可能会出现此漏洞的变体。订单状态的状态机可能如下所示:
在这种情况下,我们可以在窗口期(从验证付款到最终确认订单)期间向购物车添加更多商品。
对齐多端点竞争窗口
在测试多端点条件竞争时,即使使用单数据包技术完全相同地同时发送所有请求,也可能会在尝试排列每个请求的竞争窗口时遇到问题。
这种常见问题主要是由以下两个因素造成的:
网络架构引入的延迟 - 例如,每当前端服务器与后端建立新连接时,可能会出现延迟。使用的协议也会产生重大影响。
端点的特定处理引入的延迟 - 不同端点的处理时间本质上有所不同,有时差异很大,具体取决于它们触发的操作。
不要怕,这两个问题都有解决办法的!
连接预热
后端连接延迟通常不会干扰条件竞争攻击,因为它们通常会同等地延迟并行请求,因此请求保持同步。
必须能够将这些延迟与端点特定因素引起的延迟区分开来。实现此目的的一种方法是通过一个或多个无关紧要的请求"预热"连接,看看这是否可以平滑剩余的处理时间。在Repeater中,我们可以尝试将主页的GET请求添加到分组的开头,然后使用Send group in sequence (single connection)发送请求。
如果第一个请求仍然有较长的处理时间,但其余请求现在都在很短的时间内处理,我们可以忽略明显的延迟并继续正常测试。
如果即使使用单数据包技术,仍然在单个端点上看到不一致的响应时间,这表明后端延迟正在干扰攻击。我们可以通过在跟进主要攻击请求之前使用Turbo Intruder发送一些连接预热请求来解决此问题。
配套靶场:多端点条件竞争
这道题还是低价购那件夹克,但是这次没有促销代码了!梨子这里要试着用上面的方法论去寻找解决办法,这也可以是大家寻找任何解决办法的途径!!!这里只用方法论一次,后面还是直接解题的,梨子只是推荐大家学习一下方法论。
预测一个潜在的碰撞
我们先登录并且购买一个礼品卡,从而了解购买流程
考虑一下购物车机制,特别是决定可以订购什么的限制,值得尝试绕过。
从History中,识别能够与购物车交互的所有端点。例如,POST /cart请求将商品添加到购物车,POST /cart/checkout请求提交订单。
将另一张礼品卡添加到购物车,然后将GET /cart请求发送到Repeater。
在Repeater中,尝试发送带或不带会话cookie的GET /cart请求。确认如果没有会话cookie,只能访问空购物车。由此,我们可以推断:
- 购物车的状态存储在会话的服务器端。
- 购物车上的任何操作都取决于会话ID或关联的用户ID。
这表明存在发生碰撞的可能性。请注意,提交和接收成功订单的确认是在单个请求/响应周期内进行的。
请注意,订单验证和确认之间可能存在竞争窗口。这可以让我们在服务器检查是否有足够的商店积分后向订单添加更多商品。
对行为进行基准测试
将POST /cart和POST /cart/checkout请求发送到Repeater。
把这两个标签添加到一个分组中
通过单个连接按顺序发送两个请求几次。从响应时间可以看出,第一个请求始终比第二个请求花费更长的时间。
将主页的GET请求添加到分组的开头。
通过单个连接按顺序发送所有三个请求。请注意,第一个请求仍然需要更长的时间,但是通过以这种方式"预热"连接,第二个和第三个请求现在可以在更小的窗口内完成。
推断这个延迟是由后端网络架构引起的,而不是每个端点各自的处理时间造成的。因此,它不太可能干扰攻击。
从分组中删除对主页的GET请求。
确保购物车中有一张礼品卡。
在Repeater中,修改分组中的POST /cart请求,将productId参数设置为1,即Lightweight L33t Leather Jacket的ID。
再次按顺序发送请求。
如我们所料,请注意订单因资金不足而被拒绝。
证明猜想
从购物车中取出夹克并添加另一张礼品卡。
在Repeater中,尝试再次发送请求,但这次是并行发送。
查看对POST /cart/checkout请求的响应:
如果收到相同的“资金不足”响应,请从购物车中取出夹克并重复攻击。可能需要多次尝试。
如果收到200响应,请检查是否成功购买了皮夹克。
好的,学习了方法论,梨子感觉思路马上就清晰了,虽然看上去很复杂,但是这么一步一步分析下来,感觉没有什么问题是困难的!!!我们就开始解题吧,在购物车里留一个礼品卡。
然后我们把将夹克添加到购物车和结算的包到Repeater并且设置成一个分组,然后选择并发模式发送。
然后,并发!!!成功10刀买到夹克!!!
滥用速率或资源限制
如果连接预热没有任何变化的话,还有办法解决的。使用Turbo Intruder可以引入较短的客户端延迟。但是,由于这涉及将实际攻击请求拆分为多个TCP数据包,因此无法使用单数据包攻击技术。因此,对于高抖动目标,无论设置什么延迟,攻击都不太可能可靠地进行。
相反,我们可以通过滥用常见的安全功能来解决此问题。如果请求发送速度过快,Web服务器通常会延迟处理请求。通过发送大量虚拟请求来故意触发速率或资源限制,可能会导致适当的服务器端延迟。即使需要延迟执行,这也使得单数据包攻击可行。我靠,还能这样的!!!学到了学到了。
单端点条件竞争
将具有不同值的并行请求发送到单个端点有时会触发强大的条件竞争。我们设想一下在用户会话中存储用户ID和重置令牌的密码重置机制。在这种情况下,从同一会话发送两个并行密码重置请求但使用两个不同的用户名,可能会导致以下冲突:
请注意所有操作完成后的最终状态:
session['reset-user'] = victim
session['reset-token'] = 1234
该会话现在包含受害者的用户ID,但有效的重置令牌会发送给攻击者。电子邮件地址确认或任何基于电子邮件的操作通常是单端点竞争条件的比较好的目标。服务器向客户端发出HTTP响应后,通常会在后台线程中发送电子邮件,从而更有可能出现竞争情况。
配套靶场:单端点条件竞争
这道题的场景是这样的,有一封来自carlos@ginandjuice.shop的管理员创建的邀请邮件,默认是谁点击确认谁就变成管理员,如果我们并发发起,幸运的话我这边可能接收到相同的邮件,是不是很神奇!!!这里顺序很重要,要把carlos@ginandjuice.shop的放在第二个,wiener的放在第一个。
然后并发!!!成功收到修改成carlos@ginandjuice.shop的确认邮件。
然后我们就相当于接管了carlos@ginandjuice.shop这个账号,我们就可以删除carlos了!!!
基于会话的锁定机制
某些框架尝试通过使用某种形式的请求锁定来防止意外的数据损坏。例如,PHP的本机会话处理程序模块一次仅处理每个会话的一个请求。发现这种行为非常重要,因为它可能反而会掩盖可轻易利用的漏洞。
如果我们发现所有请求都按顺序处理,请尝试使用不同的会话令牌发送每个请求。
局部构造条件竞争
许多应用程序通过多个步骤创建对象,这可能会引入对象可被利用的临时中间状态。例如,当注册新用户时,应用程序可以在数据库中创建用户并使用两个单独的SQL语句设置其API密钥。这会留下一个用户存在的小窗口,但他们的API密钥尚未初始化。
这种行为为漏洞利用铺平了道路,我们可以注入一个输入值,该值返回与未初始化的数据库值匹配的内容,例如空字符串或JSON中的null,并将其作为安全控制的一部分进行比较。
框架通常允许我们使用非标准语法传递数组和其他非字符串数据结构。例如,在PHP中:
param[]=foo等效于param = ['foo']
param[]=foo&param[]=bar等效于param = ['foo', 'bar']
param[]等效于param = []
原来还可以这么绕过的,摸头震惊!!!Ruby on Rails允许我们通过提供带有key但没有值的查询或POST参数来执行类似的操作。换句话说,param[key]会产生以下服务器端对象:
params = {"param"=>{"key"=>nil}}
在上面的示例中,这意味着在窗口期,我们可能会发出经过身份验证的API请求,如下所示:
GET /api/user/info?user=victim&api-key[]= HTTP/2
Host: vulnerable-website.com
配套靶场:局部构造条件竞争
这道题是想让我们利用条件竞争绕过限制注册使用任意邮件地址注册账号,然后删除carlos用户。我们先看一下注册机制是怎么样的。它仅支持使用@ginandjuice.shop邮箱注册,然后它会发一封注册确认邮件到这个邮箱,但是梨子手里没有这个邮箱的账号,那怎么办呢?
梨子从/resources/static/users.js中发现了一段可能是确认邮件的逻辑代码:
POST /confirm?token=1 HTTP/2
Host: YOUR-LAB-ID.web-security-academy.net
Content-Type: x-www-form-urlencoded
Content-Length: 0
然后梨子尝试对这个token参数进行测试,然后发现:
如果填写任意token,会返回"Incorrect token: "的响应
如果删除这个参数,会返回"Missingparameter:token"的响应
如果token为空值呢,会返回"Forbidden"的响应
那咋整啊!!!好烦。我们现在思考在下面两个动作之间可能存在时间窗口:
提交注册用户的请求时。
新生成的注册令牌实际存储在数据库中时。
这就可能存在一种子状态,null(或等效值)也会被视作有效的注册令牌。空值被禁了,我们可以试一下空值数组:
POST /confirm?token[]=
我们发现发送空值数组会返回"Invalid token: Array"响应,而不是"Forbidden"了,说明它进行到了与未初始化的令牌匹配这一步了。我们开始尝试攻击了,因为用户名注册一次以后就不能用了,所以我们这里需要魔改一下Turbo Intruder的脚本:
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=1,
engine=Engine.BURP2
)
confirmationReq = '''POST /confirm?token[]= HTTP/2
Host: YOUR-LAB-ID.web-security-academy.net
Cookie: phpsessionid=YOUR-SESSION-TOKEN
Content-Length: 0
'''
for attempt in range(20):
currentAttempt = str(attempt)
username = 'User' + currentAttempt
# queue a single registration request
engine.queue(target.req, username, gate=currentAttempt)
# queue 50 confirmation requests - note that this will probably sent in two separate packets
for i in range(50):
engine.queue(confirmationReq, gate=currentAttempt)
# send all the queued requests for this attempt
engine.openGate(currentAttempt)
def handleResponse(req, interesting):
table.add(req)
我们把注册的包发到Turbo Intruder里,然后username设置为变量位,邮箱要以@ginandjuice.shop结尾,脚本替换为上面的,Attack!!!
成了!然后我们用注册时候填的密码peter登录User0即可,然后就可以删除carlos了!!!老carlos太惨了。删的时候看清楚一点,梨子习惯性点最下面那个了,结果把刚注册的号删了,大家注意看啊!!!
时间敏感型攻击
有时候可能找不到竞争条件,但以精确的时间传递请求的技术仍然可以发现其他漏洞的存在。其中一个例子是使用高分辨率时间戳而不是加密安全随机字符串来生成安全令牌。考虑仅使用时间戳随机化的密码重置令牌。在这种情况下,可能会为两个使用相同令牌的不同用户触发两次密码重置。我们可以通过对并发的两个请求计时来判断是否得到由相同时间戳生成的令牌。
配套靶场:利用时间敏感型漏洞
这道题是想让我们重置carlos的密码,因为重置令牌仅通过时间戳生成,所以我们可以通过并发一组两个密码重置请求,这两个请求仅用户名不同,幸运的话,我们可以收到和carlos相同重置令牌的重置邮件,从而可以重置carlos的密码,开干!!!把重置请求包发两个到Rpeater里并且放在一个分组里。我们需要两套会话和csrf token,所以我们需要删掉Cookie然后GET一下重置密码页面来重新获取一套会话和csrf,然后并发!!!如果一次没成功的话需要调整重置用户会话的获取顺序,这里梨子就不讲那么细啦,嘻嘻嘻。
我们将链接复制到浏览器中,如果我们和carlos拿到的重置令牌相同的话,将user修改为carlos是可以成功进入carlos的密码重置页面的。
如何防范条件竞争漏洞?
当单个请求可以通过不可见的子状态转换应用程序时,理解和预测其行为是极其困难的。这使得防御变得不切实际。为了正确保护应用程序,burp建议通过应用以下策略来消除所有敏感端点的子状态:
避免混合来自不同存储位置的数据。
通过使用数据存储的并发功能,确保敏感端点使状态更改原子化。例如,使用单个数据库事务来检查付款是否与购物车价值匹配并确认订单。
作为深度防御措施,请利用数据存储完整性和一致性功能(例如列唯一性约束)。
不要尝试使用一个数据存储层来保护另一层的安全。例如,会话不适合防止对数据库的限制溢出攻击。
确保会话处理框架保持会话内部一致。单独更新会话变量而不是批量更新可能是一种看上去很好的优化,但这是极其危险的。
在某些架构中,完全避免服务器端状态可能是合适的。相反,我们可以使用加密将状态推送到客户端,例如使用JWT。
总结
以上就是梨子去上PortSwigger网络安全学院系列之服务器端漏洞篇新增的条件竞争专题内容啦。这个专题对于现有的知识体系还是很新的技术,梨子希望大家能用心学一学,本专题主要讲了什么是条件竞争、如何利用方法论发现并测试条件竞争漏洞以及如果利用Repeater和Turbo Intruder触发条件竞争漏洞,欢迎大家在评论区还有从各种途径和梨子讨论哦,我们下个专题再见啦!!!