游客发表
上周三凌晨两点,信息系统运维老张在群里甩了张截图——某台边缘节点的漏洞Nginx日志里,出现了连续17次针对`/api/v1/user/export`的检查异常POST请求,返回码清一色200。回复他圈出其中一条payload:“`{ "role":"admin",报告"deptId":-1}`”。没人回消息,信息系统但第二天早上六点,漏洞安全组的检查人已经蹲在会议室啃包子了。
这就是回复典型的越权漏洞。系统设计时默认前端传什么后端就信什么,报告`deptId`字段没做归属校验,信息系统攻击者把部门ID改成负数,漏洞直接拉走全量用户数据。检查修复方案倒不复杂:在Controller层加个`@PreAuthorize`注解,回复再补一段数据权限过滤逻辑。报告但真正麻烦的是排查历史日志——过去三个月里,相同IP还试过`/api/v1/order/list?status=all`,当时返回的是403,没人当回事。
漏洞检查回复报告最忌讳写成流水账。我见过一份报告,光“漏洞描述”就列了十二页,结果修复建议只有一句“建议加强校验”。安全团队要的不是学术论文,是能直接扔给开发改代码的工单。比如这次,我们直接在报告里嵌了段Groovy脚本,让运维跑一遍就能定位所有未鉴权的导出接口:
import groovy.sql.Sql def db = Sql.newInstance("jdbc:mysql://...") db.eachRow("SELECT uri FROM api_log WHERE uri LIKE '%export%' AND status=200 AND params LIKE '%role%'") { row -> println "待修复: ${ row.uri}" } 有个细节挺有意思。开发最初坚持认为`deptId`是内部字段,前端不会篡改。但抓包显示,攻击者用的就是浏览器F12改的请求体。后来复盘时发现,前端代码里确实有个隐藏的``,但后端根本没校验这个值是否等于当前用户的部门。这种“前端校验当安全”的思维,比漏洞本身更值得写进报告。
报告里我特意放了张时序图,用ASCII画的:
攻击者 -> 前端: 修改deptId=-1 前端 -> 后端: POST /export { deptId:-1} 后端 -> 数据库: SELECT * FROM user WHERE dept_id=-1 数据库 --> 后端: 返回全量数据 后端 --> 攻击者: 200 OK + CSV文件 比文字描述直观多了。安全组的老王看完说:“这图往Jira上一贴,开发想赖都赖不掉。”
修复验证阶段出了个岔子。开发加了`@PreAuthorize("hasPermission(#deptId, 'DEPT_READ')")`,但测试环境跑不通——权限框架的SpEL表达式解析不了负数。最后改成在Service层手动判断:if (deptId < 0 || !userDeptIds.contains(deptId)) throw new AccessDeniedException();。所以报告里的“修复建议”必须带具体代码片段,光写“增加权限校验”等于没写。
再说个真事。某次检查发现Redis未授权访问,报告里写了“建议设置密码”。结果运维直接回:“生产环境Redis绑的是内网IP,加密码会影响性能。”后来我们改成“在iptables层限制源IP,并禁用CONFIG命令”,他们当天就改了。写报告的人得懂点运维的难处,不然建议就是废纸。
最后附了张检查清单,用checkbox格式:
没打勾的那项写了原因:“前端重构排期在Q3,临时方案是在网关层过滤`deptId<0`的请求。”这样报告才有人看,也才有人改。
友情链接