目录[-]
一、测试背景
本次测试使用 Burp Suite 对 Web 系统进行安全测试,覆盖了5个核心攻击面:登录接口、Token鉴权、越权、文件上传、支付/提现接口。
-
测试工具:Burp Suite (Proxy, Repeater, Intruder, Decoder)
-
学习与参考:Burp Suite官网教程
二、登录接口安全测试
2.1 测试维度
| 序号 | 测试维度 |
|---|---|
| 1 | 用户名枚举 |
| 2 | SQL注入绕过 |
| 3 | 暴力破解防护 |
| 4 | 越权/会话相关 |
| 5 | 敏感信息泄露 |
2.2 用户名枚举测试(核心漏洞)
测试方法:分别使用“存在的手机号”和“不存在的手机号”发送登录请求,对比返回值差异。
| 用例 | 账号输入 | 密码输入 | 返回值 |
|---|---|---|---|
| 用例1 | 真实手机号 | 空 | 请输入密码 |
| 用例2 | 真实手机号 | 错误密码 | 账号或密码错误 |
| 用例3 | 不存在的手机号 | 任意 | 9999 系统繁忙 |
漏洞发现:
-
存在的手机号 →
code:5000 -
不存在的手机号 →
code:9999
风险:攻击者可利用返回值差异批量验证有效手机号。
图片1:数据库中存在的手机号,登录失败时,返回 code:5000
图片1补充:
图片2:数据库中存在的手机号,登录失败时,返回 code:9999
漏洞2:日志型拒绝服务
每次请求不存在的手机号,后端会执行“数据库查询 + 异常对象创建 + 错误日志写入”。攻击者批量发送假账号请求,可导致磁盘空间被写满,CPU及I/O资源耗尽。
这是一个极其严重的bug,如果无法保证其安全性,用户可以大量攻击,我举个例子,2015年 GitHub的日志炸弹事件,攻击者向GitHub提交了一段特制的10kb大小的代码,GitHub后端在记录相关操作时,将日志原样写入日志文件,随后,短时间内,这个日志被大量写入,导致磁盘耗尽、服务瘫痪。
你可能会好奇,10kb能有这么大威力么?但如果是这样:攻击者用1000个并发线程,每秒发送10次请求。1秒钟产生100MB日志,10秒钟就是10GB,以此类推,这是不可逆的重大问题。
漏洞3:冻结期凭证验证
账户冻结期间,系统对“正确密码”与“错误密码”的反馈存在差异,攻击者仍可利用此差异进行密码猜测。
图片3:冻结校验,当错误密码尝试10次以上后,触发系统5分钟的强制冻结,但冻结期间,仍然可以通过“正确密码”和“错误密码”进行攻击。(前提是已经拿到了数据库里保存到账号)
2.3 SQL注入测试
在账号输入框输入以下Payload,全部返回 9999 系统繁忙:
' or 1=1 -- admin' -- admin'/**/or/**/1=1--
结论:后端采用参数化查询,对SQL注入有防护。
图片4:账号输入(<script>alert(1)</script>)没有出现报错信息
2.4 特殊字符与边界测试
| 用例 | 账号输入 | 密码输入 | 返回值 |
|---|---|---|---|
| 空字符串 | 空 | 空 | 5000 账号或密码错误 |
| 空格 | 空格 | 空格 | 9999 系统繁忙 (异常) |
图片5:账号名输入空字符串
图片6:账号输入空字符串,密码输入空格
2.5 暴力破解防护测试
| 测试项 | 结果 |
|---|---|
| 同一账号,连续10次错误密码 | 有冻结机制(10分钟),但无验证码 |
| 同一IP,不同账号连续尝试 | 无IP限制 |
图片7:第一种情况,手机号正确,但处于冻结状态,所以,给出的提示 code 仍然是5000,但提示信息变了
图片8:待补充
隐藏的雷点:
- 攻击者可以撞库:因为没有验证码机制,攻击者可以购买大量手机号进行自动化请求,可以检测出一批数据库中已存在的手机号。接下来,攻击者可以对这些数据库中已存在的手机号。
- 无IP限制:同一个IP在一个小时内,连续请求10次还算是正常情况,但连续请求20次、100次甚至更多就不正常了,应该有IP限制。
- 账号锁定:修改报错码,不能让攻击者发现系统的逻辑,统一改成 code:9999,账号已锁定。提示信息统一返回:账号或密码错误。
修复建议:
- 验证码:连续错误 2-3 次后弹出验证码(图片/滑块),阻断自动化脚本。
- IP限流:同一IP每小时最多尝试XX次,超过则封禁24小时或要求验证码。
- 账号软锁定:统一提示信息,不要在接口返回值和提示信息中,显示真实的报错原因。
- 风险账号监控:当一个账号触发监控,接下来每一次请求都要验证码,做一个定时器,当最后一次错误时间超过24小时之后,再将账号恢复正常。
2.6 敏感信息泄露测试
登录成功后,响应包返回了过多敏感信息:
问题字段:
-
个人敏感信息:
phone,account -
内部ID:
empId,departId,postId -
内部配置:
faceInfoFlag,source,clientType
风险:
- 隐私合规风险:接口返回明文手机号,涉嫌违反《个人信息保护法》,可能面临行政处罚或用户个人诉讼。
- 撞库攻击面扩大:攻击者可批量收集有效手机号,用于后续攻击。
- 越权漏洞利用:暴露的 empId、departId、postId 可被用于后续构造接口请求。
- 社会工程学攻击:获取手机号的攻击者可定向发送钓鱼短信,诱导用户泄露验证码或点击恶意链接。
- 组织结构泄露:通过 departId、postId 反推公司部门和管理结构。
- 短信轰炸:收集到的手机号可被用于短信验证码接口的恶意调用,对用户试试骚扰。
修复建议:
- 登录接口仅返回部分必要字段,移除敏感字段。
- 如需要展示手机号,脱敏处理为:130****0000。
- 内部配置类字段(如 faceInfoFrag、source、clientType)应在服务端内部处理,不应返回到客户端。
图片9:登录成功后返回值显示
三、Token鉴权测试
3.1 测试维度
| 序号 | 测试维度 | 说明 |
|---|---|---|
| 1 | 无Token访问 | 不传Token能否访问 |
| 2 | Token可篡改性 | 修改JWT内容是否通过 |
| 3 | Token复用性 | 一个Token能否用于多用户 |
| 4 | Token过期校验 | 过期后是否还能使用 |
| 5 | Token可猜测性 | Token是否有规律 |
3.2 JWT Token解码
使用 Burp Suite Decoder 解码 JWT Token:
原始Token:
eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJiZDAwZDJjMGE1Y2YwMDAiLCJpYXQiOjE3NzkzNDE0NzIsImV4cCI6MTc3OTM0ODY3Miwic3ViIjoiMzE2IiwicmFuZG9tIjoiYmQwMGQyYzBhNWNmMDAwIiwidGVsZXBob25lIjoiMTMwMTExMTIyMjIifQ.nhY3IkotynRklRNOWZnc1UwIDZqBlPv-xXhddL3ue_w
第一部分:Header
eyJhbGciOiJIUzI1NiJ9 → base64位解码后变成 → {"alg":"HS256"}
声明:签名算法是 HMAC SHA256(应该是统一的,不用它校验用户)
第二部分:Payload
eyJqdGkiOiJiZDAwZDJjMGE1Y2YwMDAiLCJpYXQiOjE3NzkzNDE0NzIsImV4cCI6MTc3OTM0ODY3Miwic3ViIjoiMzE2IiwicmFuZG9tIjoiYmQwMGQyYzBhNWNmMDAwIiwidGVsZXBob25lIjoiMTMwMTExMTIyMjIifQ
base64位解码后变成:
{
"jti": "bd00d2c0a5cf000",
"iat": 1779341472,
"exp": 1779348672,
"sub": "316",
"random": "bd00d2c0a5cf000",
"telephone": "13011112222"
}
sub:316、telephone:13011112222,这两个字段属明文暴露。
第三部分:Signature
nhY3IkotynRklRNOWZnc1UwIDZqBlPv-xXhddL3ue_w 无法解码成可读文本,应该用于校验:Token 是否被篡改。
风险:Payload中包含明文手机号和用户ID。
3.3 测试结果
| 测试项 | 结果 |
|---|---|
| 无Token访问 / 传空 / 传错误 | ✅ 正确拒绝 |
| 篡改Payload/userId/exp | ✅ 签名校验生效 |
| Token跨用户复用 | ❌ 漏洞:一个Token可用于多用户 |
| Token过期校验 | ✅ 正确拒绝 |
| Token可猜测性 | ✅ 无明显规律 |
漏洞详情:将用户A的Token发给其他同事,他们可以完全以用户A的身份调用所有接口。
四、越权测试(水平/垂直)
| 测试项 | 预期结果 | 实际结果 |
|---|---|---|
| 用户A获取订单列表 | 只看到A的订单 | ✅ 通过 |
| 修改userId为其他用户 | 拒绝 | ✅ 通过 |
| 修改手机号 | 拒绝 | ✅ 通过 |
| 普通用户调用管理员接口 | 拒绝 | ✅ 通过 |
结论:服务端严格校验用户身份,不信任客户端传入的参数,越权防护有效。
五、文件上传安全测试(高危)
5.1 测试维度覆盖
-
文件类型校验
- 后缀名绕过
-
MIME Type伪造
-
文件内容校验
-
文件名注入
-
文件大小限制
-
路径泄露
-
权限控制
-
二次渲染
5.2 核心漏洞发现
漏洞1:任意文件上传(无类型校验)
-
操作:在Burp Repeater中,将请求的
filename从test.mp3改为test.html,Content-Type从audio/mpeg改为text/html,文件内容改为<script>alert(1)</script>。 -
结果:上传成功,返回
code:0000。 -
风险:可上传任意恶意文件,包括HTML(XSS)和PHP(Webshell)。
图片10:一个mp3 类型的接口,修改 content-type,却能够上传成功,数据库存的内容错误
漏洞2:文件内容伪造
-
操作:将MP3文件内容删除,替换为纯文本
111。 -
结果:上传成功,后端完全不校验文件内容。
图片11:内容改成 1111
漏洞3:存储型XSS
-
操作:上传
test.html,内容为<script>alert(1)</script>。 -
结果:上传成功,文件被存储。
-
风险:如果系统展示了该文件,用户浏览器会执行恶意脚本。
图片12:类型改成 html,内容改成脚本
5.3 其他风险点
-
fileLogId可遍历:可枚举其他用户上传的文件。 -
fileName未重命名:可能用于路径遍历。 -
uploadPlatform、isCommon可篡改:可尝试提升权限或公开私密文件。
六、支付/提现接口测试(高危)
-
操作:拦截提现请求,将
amount=100修改为amount=1000000。 -
结果:后端未校验余额,直接提交成功。
-
风险:可提取超过账户余额的金额,直接导致资金损失。
涉及公司接口,比较敏感,不能上传图片。
测试者在测试过程中,需要留意接口入参。
七、漏洞汇总表
| 序号 | 漏洞名称 | 类型 | 严重程度 | 发现位置 |
|---|---|---|---|---|
| 1 | 用户枚举 | 信息泄露 | 中危 | 登录接口 |
| 2 | 日志型拒绝服务 | 资源耗尽 | 中危 | 登录接口 |
| 3 | 冻结期凭证验证 | 逻辑缺陷 | 中危 | 登录接口 |
| 4 | 敏感信息过度暴露 | 信息泄露 | 中危 | 登录接口 |
| 5 | 无验证码机制 | 暴力破解 | 中危 | 登录接口 |
| 6 | 无IP限流 | 暴力破解 | 中危 | 登录接口 |
| 7 | Token跨用户复用 | 鉴权缺陷 | 中危 | Token鉴权 |
| 8 | JWT Payload明文手机号 | 信息泄露 | 中危 | Token鉴权 |
| 9 | 任意文件上传 | 文件上传 | 高危 | 上传接口 |
| 10 | 文件内容伪造 | 文件上传 | 高危 | 上传接口 |
| 11 | 存储型XSS | XSS | 高危 | 上传接口 |
| 12 | fileLogId可遍历 | 信息泄露 | 中危 | 上传接口 |
| 13 | uploadPlatform可篡改 | 权限绕过 | 中危 | 上传接口 |
| 14 | isCommon可篡改 | 权限绕过 | 中危 | 上传接口 |
| 15 | 金额篡改(提现超余额) | 业务逻辑 | 高危 | 支付/提现接口 |
八、核心修改建议
| 问题 | 修复建议 |
|---|---|
| 登录接口返回值不一致 | 统一返回“账号或密码错误”,不论账号是否存在 |
| 文件上传无校验 | 严格校验文件类型、Content-Type、文件内容 |
| 提现金额可篡改 | 后端从数据库查询真实余额,不信任前端传参 |
| Token跨用户复用 | Token与用户ID、设备指纹绑定,关键接口持续校验身份 |
| 敏感信息暴露 | 登录接口只返回必要的状态码和userToken |
| 暴力破解 | 增加验证码、IP限流、账号锁定机制 |
九、测试工具与执行顺序
推荐工具
| 测试维度 | 工具 |
|---|---|
| 用户名枚举 | 手动 + Burp Repeater |
| SQL注入 | Burp Repeater |
| 特殊字符 | Burp Repeater |
| 暴力破解 | Burp Intruder |
| 敏感信息 | Burp Proxy + 手动 |
测试执行顺序
-
第1轮 (手动):用户名枚举、特殊字符
-
第2轮 (抓包+Repeater):SQL注入、XSS
-
第3轮:敏感信息检查
-
第4轮:暴力破解
十、测试用例设计
一、登录接口测试用例
1.1 用户名枚举测试
| 用例编号 | 测试项 | 账号输入 | 密码输入 | 预期结果 | 实际结果 | 状态 |
|---|---|---|---|---|---|---|
| ENUM-01 | 存在的账号+空密码 | 真实手机号 | (空) | 提示“账号或密码错误” | 请输入密码 | ❌ |
| ENUM-02 | 存在的账号+错误密码 | 真实手机号 | 任意错误密码 | 提示“账号或密码错误” | 账号或密码错误 | ✅ |
| ENUM-03 | 不存在的账号+任意密码 | 不存在的手机号 | 任意密码 | 提示“账号或密码错误” | 9999 系统繁忙 | ❌ |
| ENUM-04 | 空账号+空密码 | (空) | (空) | 提示“请输入账号” | 5000 账号或密码错误 | ⚠️ |
测试方法:分别使用“存在的手机号”和“不存在的手机号”发送登录请求,对比返回值差异。
判断标准:不论什么情况,都应该统一返回“账号或密码错误”,不能暴露“账号不存在”、“密码错误”等具体信息,不论是前端提示信息,或是后端接口返回。
1.2 SQL注入测试
| 用例编号 | 测试Payload | 输入位置 | 预期结果 | 实际结果 | 状态 |
|---|---|---|---|---|---|
| SQL-01 | ' or 1=1 -- |
账号框 | 登录失败,无报错 | 9999 系统繁忙 | ✅ |
| SQL-02 | admin' -- |
账号框 | 登录失败,无报错 | 9999 系统繁忙 | ✅ |
| SQL-03 | admin'/**/or/**/1=1-- |
账号框 | 登录失败,无报错 | 9999 系统繁忙 | ✅ |
| SQL-04 | <script>alert(1)</script> |
账号框 | 无弹窗,无XSS | 9999 系统繁忙 | ✅ |
| SQL-05 | ' or '1'='1 |
密码框 | 登录失败,无报错 | 9999 系统繁忙 | ✅ |
测试方法:在账号/密码输入框输入SQL注入Payload,观察是否绕过登录或出现数据库报错。
判断标准:应全部被拦截,统一返回错误提示,不能出现数据库报错信息。
1.3 暴力破解防护测试
| 用例编号 | 测试场景 | 测试方法 | 预期结果 | 实际结果 | 状态 |
|---|---|---|---|---|---|
| BRUTE-01 | 单账号频繁错误 | 同一账号连续10次错误密码 | 触发验证码或账号锁定 | 有冻结(10分钟),但无验证码 | ⚠️ |
| BRUTE-02 | 同一IP多账号尝试 | 同一IP,不同账号各试2-3次 | 触发IP限流或验证码 | 无IP限制 | ❌ |
| BRUTE-03 | 验证码机制 | 错误多次后观察是否有验证码 | 出现图形/滑块验证码 | 无 | ❌ |
| BRUTE-04 | 冻结后正确密码 | 账号冻结后,输入正确密码 | 仍提示账号锁定 | 冻结期间提示变化 | ⚠️ |
测试方法:使用Burp Intruder批量发送登录请求,观察系统的限流和锁定机制。
判断标准:应有验证码、IP限流、账号软锁定,且冻结期间不应暴露“密码正确”的信号。
二、Token 鉴权测试用例
| 用例编号 | 测试项 | 测试方法 | 预期结果 | 实际结果 | 状态 |
|---|---|---|---|---|---|
| TOKEN-01 | 无Token访问 | 请求业务接口,不传Token | 返回401或403 | 登录身份过期 | ✅ |
| TOKEN-02 | Token传空 | Token参数传空字符串 | 返回401或403 | 登录身份过期 | ✅ |
| TOKEN-03 | Token传错误值 | 传任意错误Token | 返回401或403 | 登录身份过期 | ✅ |
| TOKEN-04 | JWT篡改-修改userId | 解码JWT,修改sub字段,重放请求 | 签名校验失败,拒绝访问 | 签名校验生效 | ✅ |
| TOKEN-05 | JWT篡改-修改过期时间 | 解码JWT,修改exp字段,重放请求 | 签名校验失败,拒绝访问 | 签名校验生效 | ✅ |
| TOKEN-06 | Token跨用户复用 | 用户A的Token,在用户B的设备上使用 | 拒绝访问或登录新用户 | 可跨用户使用 | ❌ |
| TOKEN-07 | Token过期校验 | 等待Token过期后,重放请求 | 返回Token过期 | 登录身份过期 | ✅ |
| TOKEN-08 | JWT Payload信息泄露 | 解码JWT,查看Payload内容 | 不应包含明文敏感信息 | 包含明文手机号、用户ID | ❌ |
测试方法:使用Burp Suite的Decoder解码JWT,修改后使用Repeater重放请求。
三、文件上传测试用例
3.1 类型校验与MIME绕过
| 用例编号 | 文件名 | Content-Type | 文件内容 | 预期结果 | 实际结果 | 状态 |
|---|---|---|---|---|---|---|
| UP-01 | test.jpg | image/jpeg | 正常图片 | 成功 | 成功 | ✅ |
| UP-02 | test.txt | text/plain | 文本内容 | 拒绝 | 可上传 | ❌ |
| UP-03 | test.html | text/html | <script>alert(1)</script> |
拒绝 | 可上传,触发XSS | ❌ |
| UP-04 | test.php | application/x-php | <?php phpinfo();?> |
拒绝 | 可上传 | ❌ |
| UP-05 | test.mp3 | audio/mpeg | 正常MP3 | 成功 | 成功 | ✅ |
| UP-06 | test.mp3 | image/jpeg | 正常MP3 | 拒绝(MIME不匹配) | 可上传 | ❌ |
| UP-07 | test.jpg.php | image/jpeg | 正常图片 | 拒绝(双重后缀) | 待测 | |
| UP-08 | test.Mp3 | audio/mpeg | 正常MP3 | 成功(大小写) | 待测 |
3.2 文件内容伪造
| 用例编号 | 文件名 | 操作 | 预期结果 | 实际结果 | 状态 |
|---|---|---|---|---|---|
| UP-09 | test.mp3 | 替换文件内容为纯文本111 |
拒绝(内容不匹配) | 可上传 | ❌ |
| UP-10 | shell.jpg | 图片末尾添加<?php phpinfo();?> |
拒绝或剥离恶意代码 | 待测 |
3.3 其他风险点
| 用例编号 | 测试项 | 测试方法 | 预期结果 | 实际结果 | 状态 |
|---|---|---|---|---|---|
| UP-11 | fileLogId遍历 | 修改fileLogId参数,尝试访问其他文件 | 无权限或不存在 | 可遍历 | ❌ |
| UP-12 | fileName未重命名 | 上传同名文件 | 覆盖或重命名 | 未重命名 | ⚠️ |
| UP-13 | uploadPlatform篡改 | 将platform改为admin | 无权限提升 | 可篡改 | ❌ |
| UP-14 | isCommon篡改 | 将false改为true | 文件不可公开 | 可篡改 | ❌ |
四、支付/提现接口测试用例
| 用例编号 | 测试项 | 测试方法 | 预期结果 | 实际结果 | 状态 |
|---|---|---|---|---|---|
| PAY-01 | 金额篡改 | 拦截提现请求,将amount从100改为1000000 | 后端校验余额,拒绝请求 | 提交成功 | ❌ |
| PAY-02 | 负数金额 | 将amount改为-100 | 拒绝 | 待测 | |
| PAY-03 | 非数字金额 | 将amount改为abc | 参数校验失败 | 待测 | |
| PAY-04 | 重复提现 | 同一笔提现请求重复发送 | 幂等性校验,拒绝重复 | 待测 |
测试汇总:将测试结果汇总即可。
十一、总结
本次安全测试共发现15个安全漏洞,其中4个高危:任意文件上传、文件内容伪造、存储型XSS、金额篡改。
核心结论:
-
❌ 文件上传接口后端完全没有校验,改了就能成功
-
❌ 提现接口信任客户端传入的金额参数,可超额提现
-
⚠️ 登录接口返回值不一致,存在用户枚举风险
-
⚠️ Token签名校验有效,但可跨用户复用,且Payload泄露敏感信息
-
✅ 越权防护设计良好,服务端不信任客户端参数