这篇文章是我最喜欢的发现之一,因为这是一个非常意想不到的漏洞。
我在测试一个电子商务网站,范围内有两个资产:target.com
和 admin.target.com
。
target.com
是面向用户的门户,用户可以在此购买商品。而 admin.target.com
则是卖家的管理门户,卖家可以在此列出商品、跟踪订单、查看客户信息等。
我正在测试 IDOR(不当直接对象引用)和访问控制。通常,我使用 Autorize 工具来进行测试。
如果一个权限较低的用户能够访问管理端点,Autorize 将会标记为“Bypass”。
img
将普通用户的 Cookie 从 target.com
放入 Autorize 中,我正在使用 admin.target.com
检查普通用户是否可以访问管理端点。
在我的测试过程中,发生了一些异常情况。
每次我访问端点:
https://admin.target.com/orders
,都会发出以下 GraphQL 请求。
POST /graphql
Host: admin.target.com
{"operationName":"GetOrders","variables":{"shop_id":"X"},"query":"query X"}
响应包含了我商店的所有订单信息。这是一个预期的行为。
然而,奇怪的是,Autorize 将该端点标记为“已绕过”,这意味着即使是普通用户也能够发出此请求并访问我商店的订单信息。
但是,当我将该请求发送到重放器并尝试使用普通用户 Cookie 发出请求时,却出现了错误。
img
Autorize 说绕过了,但重放器却说禁止。
我以为这是 Autorize 的一个故障,于是继续测试。
在整个测试程序的一周内,这种情况一直发生。
Autorize 一直显示 GetOrders
端点为“已绕过”,但当我将请求发送到重放器进行测试时,却给出了 403 forbidden
的错误。
在这一点上,我确信这不是 Autorize 的问题,而是我遗漏了什么。
然后我明白了。
Autorize 和重放器之间唯一的区别是时间间隔。
尽管它们都有相同的 Cookie/令牌,但 Autorize 是立即调用管理员端点,而我从重放器发出的请求则需要一些时间。
为了验证我的理论,我使用管理员令牌对 GetOrders
端点进行了请求。
POST /graphql
Host: admin.target.com
Auth: Bearer admin
{"operationName":"GetOrders","variables":{"shop_id":"X"},"query":"query X"}
然后,我立即使用用户令牌对同一个请求进行了测试。
POST /graphql
Host: admin.target.com
Auth: Bearer user
{"operationName":"GetOrders","variables":{"shop_id":"X"},"query":"query X"}
到我的惊讶,我能够获取该商店的所有订单信息,包括客户详细信息。
问题
所以发生了什么: 服务器在大约 3 到 4 秒的非常短暂的时间内缓存 GetOrders
响应。
因此,如果攻击者在正常商店管理员使用其管理门户时同时发出请求,攻击者将能够仅使用 shop_id
获取任何商店的所有订单/客户信息。
shop_id
是一个公开可访问的 ID。
利用
创建一个简单的 bash 脚本,该脚本将在一天内持续请求 GetOrders
端点。
每当管理员访问其门户时,订单/客户信息会在 3 到 4 秒的窗口内缓存,允许攻击者获取它们并绕过所有访问控制限制。
概念验证(POC)
我让intruder使用用户令牌向 GetOrders
端点发送请求。
由于实施了访问控制,最初它给出了 403 forbidden
响应。
img
与此同时,我作为 adminUser
登录到 admin.target.com
并正常访问 admin.target.com/orders
。
此时,针对 GetOrders
的 GraphQL 请求在后台代表管理员发出,该请求可在 3 到 4 秒内进行缓存。
最终,缓存的响应被同一个先前返回 403
错误的 intruder标签获取。
img
该问题被评估为严重,并在几小时内迅速解决。
img
无 偿 获 取 网 安 资 料:
申明:本账号所分享内容仅用于网络安全技术讨论,切勿用于违法途径,所有渗透都需获取授权,违者后果自行承担,与本号及作者无关