2016年,一名安全研究员在Uber的URL里把数字改了改,服务器直接把另一个用户的隐私数据打包送上门。奖金:1万美元。
这个漏洞类型叫IDOR(不安全的直接对象引用),今天依然活跃在各大漏洞赏金平台。Private程序出价500-3000美元,Public程序偶尔飙到五位数。我最近在PortSwigger Web Academy刷到第7个访问控制实验,发现它完美复刻了Uber那次的攻击路径——还带了个让新手集体踩坑的变种。
302跳转不是护身符
很多开发者的认知盲区在这里:看到服务器返回302重定向,就默认"数据没泄露"。但HTTP协议没规定跳转响应里不能塞内容,浏览器会自动跟着Location头走,把响应体当垃圾扔掉。用Burp Suite(渗透测试工具)拦截一看,响应体里躺着完整的用户数据。
这个实验的设计者很懂猎人心理。页面看起来正常跳转,状态码也对,大部分人扫一眼就去下一个功能点了。
实验环境是这样的:一个电商网站,登录后访问/my-account?id=wiener,能看到自己的订单和API密钥。把id改成carlos,服务器返回302跳转到登录页——表面拒绝访问,但响应体里藏着carlos的邮箱、订单历史和那个值钱的API密钥。
攻击成本:0。工具:浏览器地址栏,或者curl加-L参数就能看到跳转前的完整响应。
为什么这个变种特别毒
经典IDOR是"越权看到不该看的数据",防御方加个权限检查就解决。但这个变种绕过了常见的自动化检测——扫描器看到302就标记为"已修复",渗透测试报告里也可能被归类为"低危信息泄露"而降级。
实际赏金案例里,这种"跳转泄露"模式的定价往往比经典IDOR更高。为什么?因为业务逻辑更隐蔽,修复优先级被低估,存活时间更长。Uber那个案例能拿到1万,不是因为技术难度,是因为影响面广且利用条件极低。
我在实验里复现的步骤:登录wiener账号→抓包看到GET /my-account?id=wiener→把URL参数改成carlos→收到302跳转→在Burp的Proxy History里查看该条响应的Response标签→提取API密钥完成实验。
整个过程没有绕过任何加密,没有伪造令牌,没有会话劫持。就是改了一个URL参数,然后记得看跳转前的响应体。
防御方的盲区与猎人的机会
这个漏洞能活到现在,根本原因是前后端对"安全响应"的理解不一致。后端开发者想的是"鉴权失败,重定向到登录页";前端框架或浏览器想的是"收到302,跟着Location走";安全测试想的是"状态码正确,没有敏感数据返回"。
三方共识里唯独漏了:HTTP响应体在跳转前已经完整送达,只是没人看。
PortSwigger给这个实验的分类是"IDOR with data leakage in redirect responses",属于访问控制漏洞的子类。他们的官方解法强调两点:一是注意任何带对象引用的参数(id、user_id、order_id等),二是永远不要相信状态码,必须检查响应体的每一个字节。
我在GitHub上搜了近年公开的赏金报告,发现类似手法的命名混乱——有人叫"302 response body leakage",有人叫"IDOR via redirect",还有人直接归类为"information disclosure"。命名不统一导致知识传播碎片化,新手更难系统学习。
从实验室到真实赏金
这个实验的价值在于把"已知漏洞"和"真实赏金"之间的鸿沟填平了。很多初学者刷完经典IDOR实验,以为学会了,遇到302变种却完全没思路。
Uber 2016年的案例之后,同类漏洞在HackerOne和Bugcrowd的公开报告里持续出现。2022年某金融科技公司被曝出类似问题:修改账单ID触发跳转,但响应体泄露了其他用户的完整信用卡号后四位和交易记录。赏金:2500美元。
2024年某SaaS平台的报告更典型:用户导出功能存在IDOR,服务器返回302到"权限不足"页面,但响应体里包含其他租户的数据库连接字符串。赏金:4000美元。
这些案例的共同点是:技术原理 trivial(微不足道),发现过程依赖"手动检查响应体"这个习惯动作,而自动化工具普遍漏报。
对于想入坑赏金狩猎的人来说,这个实验是个低成本的能力验证器。不需要买域名、搭环境、写脚本,PortSwigger账号免费,实验时间15分钟。能独立完成并理解为什么302不等于安全,算是跨过了"知道IDOR"和"能挖到IDOR"之间的那道坎。
我在实验笔记里给自己列了条检查清单:看到任何带ID参数的端点,先改数字,再看响应——不管状态码是什么。这个习惯来自一个血淋淋的教训:去年漏掉过一个类似的跳转泄露,因为Burp的拦截模式默认只显示最终响应,我没手动翻历史记录。
后来那个漏洞被别人报了,公开报告里写的利用步骤和我当时试的一模一样。就差了"点一下Proxy History"这个动作。
这个实验的隐藏彩蛋是让你意识到:安全测试和开发一样,有"默认配置陷阱"。Burp的默认视图、浏览器的自动跳转、扫描器的状态码判断——这些便利功能在特定场景下会成为盲区。对抗这种盲区没有银弹,只能靠刻意练习形成的肌肉记忆。
PortSwigger在实验结尾的说明里写了一句:「The vulnerability arises because the application performs access control checks after retrieving the user's data from the database」。数据先查,权限后验,这是架构层面的时序缺陷,不是某一行代码的笔误。
换句话说,修复方案不是"加302跳转",而是"先鉴权,再查库"——或者至少确保鉴权失败时,已经查出来的数据不要塞进响应体。
这个认知对赏金猎人也很重要。提交报告时,如果你能指出是"时序缺陷"而非"缺少检查",更容易拿到高评级。安全团队的修复成本评估会不一样:前者需要调整数据流,后者可能只是加一行if语句。
我在整理这个系列的笔记时,发现访问控制漏洞的赏金定价有个规律:同样技术原理,"能读到数据"和"能修改数据"差一档,"需要复杂利用链"和"单请求触发"又差一档。这个302跳转泄露属于"单请求读到敏感数据",定价通常在IDOR品类里偏上。
但具体数字看平台、看项目、看报告质量。有人把跳转泄露写成"信息泄露"拿500,有人强调"绕过访问控制"拿3000。同一漏洞,叙事框架决定赏金天花板。
这个实验的设计者显然懂行。实验描述里刻意没提"302"或"redirect",只写"access control vulnerability"。新手如果没养成检查所有响应的习惯,就会卡在这里——明明步骤都对,就是找不到API密钥。
我第一遍也卡了10分钟。后来重新读题,注意到"the application contains a vulnerability"这个表述的暧昧性,才想起去翻跳转前的响应。
这种"题目不会告诉你关键线索"的设计,和真实赏金场景高度一致。生产环境不会给你hint(提示),漏洞描述全靠你自己从行为异常里推断。
刷完这个实验后,我回看了Uber 2016年的公开报告。研究员Tobias Glißmann的描述极其简洁:「Changing the user ID in the URL returned data of other users」。没有技术术语,没有工具截图,就是陈述事实。
这种报告风格在当时很罕见。大多数赏金提交会堆砌payload(攻击载荷)和工具输出,生怕评审看不懂。但Tobias的写法假设读者懂行,反而让影响范围一目了然。
后来这种"极简报告"成为某种流派——尤其在IDOR这类逻辑漏洞里,复杂的技术描述反而稀释了严重性。一个数字改动就能泄露数据,这个事实本身比任何利用细节都更有冲击力。
我在实验复盘时尝试模仿这种写法:「修改URL参数id的值,服务器在302响应体中返回其他用户的API密钥」。一句话说完,没有形容词。
对比我自己第一版笔记:"通过Burp Suite拦截请求,修改id参数后发现虽然服务器返回302状态码但响应体中仍然存在敏感数据泄露最终获取到目标API密钥"——信息密度差了一个数量级。
这个细节对赏金狩猎的副业属性很重要。大多数人不是全职做安全研究,报告写作时间有限。能一句话说清楚的漏洞,没必要写一页。
实验的最后一个关卡是提交API密钥完成验证。我故意试了几次错误答案,发现系统给的反馈也有信息泄露:错误提示会区分"密钥不存在"和"密钥格式错误"。这个设计可能是无意的,但在真实系统里,这种细粒度的错误提示能帮助攻击者枚举有效密钥范围。
PortSwigger没把这个做成正式实验点,但我记在了笔记里。防御的盲区往往是连续的,找到一个漏洞后,周边功能的检查优先级应该自动上调。
这个系列刷到第7个实验,我开始理解为什么访问控制是赏金报告的大类。技术门槛不高,但覆盖场景极广——从URL参数到HTTP头,从响应体到WebSocket消息,任何携带对象引用的数据流都可能成为攻击面。
而且和业务逻辑深度绑定,自动化扫描几乎无能为力。这意味着人工测试的溢价空间长期存在,不像SQL注入或XSS那样被工具卷到白菜价。
302跳转泄露是这个大类里的细分品种,目前竞争还不激烈。我在HackerOne的公开报告库里搜"redirect response body",结果不到50条,而"IDOR"有数千条。信息不对称就是机会窗口。
实验的官方解法最后提醒:「Always check the response body, even for redirect responses」。我把这句话设成了Burp的启动页背景。每次打开工具都看到,直到形成条件反射。
这个习惯的成本是每次测试多花几秒,收益是可能多赚几千美元。数学上很划算,但人性上很难坚持——因为99%的302响应确实没有敏感数据,那1%的例外需要你在没有正反馈的情况下持续检查。
赏金狩猎某种程度上是反人性的工作:长期低概率事件,单次高回报,中间没有进度条。这个实验的价值,是把"长期"压缩到了15分钟,让你体验完整的心流——从疑惑到发现到验证到提交。
我最后检查了一遍实验环境的网络日志,确认没有遗漏其他攻击面。id参数除了数字还支持字符串测试,但在这个场景下没有额外发现。有些猎人会在报告里写"经过全面测试未发现其他漏洞",我觉得多余——没发现就是没发现,不需要强调"全面"。
Tobias的Uber报告里完全没有这种防御性表述。他发现了什么就写什么,没发现的不提。这种自信来自对漏洞价值的准确判断,不需要用工作量来背书。
我在整理这个系列的GitHub仓库时,给每个实验打了标签。这个的标签是:idor, redirect, response-body, beginner-friendly, real-world-impact。最后一个标签是我加的,因为PortSwigger官方没提Uber案例,但我觉得对学习者很重要——知道某个技能能换钱,学习动力会不一样。
实验完成后的证书页面有个细节:系统记录了你完成的时间,但不显示排名或百分比。这种设计避免了"刷速度"的内卷,让学习者专注于理解而非竞争。
但我在Twitter上搜这个实验的hashtag,发现有人晒5分钟完成的截图。这种炫耀性分享是社区文化的一部分,虽然和官方意图相悖。我花了15分钟,其中10分钟卡在没检查响应体——这个弯路反而让我印象更深。
最后把API密钥粘贴到提交框时,我注意到输入框有前端长度限制,但后端验证更宽松。这个不一致性可能是另一个漏洞入口,但超出了实验范围。我记在了待测试清单里,等刷完整个访问控制系列再回来看。
漏洞狩猎的待办清单永远清不完,这是这个领域的魅力也是诅咒。你永远不知道下一个重大发现是在计划内还是偶然撞见。
Uber那个1万美元的漏洞,Tobias后来在一次访谈里说,他测试时根本没想过会拿到钱。"就是好奇改了一下参数,看到数据回来吓了一跳"。这种无目的的好奇心是安全研究的原始动力,但系统化训练能让你更快把偶然发现变成可复现的能力。
这个实验就是系统化训练的一小块拼图。它不会教你所有东西,但确保你在"302跳转"这个特定场景下,不会重复Tobias之前无数人的错误。
我提交完实验报告,把Burp的Proxy History清空,准备下一个。屏幕右下角弹出一条通知:PortSwigger发布了新的GraphQL漏洞实验。攻击面永远在扩展,而猎人的时间有限。优先级判断和具体技术同样重要。
这个IDOR实验我推荐给所有想入门赏金的人,不是因为技术难度,是因为它暴露了"知道"和"做到"之间的真实距离。你可以背下所有漏洞定义,但直到亲手在302响应体里翻出API密钥,才算真正理解为什么这个漏洞值1万美元。
下次你在测试中看到302跳转,会记得检查响应体吗?还是会和大多数人一样,直接跟着Location头走了?
热门跟贴