【渗透日常】某高校机动车管理系统,从一个小越权到接管全站用户+数据

身为校信息办的一名助理,日常除了修电脑、拉网线,我最大的爱好就是在合规授权的前提下,给学校的各大系统把把脉。

前几天,在测试学校内网某个刚刚上线的“机动车出入证申领及管理系统”时,我本以为这只是一个平平无奇的 CRUD 后台。然而,几番试探下来,接连不断的“惊喜”推翻了我的假设。这不仅仅是一个简单的越权,而是一场从普通学生权限一路狂飙到后台超级管理员、最终牵扯出数万条敏感数据的奇妙之旅。

今天,就带大家硬核拆解一下,我是如何靠着敏锐的直觉和抓包工具,一步步击穿这个系统的安全防线的。


0x01 故事背景

故事的开始很简单。这个系统部署在内网,需要先通过学校的 SSO(单点登录)认证。
登录进去后,我注意到系统的 URL 发生了一次跳转,最终落在了一个极其朴素的页面:

http://sys.target-edu.cn:8080/APP_ROOT/main3.jsp

如果你用访客账号(非 SSO)登录,则会跳转到:

http://sys.target-edu.cn:8080/APP_ROOT/main4.jsp

黑客的直觉往往来源于开发者的“偷懒”。
看着这两个高度对称的命名——main3.jsp、main4.jsp,我的脑海里立刻闪过一个念头:功能点是不是都写死在了类似 main+自然数.jsp 的文件里?既然前端功能没什么明显的区别,那后端的权限校验真的做严密了吗?

带着这个疑问,我点开了“查看申请表”功能,Burp Suite 已经饥渴难耐了。

0x02 漏洞利用

Round 1:最经典的 IDOR (平行越权)

在“查看”功能处抓包,我看到了一个再熟悉不过的请求结构:

GET /APP_ROOT/ShowTabCarUser?id=46222 HTTP/1.1
Host: sys.target-edu.cn:8080
Cookie: JSESSIONID=XXXXXXX...

一个赤裸裸的 id 参数暴露在 GET 请求中。

我顺手扔进了 Intruder 跑了一下,成功遍历出 4万+ 的敏感信息。这属于非常经典的水平越权(IDOR)

Round 2:突破业务逻辑(修改金额 & 替人办事)

继续探索,我来到了“个人加时包”列表。系统设定只能选择固定的金额(比如 50 元、100 元)。

系统设置了只能选择这些金额


抓取提交订单的 POST 包:

POST /APP_ROOT/AddbeRenew HTTP/1.1
Host: sys.target-edu.cn:8080
Content-Type: application/x-www-form-urlencoded

ghxh=20231234&cardYf=50

观察参数:ghxh 显然是学号,cardYf 是金额。
系统前端限制了只能选 50?那我偏要在 Burp 里把 cardYf=50 改成 cardYf=1。
发包,返回 {“code”:”0″, “msg”:”插入成功”}。成功突破金额限制!

回到界面确认

但这还没完,如果我把 ghxh 改成我同学的学号呢?
再次发包,依旧返回成功。我找同学确认了一下,他的账号下果然凭空多出了一个加时包。这意味着,我不仅可以随意篡改账单金额,还能越权替任何人下订单(或恶意塞入垃圾数据)

同理,在“删除”功能的接口 /APP_ROOT/beRenewDel?id=417 中,通过修改 id 参数,我同样可以随意删除他人的申请记录

Round 3:后台管理员权限接管+全系统用户信息泄露

前面提到,普通用户看到的是 main3.jsp 和 main4.jsp。既然如此,那 main1.jsp 到 main10.jsp 到底藏着什么?

我直接打开 Yakit 进行 Fuzz 测试,对自然数部分进行爆破

结果令人大跌眼镜:大量页面返回了 200 OK,其中 main9.jsp 赫然是一个后台管理界面!而且存在严重的垂直越权,我一个普通学生账号直接进去了。

后台的“过车记录查询”泄露了 43 万页,共计 400余万条 车辆行驶记录。但这还不够带劲。

随后,我点击了最上方的“B,C,E 证已通过申请表”。此时,页面弹出了一个警告:
未登录系统! 并自动跳转回了登录页。

本以为到此为止,后端的鉴权终于起作用了,然而,接下来的发现直接推翻了我的假设。

我回去仔细看了一遍 Burp 里的 HTTP 返回包。这个 /APP_ROOT/service/atgtest.jsp 接口的返回体简直是“掩耳盗铃”的教科书级示范

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 20823

<script>alert('未登录系统!');top.location.href='../login.jsp';</script>
<html>
    <head>
        <title>通行证申请已通过列表</title>
        <!-- 下面紧跟着完整的后台机密数据表格 -->
        ...
        <td>张三</td><td>3101031999...</td><td>13800000000</td>
        ...

看懂了吗?后端确实判断了我没有管理员权限,但它仅仅是在 HTML 顶部插入了一段 JavaScript 弹窗跳转代码,同时把成千上万条本该保密的数据一股脑全下发给了前端!

对付这种“纸老虎”,只需要使用 Burp Suite 的 Match and Replace 功能,或者直接拦截响应包,把 <script>…</script> 这段标签删掉。
放行请求,一张包含 8394 条高度敏感信息(姓名、身份证、手机号、车牌、家庭住址)的列表直接展现在我眼前。随后在“D证申请表”中,我又用同样的手法获取了数万条高价值 PII 数据。

0x03 防御与反思

这次测试是一次典型的“由点到面”的渗透过程。从一个简单的 IDOR,演变成了横跨水平越权、垂直越权、业务逻辑绕过、以及前端鉴权绕过的严重安全事故。

如果这套系统暴露在公网,或者被有心之人利用,后果不堪设想。全校师生的高度敏感 PII 信息将面临被全量“脱裤”的风险。作为建设者,我们需要从这次事件中吸取什么教训?

Root Cause (根本原因分析):
整个系统的致命伤在于:过度信任客户端
无论是订单金额(前端限制下拉框,后端不校验)、操作对象(依赖前端传来的用户ID,不与当前 Session 绑定)、还是权限校验(用 JS 跳转代替后端的硬性拦截),都犯了安全开发的大忌。

💡 开发者加固建议:

  1. 废弃前端鉴权: 权限校验绝对不能通过返回 <script> 跳转来实现。如果用户无权访问,后端必须直接返回 401 Unauthorized 或 403 Forbidden 状态码,并终止输出任何真实的业务数据
  2. 强制水平鉴权 (解决 IDOR): 在执行查询、修改、删除操作时,不能仅仅根据请求参数中的 id 去查库。必须在 SQL 语句或业务逻辑中加上条件:WHERE record_id = ? AND owner_user_id = ?,确保当前 Session 的用户只能操作自己的数据。
  3. 敏感参数服务端计算: 像订单金额这类关键业务数据,绝不能由前端传递。应该只传递“商品ID”或“套餐类型”,具体金额由后端去数据库中查询核对后生成订单。
  4. 引入 RBAC/ABAC 模型: 对 .jsp 文件的直接访问进行严格的鉴权拦截器(Interceptor)配置,非 Admin 角色的 Session 访问管理路径应直接被丢弃。

写在最后:作为一名热爱网络安全的大学生,能用自己学到的技术帮助学校排查隐患,是一件非常有成就感的事情。漏洞已经第一时间提交给了校信息办老师,并协助完成了紧急修复。技术无罪,但心存敬畏。我们下次实战见!

发表回复

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