swaggerapi未授权访问漏洞修复

 人参与 | 时间:2026-10-17 07:06:24

去年秋天,未授问漏我帮一个做电商的权访朋友看服务器日志。凌晨三点,洞修一个IP在十分钟内爬走了他后台所有订单接口的未授问漏数据——收件人姓名、电话、权访地址,洞修一共七万多条。未授问漏他以为接口加了JWT校验就没事,权访结果漏了一个历史遗留的洞修Swagger文档页。那个页面不需要登录,未授问漏直接把所有API的权访路径、参数、洞修甚至示例请求都列了出来。未授问漏攻击者连猜都不用猜。权访

Swagger UI本身是洞修个好东西,开发阶段谁用谁知道。但问题出在它默认不设防。Springfox、SpringDoc这些库集成进来,通常会把/swagger-ui.html、/v2/api-docs、/v3/api-docs这几个路径暴露在外。生产环境如果没做额外处理,任何人访问你的域名/swagger-ui/index.html就能看到整套接口文档。更糟的是,有些配置还会把try it out按钮留着,攻击者可以直接在页面上发请求。

为什么很多人没修

我见过至少三种心态。一种是“反正接口有鉴权,文档看到也无所谓”——但文档里往往泄露了内部接口路径、参数命名规律、甚至测试用的固定token。另一种是“生产环境没配Swagger,只有测试环境有”——可测试环境常常和公网只隔一层薄薄的防火墙。第三种最要命:开发在application.yml里写了swagger.enabled: false,但代码里用的是@Profile({ "dev","test"}),结果生产打包时profile没对上,Swagger照样启动。

有个做金融的朋友更离谱。他们用Nginx做了IP白名单,只允许公司出口IP访问/swagger-ui。但Nginx配置里allow写的是192.168.1.0/24,而他们办公网早就换成10.10.0.0/16了。白名单形同虚设,漏洞裸奔了八个月。

怎么修才不折腾

最干净的办法是生产环境直接不加载Swagger相关依赖。Maven里用<scope>provided</scope>,打包时排除掉。但很多项目做不到,因为有些内部工具依赖Swagger的注解。那就退一步:在配置类上加条件。

@Configuration @EnableSwagger2 @Profile("!prod") public class SwaggerConfig {  ... } 

注意!prod这个写法。如果你用@Profile({ "dev","test"}),一旦某个环境没显式指定profile,Swagger就不会加载——这反而安全。但如果你用@Profile("!prod"),只要不是prod就加载,而很多公司生产环境的profile名字叫production或者online。所以更稳妥的是用@ConditionalOnProperty(name = "swagger.enabled", havingValue = "true"),默认false,只在需要时打开。

Nginx层再加一道。我习惯这样写:

location ~* /(swagger-ui|v2/api-docs|v3/api-docs|swagger-resources) {  deny all; return 403; } 

但别只写deny all就完事。有些老版本Swagger的静态资源路径是/webjars/springfox-swagger-ui/,漏掉这个照样能加载出页面。最好把webjars里跟swagger相关的路径也一并禁掉。

一个容易忽略的角落

Spring Boot Actuator的/actuator/mappings端点也会泄露所有接口路径。很多人修了Swagger,忘了这个。还有/actuator/env,如果没做脱敏,数据库密码都能看到。这两个端点要么关掉,要么加鉴权,要么只监听127.0.0.1。

我自己的做法是:生产环境Nginx里直接location /actuator { deny all; },需要监控就用内网单独开一个端口。Swagger同理,开发机随便用,生产环境连静态资源都不给。

最后说个真事。上个月帮一个创业公司做渗透测试,他们修了Swagger,但漏了/v3/api-docs/swagger-config。这个端点返回一个JSON,里面有个urls字段,指向真正的api-docs地址。攻击者拿到这个,照样能拼出完整文档。修漏洞最怕的就是只修一半——你以为堵住了门,其实窗户还开着。

顶: 739踩: 64344