【HW实录】一个简单的越权,泄露全校访客敏感信息30万+

最近在参与某次授权的攻防演练打怪升级时,偶然碰到了一个看似平平无奇的访客管理系统。本以为只是一次走马观花的日常摸鱼,没想到凭借一个微小的逻辑转换,竟牵扯出了高达 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 时,只做了“身份认证”(你是谁),却没有做“访问授权”(你是否有权看这个东西)

如果你是业务开发同学,请务必在代码里加上这三道锁:

  1. 水平越权校验(核心): 在执行 findById(id) 查询数据库之前,必须加入校验逻辑:SELECT * FROM appointments WHERE id = ? AND user_id = ?。确保查询的这条记录,其所属人与当前 Session/Token 中的用户完全一致。
  2. 拒绝连续可预测的 ID: 不要直接将数据库的自增主键暴露在前端 API 中。强烈建议使用 UUID、雪花算法生成不可预测的随机字符串作为外部查询的 id,直接切断攻击者通过遍历(Brute Force)拉取全站数据的途径。
  3. 敏感数据脱敏: 即使是用户查看自己的信息,后端返回给前端的 JSON 数据中,也应当将身份证、手机号进行打码处理(如 310***********1234),在展示层做到最小化暴露。

一次简单的 id 修改,就能撬动 30 万的敏感数据。在网络安全的世界里,细节往往决定了系统的生死。代码诚不欺我,唯有敬畏每一行代码,才能筑起真正的安全高墙。

Keep Hacking, Keep Securing. 我们下个漏洞见!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注