2019年,权限某电商平台的绕过一位普通用户发现,把订单详情页URL里的漏洞用户ID从自己的改成别人的,居然能看到对方的权限收货地址和手机号。他没声张,绕过又试了试退款接口——把订单号换成别人的漏洞,退款金额填成任意数字,权限系统照单全收。绕过这个漏洞后来被修复了,漏洞但类似的权限事情每天都在发生。
权限绕过漏洞的绕过本质,是漏洞系统在某个环节忘了检查“你是谁”或者“你能不能干这事”。听起来低级,权限可它偏偏是绕过最常见的漏洞类型之一。OWASP每年排的漏洞Web安全风险榜单里,失效的访问控制稳居前列。不是因为它难防,而是因为开发时太容易漏。
举个具体的例子。一个后台管理系统,前端菜单只给管理员显示“删除用户”按钮,普通用户看不到。但接口本身没有做角色校验。普通用户抓个包,直接调那个删除接口,照样能把人删掉。前端隐藏不等于后端拦截——这句话说了无数遍,还是有人栽在上面。
再比如水平越权。两个用户A和B,A想看B的私信。系统查私信时只根据消息ID去数据库取,没校验这条消息的归属者是不是当前登录用户。A把消息ID一改,B的私信就出来了。这种漏洞在社交类产品里特别多,因为业务逻辑天然涉及大量“我的东西”和“别人的东西”之间的切换。
还有一种更隐蔽的:通过修改请求方法绕过。某个接口只允许POST,因为POST请求里带了CSRF token。但如果你用GET请求同样的URL,有些框架会照样路由到同一个处理函数,而token校验逻辑只在POST分支里写了。GET请求直接跳过校验。这种坑,不仔细看代码根本发现不了。
为什么权限绕过这么难根除?我的观察是,它跟业务逻辑绑得太紧。SQL注入、XSS这些有成熟的框架级防护方案,但权限校验往往需要开发者自己写。每个接口的权限规则可能都不一样——这个接口要管理员,那个接口要资源所有者,另一个接口要特定角色加特定条件。写多了总会漏。
而且很多团队在开发阶段用超级管理员账号测试,所有权限都有,根本触发不了绕过场景。等上线了,普通用户一用就出问题。测试权限漏洞,必须用不同角色的账号交叉验证,这需要额外的工作量。
修复思路其实不复杂。所有敏感操作,后端必须独立校验当前用户是否有权执行。不要信任前端传来的任何身份标识,用户ID从session或token里取,不要从请求参数里读。对于资源类接口,每次查询都要带上“当前用户ID”作为条件,确保只能操作自己的数据。角色校验用中间件统一处理,别在每个接口里手写if-else。
有个做安全的朋友跟我说过一句话:权限绕过漏洞就像门锁——你装了锁,但忘了检查每个窗户。攻击者不需要撬锁,推开窗户就进去了。而大多数团队,连自己有多少扇窗户都不清楚。