JavaWeb中常见的信息泄漏—Swagger

admin 2021年5月10日01:26:24评论872 views字数 6435阅读21分27秒阅读模式

关于Swagger

  Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。总体目标是使客户端和文件系统作为服务器以同样的速度来更新。相关的方法,参数和模型紧密集成到服务器端的代码,允许API来始终保持同步。

主要作用

  • 接口的文档在线自动生成
  • 功能测试

相关项目

  • Swagger-tools:提供各种与Swagger进行集成和交互的工具。例如模式检验、Swagger 1.2文档转换成Swagger 2.0文档等功能。
  • Swagger-core: 用于Java/Scala的的Swagger实现。与JAX-RS(Jersey、Resteasy、CXF...)、Servlets和Play框架进行集成。
  • Swagger-js: 用于JavaScript的Swagger实现。
  • Swagger-node-express: Swagger模块,用于node.js的Express web应用框架。
  • Swagger-ui:一个无依赖的HTML、JS和CSS集合,可以为Swagger兼容API动态生成优雅文档。
  • Swagger-codegen:一个模板驱动引擎,通过分析用户Swagger资源声明以各种语言生成客户端代码。

  swagger-ui会根据我们在代码中的设置来自动生成Api说明文档,若存在相关的配置缺陷的话,可能会存在信息泄漏问题。

通过Swagger生成API文档

  以Springboot整合Swagger2为例:

  在pom.xml中引入Swagger2的dependency依赖,同时引入Swagger UI生成可视化的UI页面展示描述文件,以便可以与自定义的API规范进行交互并测试端点。:

xml
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>

  然后就是编写Swagger2的配置文件了:

  使用相关注解进行配置:

  • @Configuration注解代表上图SwaggerConfig类为配置类,自动加载到容器中。
  • @EnableSwagger2则是用来启动Swagger支持,表示这是一个Spring Swagger的配置文件。

  定义了Bean方法createRestApi,返回类型为Docket。传入参数DocumentationType.SWAGGER_2指定使用swagger2.0。然后通过apiInfo指定接口文档的基本信息。RequestHandlerSelectors.basePackage(“org.demo.swagger2.controller”),这是扫描注解的配置(API接口位置)。配置的是你swagger想要要加载的接口所在的包名。例如配置为com的话会扫描com包下的。这里的话扫描的是org.demo.swagger2.controller下的Controller。

```java
@Configuration
public class SwaggerConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2).pathMapping("/").select()
// 方法需要有ApiOperation注解才能生存接口文档
.apis(RequestHandlerSelectors.basePackage("org.demo.swagger2.controller"))
// 路径使用any风格
.paths(PathSelectors.any()).build()
// 接口文档的基本信息
.apiInfo(apiInfo());
}

/*
 * 接口文档详细信息
 *
 * @return
 */
private ApiInfo apiInfo() {
    return new ApiInfoBuilder().title("Springboot整合Swagger2").description("xxx-api文档")
            .termsOfServiceUrl("https://sec-in.com/").version("1.0.0").build();
}

}
```

  然后在对应的Controller内加入Swagger的注解,便于生成对应的api接口文档,常用的注解有:

  • @Api:一般用于Controller中,用于接口分组,描述具体的实现内容。
  • @ApiImplicitParam:接口说明,用于controller控制层方法参数上,表示单独的请求参数 。
  • @ApiImplicitParams:用于controller控制层方法参数上,包含多个 @ApiImplicitParam。
  • @ApiOperation:对接口发起的http请求进行描述。
  • @ApiResponse:描述接口的response。
  • @ApiParam:表示对参数的添加元数据(说明或是否必填等)。
  • @ApiModel:用于实体bean,对其进行说明
  • @ApiModelProperty:用于实体bean,对实体参数进行说明。

  例如下面的例子:

```java
@RestController
@Api(tags = "用户管理接口")
@RequestMapping("/user")
public class UserController {

@ApiOperation(value="获取用户信息",notes="根据id查询用户")
@ApiImplicitParam(name = "id",value = "用户id", defaultValue = "0")
@GetMapping("/")
public User getUserById(Long id) {
    User user = UserService.findUser(id);
    return user;
}

@ApiOperation(value="更新用户名",notes="根据id更新用户名")
@ApiImplicitParams({
        @ApiImplicitParam(name = "id", value = "用户id", defaultValue = "0"),
        @ApiImplicitParam(name = "username", value = "用户名", defaultValue = "tkswifty")
})
@PutMapping("/")
public boolean updateUsernameById(String username, Long id) {
    boolean = UserService.update(id,username)
    return user;
}

......
}

```

  实体Bean的注解:

```java
@ApiModel
public class User {
@ApiModelProperty("用户id")
private Long id;
@ApiModelProperty("用户名")
private String username;
@ApiModelProperty("用户地址")
private String address;

public Long getId() {
    return id;
}

public void setId(Long id) {
    this.id = id;
}

public String getUsername() {
    return username;
}

public void setUsername(String username) {
    this.username = username;
}

public String getAddress() {
    return address;
}

public void setAddress(String address) {
    this.address = address;
}

}

```

  启动项目后,访问/swagger-ui.html即可查看生成的接口文档:

JavaWeb中常见的信息泄漏—Swagger
  展开查看对应的api详情:

JavaWeb中常见的信息泄漏—Swagger
  execute后相关的response信息:

JavaWeb中常见的信息泄漏—Swagger
  返回了预期的结果,通过上述方式即可简单的结合Swagger-UI生成对应的API接口文档。

  除此以外,也可以引入如下依赖:

xml
<dependency>
<groupId>com.spring4all</groupId>
<artifactId>swagger-spring-boot-starter</artifactId>
<version>1.8.0.RELEASE</version>
</dependency>

  然后通过在主类中配置@EnableSwagger2Doc注解,结合配置文件的方式生产对应的API接口文档。

```java
@SpringBootApplication
@EnableSwagger2Doc
public class SpringDataJpaApplication {

public static void main(String[] args) {
    SpringApplication.run(SpringDataJpaApplication.class, args);
}

}

```

  配置文件applicaion.properties的部分配置:

swagger.title=Springboot整合Swagger2
swagger.description=xxx-api文档
swagger.licenseUrl=https://sec-in.com/
swagger.base-package=org.demo.swagger2.controller

  此外,Swagger2已经在17年停止维护了,取而代之的是Swagger3( OpenAPI Spec)。具体可以参考https://blog.readme.com/an-example-filled-guide-to-swagger-3-2/

  在pom.xml中引入相关dependency依赖,将springdoc-openapi和Swagger UI集成在一起,以便可以与我们的API规范进行交互并测试业务接口。

xml
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-core</artifactId>
<version>1.1.49</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.1.49</version>
</dependency>

  相关的注解也做了迁移:

| Swagger2 | OpenAPI Spec |
| -------------------------------------- | ------------------------------------------------------------ |
| @ApiParam | @Parameter |
| @ApiOperation(value="", notes="") | @Operation(summary = "", description = "") |
| @Api | @Tag |
| @ApiImplicitParams | @Parameters |
| @ApiImplicitParam | @Parameter |
| @ApiIgnore | @Parameter(hidden=true) Or @Operation(hidden=true) or @Hidden |
| @ApiModel | @Schema |
| @ApiModelProperty | @Schema |
| @ApiModelProperty(hidden = true) | @Schema(accessMode = READ_ONLY) |
| @ApiResponse(code = 404, message = "") | @ApiResponse(responseCode = "404", description = "") |

  同样的完成相关设置启动项目后,访问/swagger-ui.html即可查看生成的接口文档:

JavaWeb中常见的信息泄漏—Swagger

利用思路

  可以发现一个问题,以上整合Swagger生成的API文档,是直接暴露在相关web路径下的。所有人均可以访问查看。通过这一点即可获取项目上所有的接口信息。那么结合实际业务,例如如果有文件读取相关的接口,可能存在任意文件下载,相关的业务访问可能存在未授权访问等。

  常见的可利用漏洞有:

  • SQL注入
  • 任意文件上传/下载
  • 权限控制缺失
  • fastjson/jackson反序列化
  • ......

  以fastjson为例,例如如下接口文档,很明显是使用json进行提交的:

JavaWeb中常见的信息泄漏—Swagger
  那么可以尝试修改提交的内容,点击execute进行提交,进行fastjson的相关测试:

JavaWeb中常见的信息泄漏—Swagger
  也可以设置burp代理,结合repeater模块进行测试。

修复建议

  • 在生产节点禁用Swagger2:

  • 使用注解@Profile({"dev","test"}) 表示在开发或测试环境开启,而在生产关闭。

  • 使用注解@ConditionalOnProperty(name = "swagger.enable", havingValue = "true") 然后在测试配置或者开发配置中 添加 swagger.enable = true 即可开启,生产环境不填则默认关闭Swagger。

  • 在配置文件里添加一个swagger.enable属性,根据不同的application-xx.yml进行动态插入truefalse即可。然后在Swagger配置中进行设置:
    ```java
    @Value("${swagger.enable}")
    private Boolean enable;

    @Bean
    public Docket swaggerPersonApi10() {
    return new Docket(DocumentationType.SWAGGER_2)
    .select()
    .apis(RequestHandlerSelectors.basePackage("org.demo.swagger2.controller"))
    .paths(PathSelectors.any())
    .enable(enable)
    .build()
    .apiInfo(apiInfo());
    }
    ```

  具体效果如下:

JavaWeb中常见的信息泄漏—Swagger
* 结合SpringSecurity/shiro进行认证授权,将Swagger-UI的URLs加入到各自的认证和授权过滤链中,当用户访问Swagger对应的资源时,只有通过认证授权的用户才能进行访问。
* 结合nginx/Filter对对应的接口端点进行访问控制。

参考资料

https://github.com/swagger-api/swagger-ui

https://springdoc.org/faq.html#how-can-i-hide-an-operation-or-a-controller-from-documentation-.

相关推荐: 记一次对补天公益的渗透测试

无聊的时候挖挖补天公益还是比较美好的!!! 废话不多说开整,因为上次的事情打码不严谨,差点GG了。 现在我就全部打上,哈哈哈哈嗝 万事不慌,burp前去探路 ::: hljs-center 0X01批量注册 ::: 因为没有做手机验证码功能注册,而且验证码无效…

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2021年5月10日01:26:24
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   JavaWeb中常见的信息泄漏—Swaggerhttps://cn-sec.com/archives/246657.html