最近在参与某次授权的攻防演练打怪升级时,偶然碰到了一个看似平平无奇的访客管理系统。本以为只是一次走马观花的日常摸鱼,没想到凭借一个微小的逻辑转换,竟牵扯出了高达 30 万+ 的敏感个人信息泄露。
这次实战让我深刻体会到:最高端的漏洞,往往只需要最朴素的利用方式。 今天就和大家硬核复盘一下,我是如何通过一个 IDOR(越权访问)漏洞,撕开目标系统防线的。
0x01 故事背景
故事发生在一个深夜。当时我的目标是一个名为“某单位访客管理系统”的 Web 应用。这类系统大家在大学里或者企业园区都很常见,平时用来给外来人员预约进校/进园的,通常会要求填写极度详细的个人信息(身份证、车牌号、手机号等)。
这意味着,一旦系统存在缺陷,它就是一个巨大的“敏感数据金矿”。
带着这种直觉,我打开了目标系统的首页:http://visapp.example.edu:8010/…。页面极其简洁,常规的手机号注册/登录流程。一切看起来都是那么的无懈可击。但作为一名渗透测试人员,我知道,“看似安全”往往只是因为测试的颗粒度还不够细。
0x02 信息收集
我习惯性地挂上 Burp Suite,像往常一样走了一遍正常的业务流程:输入我自己的手机号 -> 获取验证码 -> 登录。

在翻阅 HTTP 历史记录时,一条很普通的请求引起了我的注意。在完成初次身份验证后,我发现系统在某处鉴权逻辑中,过度依赖了客户端传递的参数。
为了验证我的猜想,我在拦截的请求中,尝试将原本属于我自己的手机号,替换成了一个随意构造的测试号码:13888888888
随着 Burp 中 Forward 按钮的按下,返回包出乎意料地给出了成功的响应。我竟然直接以这个伪造的手机号身份“挤”进了系统!这个意外的越权登录(Broken Authentication)给了我极大的信心——这说明后端的校验逻辑非常薄弱,甚至可以说处于“裸奔”状态

0x03 漏洞利用
虽然成功越权登录,但此时能看到的信息依然有限。我继续在系统中游荡,点击了“历史预约”、“我的信息”等功能块。
就在这时,一个关键的 API 请求落入了我的抓包记录中:
GET /appointment/findById?id=342101 HTTP/1.1
Host: visapp.example.edu:8010
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ...
NetType/WIFI MicroMessenger/7.0.20...
content-type: application/json
Accept: */*
Origin: http://visapp.example.edu:8020
Referer: http://visapp.example.edu:8020/
看着这个 URL 中的 ?id=342101,我的“安全蜘蛛感应”瞬间狂闪。
在 Web 安全中,这是一种极其经典的传参方式。342101 显然是数据库中这条预约记录的主键(Primary Key),而且是自增的整型数字。

逻辑转换的瞬间到了:
后端既然能根据 id=342101 返回我的预约信息,那如果我把请求拦截下来,把 342101 改成 342100 呢?后端会检查“现在的登录用户,有没有权限查看 342100 这条记录”吗?
我将这个数据包发送到了 Burp Suite 的 Repeater 模块,小心翼翼地将 id 修改为相近的数字,点击 Send
{
"data": {
"id": 342000,
"visitorName": "刘某某",
"visitorPhone": "138XXXX5678",
"cardNum": "310115199X... (完整身份证)",
"carPlate": "沪A88888",
...
}
}
果然可以,接下来就遍历ID,扩大战果,疯狂上分
最后发现,至少能从1遍历到340000
保守估计,泄露敏感个人信息(身份证,手机号,姓名,车牌号)30万+这里贴几个关键截图即可


0x04 漏洞影响
确认了漏洞存在后,我将数据包扔进了 Burp Intruder 进行简单的边界探测。
由于参数 id 是连续递增的整数,我发现从 id=1 开始,一直到 id=340000+,所有的接口响应全都是 200 OK,没有任何访问控制拦截。
这意味着什么?
这意味着,只要写一个几行代码的 Python 脚本循环遍历这个 id,这所高校多年来积累的 30万+ 师生及访客的绝对敏感个人信息(包含精准匹配的姓名、手机号、完整身份证号、车牌号)将可以被任何人无门槛地打包带走。
在真实的黑灰产攻击场景中,这类数据的泄露往往是电信诈骗、社工库撞库的罪魁祸首。考虑到数据的敏感度和体量,这是一个不折不扣的高危逻辑漏洞。在计算演练得分时,我也毫不犹豫地按照了最高倍率的计分规则进行了申报。
0x05 防御与反思
作为白帽子,发现漏洞只是第一步,知道如何从根源上消灭它才是我们的最终目的。
这个漏洞的产生,本质上是因为开发人员在编写 API 时,只做了“身份认证”(你是谁),却没有做“访问授权”(你是否有权看这个东西)。
如果你是业务开发同学,请务必在代码里加上这三道锁:
- 水平越权校验(核心): 在执行 findById(id) 查询数据库之前,必须加入校验逻辑:SELECT * FROM appointments WHERE id = ? AND user_id = ?。确保查询的这条记录,其所属人与当前 Session/Token 中的用户完全一致。
- 拒绝连续可预测的 ID: 不要直接将数据库的自增主键暴露在前端 API 中。强烈建议使用 UUID、雪花算法生成不可预测的随机字符串作为外部查询的 id,直接切断攻击者通过遍历(Brute Force)拉取全站数据的途径。
- 敏感数据脱敏: 即使是用户查看自己的信息,后端返回给前端的 JSON 数据中,也应当将身份证、手机号进行打码处理(如 310***********1234),在展示层做到最小化暴露。
一次简单的 id 修改,就能撬动 30 万的敏感数据。在网络安全的世界里,细节往往决定了系统的生死。代码诚不欺我,唯有敬畏每一行代码,才能筑起真正的安全高墙。
Keep Hacking, Keep Securing. 我们下个漏洞见!