越权访问漏洞十个里有八个出在接口上,这不是巧合。页面那层有框架、模板、中间件一层层兜着,接口那层是把数据直接递出去的,中间少伸一只手,就漏了。

页面藏起来的按钮,接口照样认
前端把删除按钮灰掉、把菜单藏了,不少人就认为权限做完了。抓一次包就知道,那个请求原封不动躺在列表里,id 换成别人的照样能删、能看。前端干的是「别让人误点」,后端干的才是「别让人乱来」,这俩经常被当成同一件事。
越权访问漏洞最爱藏在资源归属这一层
权限这东西有两种写法。一种是「这个功能谁能用」,管理员能进后台、普通用户不能;另一种是「这条数据归谁」,这个订单属于 1001 号用户,别人不许看。前者写起来简单,后者麻烦,因为每条数据都得带上归属判断。漏洞基本都出在后一种。功能权限做得像模像样,资源归属却靠前端传上来的 userId 决定,那等于把锁装在门帘上。
横向和纵向,两副面孔
横向是同级之间互相看:A 用户改个地址栏参数,看到 B 用户的收货地址、手机号、发票抬头。这种最不容易被发现,功能本身没坏,页面正常渲染,只是数据换了个主人。纵向是低权干高权的事,普通账号摸到了管理员接口,比如用户列表、批量导出、修改配置。纵向破坏力大,横向暴露面广,真实环境里横向翻车的次数明显更多。
一个页面七八个接口,漏一个就全漏
前后端分离之后,一个列表页要打好几个请求:列表、筛选项、总数、推荐位、导出、字典。每个接口都得判一次权限,只要漏掉一个,整条防线就没意义了。漏的往往还是最不起眼的那个——下拉框的字典接口、导出按钮背后的下载接口、图表用的统计接口。攻击者不看你的功能设计文档,他就翻请求列表,看哪个返回了数据。
另一个常见来源是图省事:把内部用的接口直接开在公网。后台管理接口、数据同步接口、给 App 用的老版本 v1 接口,鉴权逻辑还停留在好几年前。老接口没人维护、没人测,却一直在跑。
测试时最容易自己骗自己
用管理员账号从登录点一路点到尾,顺畅,测试通过。可这条路测的是「功能能不能用」,不是「权限拦不拦得住」。要发现越权访问漏洞,得换身份:两个同级账号对着打,一个低权账号去扫高权路径,把请求里的 userId、tenantId、orderId 挨个换成别人的;去掉 token 再发一次;把 GET 改成 POST 试一下。看返回是干脆的 403,还是 200 带着别人的数据,后者就是漏洞。
还有一种自欺:接口返回里把敏感字段「前端不显示」。这算不上防护。数据已经进了浏览器,抓包就看得见,藏不藏只是界面上的事。
修的时候别在业务代码里打补丁
见过太多在业务方法里一行行 if 判断的写法,加一个接口补一个 if,早晚会漏。靠谱一点的做法是收口:统一入口做身份识别,把当前用户、租户、角色从会话或 token 里解出来,别信请求体里传的身份字段。然后在取数据那一步做归属校验,查订单就带上当前用户 id 作为条件,查不到就返回 404 或 403,别先查出来再判断。
默认拒绝也是个好习惯。新加的接口如果没声明权限,就当作谁都不能调,让它一上线就报错,比悄悄放开强得多。
上线之后还得盯着
这种事修完不等于没人再试。日志里同一账号短时间访问大量连续 id、403 集中出现、某个接口调用量突然变成一台机器在刷,都是信号,接进告警比事后翻日志省事。整理接口清单的时候顺手标上每个接口的权限要求,新同事加接口照着抄都不会抄错。
顺带说一句,云上跑的接口和自建机房的接口,在这件事上没区别。WAF、API 网关能挡掉一部分明显的扫描和批量请求,但「拿 A 的令牌去取 B 的数据」这种请求长得跟正常业务一模一样,规则很难写死。最后还是要靠代码里的归属校验,平台侧防护能力的具体范围,以服务商或官方页面说明为准,只能当补充。
真要落地,先别急着上工具。把接口列表拉出来,标清楚哪些是内部接口、哪些对公网开着、每个接口取的数据归谁。然后找两个同级账号,照着一张张对撞。这一步做完能捞出来的问题,比买什么设备都实在。剩下的,交给统一的鉴权层去兜。
【版权声明】:本站内容若无意侵犯到您的权利,请及时与我们联系将尽快删除相关内容!