基于JavaSecLab 一款综合Java漏洞平台的学习思考(一)
shqI 发表于 江西 漏洞分析 1067浏览 · 2024-11-29 17:03

起始

以前只是觉得Java太难了,只是囫囵吞枣的学习,越到后面越发现离不开Java,所以想着系统学习一下,正好发现了whgojp/JavaSecLab: JavaSecLab是一款综合型Java漏洞平台,提供相关漏洞缺陷代码、修复代码、漏洞场景、审计SINK点、安全编码规范,覆盖多种漏洞场景,友好用户交互UI……

本章将跟着lab学习Swagger UI 敏感接口泄漏,SpringBoot Actuator 敏感端点泄漏,Druid 配置不当,spel注入和ssti注入的常见缺陷代码,如何防范等相关知识。

docker搭建:
git clone https://github.com/whgojp/JavaSecLab.git
mvn clean package -DskipTests
docker-compose -p javaseclab up -d
默认密码是admin/admin

SpringBoot模块


介绍

SpringBoot可以简单的理解为spring的升级版

SpringBoot框架 - 相关漏洞

Spring Boot是一个通过自动配置、嵌入式服务器和生产级功能,简化了Spring应用程序开发、配置和部署的框架,使开发者能够快速构建独立且易于部署的Java应用
在其生态系统下,也存在一些相关组件的安全隐患,如Swagger UI可能导致敏感接口泄漏,Spring Boot Actuator可能暴露敏感端口,Druid可能面临未授权访问风险,以及Spring Cloud Gateway存在远程代码执行漏洞等

漏洞情景:Swagger UI 敏感接口泄漏

tips

Swagger是一种用于描述API的开源框架,它使用OpenAPI规范来定义API的端点、请求、响应、模式等。Swagger接口泄露漏洞是指在使用Swagger描述API时,由于未正确配置访问控制或未实施安全措施,导致API接口被不授权的人员访问和利用,从而导致系统安全风险

缺陷代码=

return new Docket(DocumentationType.OAS_30)
        .pathMapping("/")
        .enable(swaggerProperties.getEnable())//生产禁用
        .apiInfo(apiInfo())
        .select()
        .apis(RequestHandlerSelectors.basePackage("top.whgojp"))//按包扫描,也可以扫描共同的父包,不会显示basic-error-controller
        .paths(PathSelectors.any())
        .build();
}
/**
 * API 页面上半部分展示信息
 */
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
        .title(swaggerProperties.getTitle())//标题
        .description(swaggerProperties.getDescription())//描述
        .contact(new Contact(swaggerProperties.getAuthor(), swaggerProperties.getUrl(), swaggerProperties.getEmail()))//作者信息
        .version(swaggerProperties.getVersion())//版本号
        .build();
}
这段代码是配置Swagger(一个API文档生成工具)在Spring Boot项目中的使用,主要是通过Docket类来配置Swagger相关的信息和文档生成规则。以下是代码的逐步解析:

1. return new Docket(DocumentationType.OAS_30)
   创建一个Docket对象,这是Swagger的核心配置类。
   DocumentationType.OAS_30表示使用OpenAPI 3.0规范(Swagger 3.0)。OAS是OpenAPI Specification(开放API规范)的缩写,是目前Swagger支持的标准版本。
2. .pathMapping("/")
   设置API路径的基础映射。这里的"/"意味着API的基础路径是根路径(即localhost:8080/)。如果想让API路径添加前缀,可以修改这个值(例如"/api")。
3. .enable(swaggerProperties.getEnable())
   通过swaggerProperties.getEnable()来动态获取是否启用Swagger文档的配置。swaggerProperties是一个配置类,它从配置文件中读取相应的参数。
   swaggerProperties.getEnable()返回一个布尔值,表示是否启用Swagger。如果为false,Swagger文档不会在生产环境中生成,通常在生产环境中会禁用Swagger以提高安全性。
4. .apiInfo(apiInfo())
   通过调用apiInfo()方法,配置Swagger文档的基本信息,如标题、描述、版本、作者等。
5. .select()
   开始选择需要暴露的API接口。它返回一个ApiSelectorBuilder,可以进一步配置哪些API接口需要包含在Swagger文档中。
6. .apis(RequestHandlerSelectors.basePackage("top.whgojp"))
   通过RequestHandlerSelectors.basePackage("top.whgojp")来指定扫描API的基础包。Swagger将扫描该包下的所有REST控制器,生成API文档。
   这里的top.whgojp是包名,你可以根据你的实际项目结构修改为需要扫描的包名。
7. .paths(PathSelectors.any())
   通过PathSelectors.any()表示扫描所有的路径,即所有的API接口都会被纳入Swagger文档中。如果你希望仅扫描某些特定路径,也可以通过PathSelectors.regex()等方法来过滤路径。
8. .build()
   最后调用build()方法,构建出一个完整的Docket对象。
   apiInfo() 方法
   这个方法返回了Swagger文档的元数据信息,包括:

title: API的标题,通常是项目名称或者API的概述。
description: API的描述,可以简单介绍该API的功能和用途。
contact: API作者的联系信息,包含名字、网站和邮箱。
version: API的版本号,通常与项目的版本同步。

我们访问给的swagger接口,可以看到很多泄露的信息。

但题目可不会直接给swagger接口,所以要么我们bp抓包进行爆破,下面是一些常用路径,

/api
/api-docs
/api-docs/swagger.json
/api.html
/api/api-docs
/api/apidocs
/api/doc
/api/swagger
/api/swagger-ui
/api/swagger-ui.html
/api/swagger-ui.html/
/api/swagger-ui.json
/api/swagger.json
/api/swagger/
/api/swagger/ui
/api/swagger/ui/
/api/swaggerui
/api/swaggerui/
/api/v1/
/api/v1/api-docs
/api/v1/apidocs
/api/v1/swagger
/api/v1/swagger-ui
/api/v1/swagger-ui.html
/api/v1/swagger-ui.json
/api/v1/swagger.json
/api/v1/swagger/
/api/v2
/api/v2/api-docs
/api/v2/apidocs
/api/v2/swagger
/api/v2/swagger-ui
/api/v2/swagger-ui.html
/api/v2/swagger-ui.json
/api/v2/swagger.json
/api/v2/swagger/
/api/v3
/apidocs
/apidocs/swagger.json
/doc.html
/docs/
/druid/index.html
/graphql
/libs/swaggerui
/libs/swaggerui/
/spring-security-oauth-resource/swagger-ui.html
/spring-security-rest/api/swagger-ui.html
/sw/swagger-ui.html
/swagger
/swagger-resources
/swagger-resources/configuration/security
/swagger-resources/configuration/security/
/swagger-resources/configuration/ui
/swagger-resources/configuration/ui/
/swagger-ui
/swagger-ui.html
/swagger-ui.html#/api-memory-controller
/swagger-ui.html/
/swagger-ui.json
/swagger-ui/swagger.json
/swagger.json
/swagger.yml
/swagger/
/swagger/index.html
/swagger/static/index.html
/swagger/swagger-ui.html
/swagger/ui/
/Swagger/ui/index
/swagger/ui/index
/swagger/v1/swagger.json
/swagger/v2/swagger.json
/template/swagger-ui.html
/user/swagger-ui.html
/user/swagger-ui.html/
/v1.x/swagger-ui.html
/v1/api-docs
/v1/swagger.json
/v2/api-docs
/v3/api-docs

要么使用自动化扫描工具,这里介绍一款SpringBoot-Scan
接着分析数据,这里就介绍一个插件swagger,火狐,谷歌里基本都长一个样
如果要什么密码认证限制和给了json文件的,可以用swagger-hack工具,自动化爬取并自动测试所有swagger接口

https://github.com/jayus0821/swagger-hack

漏洞情景:SpringBoot Actuator 敏感端点泄漏

tips

Spring Boot Actuator 是一个用于监控和管理 Spring Boot 应用程序的功能模块。它提供了一系列生产就绪的功能,帮助你了解应用程序的运行状况,以及在运行时对应用程序进行调整。Actuator 使用了 Spring MVC 来暴露各种 HTTP 或 JMX 端点,通过这些端点你可以获取到应用程序的运行信息,如健康状态、指标、线程 dump、环境变量等

缺陷代码

management:

  # 端点信息接口使用的端口,为了和主系统接口使用的端口进行分离

  server:
    port: 8080

  # 端点健康情况,默认值"never",设置为"always"可以显示硬盘使用情况和线程情况

  endpoint:
    health:
      show-details: always

  # 设置端点暴露的哪些内容,默认["health","info"],设置"*"代表暴露所有可访问的端点

  endpoints:
    web:
      exposure:
        include: '*'
      base-path: /sys/actuator

// 相关端点信息
路径          描述          默认启用
auditevents  显示当前应用程序的审计事件信息  Yes
beans  显示一个应用中所有Spring Beans的完整列表  Yes
conditions  显示配置类和自动配置类(configuration and auto-configuration  classes)的状态及它们被应用或未被应用的原因configprops  显示一个所有@ConfigurationProperties的集合列表  Yes
env  显示来自Spring的 ConfigurableEnvironment的属性  Yes
flyway  显示数据库迁移路径,如果有的话  Yes
health  显示应用的健康信息(当使用一个未认证连接访问时显示一个简单  的’status’,使用认证连接访问则显示全部信息详情)info  显示任意的应用信息  Yes
liquibase  展示任何Liquibase数据库迁移路径,如果有的话  Yes
metrics  展示当前应用的metrics信息  Yes
mappings  显示一个所有@RequestMapping路径的集合列表  Yes
scheduledtasks  显示应用程序中的计划任务  Yes
sessions  允许从Spring会话支持的会话存储中检索和删除(retrieval and deletion)  用户会话。使用Spring Session对反应性Web应用程序的支持时不可用。shutdown  允许应用以优雅的方式关闭(默认情况下不启用)  No
threaddump  执行一个线程dump  Yes
heapdump  返回一个GZip压缩的hprof堆dump文件  Yes
jolokia  通过HTTP暴露JMX beans(当Jolokia在类路径上时,WebFlux不可用)  Yes
logfile  返回日志文件内容(如果设置了logging.file或logging.path属性的话),支持使用HTTP Range头接收日志文件内容的部分信息  Yes
prometheus  以可以被Prometheus服务器抓取的格式显示metrics信息  Yes

上面的这段配置和描述主要涉及 Spring Boot Actuator 的配置和端点说明。Spring Boot Actuator 是 Spring Boot 提供的一个强大工具,它可以用来监控和管理应用的运行状态。你提供的配置和说明帮助我们了解如何配置这些端点以及它们提供的功能。

1. management.server.port

yaml复制代码server:
port: 8080

  • 这部分配置指定了 Spring Boot Actuator 端点服务的端口。默认情况下,Spring Boot 会将应用的所有端点暴露在与应用主服务相同的端口上(比如 8080)。但通过这个配置,你可以将 Actuator 的端口与应用的主端口分离开来,从而避免暴露管理端点与业务端点在同一个端口上。
2. management.endpoint.health.show-details

yaml复制代码endpoint:
health:
show-details: always

  • 这部分配置控制了健康检查 ( /actuator/health ) 端点显示的详细信息。

    • 默认情况下,健康检查端点显示的是简短的 status 信息。
    • 设置为 always 时,健康检查会返回更多的详细信息,包括硬盘使用情况、线程情况等。这对于故障排查和监控非常有用。
3. management.endpoints.web.exposure.include

yaml复制代码endpoints:
web:
exposure:
include: ''- 这部分配置决定了暴露的管理端点内容。''

表示暴露所有可用的端点。

  • 默认情况下,Spring Boot Actuator 只暴露 healthinfo 端点。
  • 如果你希望暴露更多的端点(比如 /actuator/metrics/actuator/beans 等),可以使用这个配置。
  • 注意:暴露过多的端点可能带来安全风险,因此在生产环境中应根据需要谨慎选择暴露的端点。
4. management.endpoints.web.base-path

yaml

复制代码
base-path: /sys/actuator

  • 这部分配置设置了所有 Actuator 端点的基础路径。默认情况下,Actuator 的端点会暴露在 /actuator 路径下。
  • 如果你希望改变这个路径,比如使用 /sys/actuator,可以通过这段配置来实现。
5. Actuator 端点及其描述
  • auditevents:显示应用程序的审计事件信息。默认启用。
  • beans:显示应用中所有 Spring Beans 的完整列表。默认启用。
  • conditions:显示配置类和自动配置类的状态,及它们被应用或未被应用的原因。默认启用。
  • configprops:显示所有 @ConfigurationProperties 注解的集合列表。默认启用。
  • env:显示来自 Spring ConfigurableEnvironment 的属性,包含系统环境、配置文件等。默认启用。
  • flyway:显示 Flyway 数据库迁移的路径信息(如果使用 Flyway)。默认启用。
  • health:显示应用的健康信息,show-details 配置项控制显示的详情信息。默认启用。
  • info:显示任意应用信息。默认启用。
  • liquibase:显示 Liquibase 数据库迁移路径的信息(如果使用 Liquibase)。默认启用。
  • metrics:展示应用的监控数据(如 JVM 内存使用、请求次数等)。默认启用。
  • mappings:显示所有 @RequestMapping 路径的集合列表。默认启用。
  • scheduledtasks:显示应用程序中的计划任务。默认启用。
  • sessions:允许从 Spring Session 支持的会话存储中检索和删除用户会话(如果启用了 Spring Session)。默认启用。
  • shutdown:允许应用程序优雅地关闭。默认禁用,必须显式启用。
  • threaddump:执行线程 dump,获取当前 JVM 中所有线程的堆栈信息。默认启用。
  • heapdump:返回 GZip 压缩的 hprof 堆 dump 文件。默认启用。
  • jolokia:通过 HTTP 暴露 JMX beans(当 Jolokia 在类路径上时,WebFlux 不可用)。默认启用。
  • logfile:返回日志文件内容(如果设置了 logging.filelogging.path)。支持 HTTP Range 请求。默认启用。
  • prometheus:以 Prometheus 可抓取的格式显示 metrics 信息。默认启用。
6. 注意事项
  • 在生产环境中,

    安全性

    非常重要。默认情况下,Spring Boot Actuator 提供了很多暴露的端点,可能会泄露敏感的内部信息。因此:

    • 在生产环境中,建议只暴露必要的端点(如 healthinfo)。
    • 可以通过设置 management.endpoints.web.exposure.include 来选择性暴露端点。
    • 还可以通过设置访问权限和认证来保护这些端点,避免未授权的访问。

打开给的接口按钮,可以看到有很多的泄露信息。

在/actuator/env/可以看到泄露的version,dir等,其他接口就不一一介绍了,

还有很多进一步分析利用数据的方法,比如说,首先访问/actuator/heapdump 接口,下载应用实时的 JVM 堆信息。然后通过JDK自带的JVisualVM工具对JVM堆的dump文件进行分析。

漏洞情景:Druid 配置不当

tips

Apache Druid 是阿里开源的高性能连接池和实时分析分布式数据存储系统,专为大规模时序数据和事件流分析设计,具有快速查询、低延迟写入及横向扩展能力
在导入Druid依赖时,没有在application.yml中添加配置(或忘记配置账号密码),此时Druid可以未授权访问,攻击者可直接获取websession信息,进行session爆破,以及通过weburi获取敏感信息路径,进行Fuzz攻击

缺陷代码

druid:
  ...
  filters: stat,log4j     # wall 这里关闭sql防火墙
  stat-view-servlet:
    enabled: true
    url-pattern: /druid/*

#        login-username: admin

#        login-password: admin

    reset-enable: false

  # 防火墙配置

#      wall:

#        config:

#          multi-statement-allow: false

这段配置涉及的是 Druid 数据源的设置,其中包括了一些常见的功能配置,主要是为了监控、日志记录、SQL防火墙等功能。以下是对各部分配置的解释:

1. filters: stat,log4j
  • 这部分配置指定了 Druid 数据源的过滤器(filters)。
    • stat:启用了 Druid 的统计功能,这可以帮助你查看数据库连接池的统计信息,例如活跃连接数、请求数等。
    • log4j:启用了日志功能,Druid 会将SQL执行日志通过 Log4j 打印出来,便于日志记录和排查问题。
2. stat-view-servlet

stat-view-servlet:
enabled: true
url-pattern: /druid/*
reset-enable: false

  • enabled: true:启用 Druid 的监控视图功能。它会在 Web 应用中暴露一个可访问的管理界面,用于查看连接池的状态。
  • url-pattern: /druid/*:指定 Druid 管理界面的访问路径。访问这个路径时,能够查看 Druid 的统计信息(例如连接池状态、SQL 执行统计等)。
  • reset-enable: false:设置是否允许重置 Druid 数据源的统计信息。如果设置为 false,则禁止在监控页面上重置统计数据,避免误操作。
3. wall 防火墙配置

wall:

config:

multi-statement-allow: false

  • Wall(SQL 防火墙) 是 Druid 提供的一个功能,用于防止 SQL 注入等安全问题。它会检查 SQL 是否符合一定的安全规则,尤其是防止恶意 SQL 的执行。
  • multi-statement-allow: false:如果启用该配置,表示不允许一次执行多个 SQL 语句(即禁止 ; 分号分隔的多条 SQL)。这有助于提高安全性,防止某些 SQL 注入攻击。
4. stat-view-servletlogin-username, login-password(注释部分)

login-username: admin

login-password: admin

  • 如果需要对 Druid 监控页面进行身份验证,可以取消注释这两行并设置用户名和密码。
    • login-username:设置登录的用户名。
    • login-password:设置登录的密码。
  • 这样只有提供正确的凭据才能访问 Druid 的监控页面,增加了安全性。
5. 关闭 SQL 防火墙(注释掉部分)

wall:

config:

multi-statement-allow: false

  • 这部分防火墙配置被注释掉了,表示在当前配置中 SQL 防火墙未启用或未进行详细配置。
  • 如果需要启用 SQL 防火墙并禁止多条 SQL 语句执行,可以取消注释并根据需要进行配置。

访问给的接口,

一般授权的话有两种方法:
方法1: 设置StatViewServlet(监控页面)为 false
方法2: 给druid的web页面设置账户密码,增加访问druid的权限。

但这里显示没权限,应该是设置了方法1.

一般未授权漏洞访问后是如下界面,

然后就是收集泄露登录用户的session,不管成不成功,找接口进行爆破。

SPEL注入模块

介绍:

SPEL - 表达式注入

SPEL(Spring Expression Language):SPEL是Spring表达式语言,允许在运行时动态查询和操作对象属性、调用方法等,类似于Struts2中的OGNL表达式。当参数未经过滤时,攻击者可以注入恶意的SPEL表达式,从而执行任意代码

  表达式语言/模板:表达式语言用于动态处理固定格式的内容,其中变量部分可以在运行时填入。模板可以将固定部分提取出来,方便模块化管理,动态填充变量内容

漏洞情景:原生漏洞环境

tips

代码审计SINK点:
  1、SpelExpressionParser.parseExpression()
  2、Expression.getValue()

缺陷代码

public R vul(String ex) {
    // 创建SpEL解析器,ExpressionParser接口用于表示解析器,SpelExpressionParser为默认实现
    ExpressionParser parser = new SpelExpressionParser();

    // Expression expression = parser.parseExpression(ex);
    // String result =  expression.getValue().toString();

    // 构造上下文 上下文其实就是设置好某些变量的值,执行表达式时根据这些设置好的内容区获取值 在不配置的情况下具有默认类型的上下文
    EvaluationContext evaluationContext = new StandardEvaluationContext();

    // 解析表达式,将用户输入的字符串解析为Expression对象
    Expression exp = parser.parseExpression(ex);

    // 通过上下文计算表达式的值,并将结果转换为字符串
    String result = exp.getValue(evaluationContext).toString();
    return R.ok(result);
}

先来学习下SpEL基础,Spring表达式语言全称为“Spring Expression Language”,缩写为“SpEL”,类似于Struts2x中使用的OGNL表达式语言,能在运行时构建复杂表达式、存取对象图属性、对象方法调用等等,并且能与Spring功能完美整合,如能用来配置Bean定义。

表达式语言给静态Java语言增加了动态功能。

SpEL在求表达式值时一般分为四步,其中第三步可选:首先构造一个解析器,其次解析器解析字符串表达式,在此构造上下文,最后根据上下文得到表达式运算后的值。

1)创建解析器:SpEL使用ExpressionParser接口表示解析器,提供SpelExpressionParser默认实现;

2)解析表达式:使用ExpressionParser的parseExpression来解析相应的表达式为Expression对象。

3)构造上下文:准备比如变量定义等等表达式需要的上下文数据。

4)求值:通过Expression接口的getValue方法根据上下文获得表达式值。

理解了基础,就来通过创建实例,调用方法先构造一个简单的调用runtime的payload。

会用到的语法:

spel语法中的`T()`操作符 , `T()`操作符会返回一个object , 它可以帮助我们获取某个类的静态方法 , 用法`T(全限定类名).方法名()`,后面会用得到

spel中的`#`操作符可以用于标记对象

java调用,由于Runtime类使用了单例模式-饿汉式,需要调用Runtime的静态方法得到Runtime实例

使用string参数 (java.lang包下的类不需要加全限定类名)

T(java.lang.Runtime).getRuntime().exec("whoami")

字符串数组方法调用

T(Runtime).getRuntime().exec(new String[]{"open","/System/Applications/Calculator.app"})

解释: 由于RunTime类使用了单例模式 ,获取对象的话不能直接通过构造方法获得,必须通过静态方法getRuntime来获得 , 其源码可参考下图 , 调用静态方法的话需要使用SpEL的T()操作符,T()操作符会返回一个object.



payload传入代码成为ex,即可攻击成功


怎么修复呢,

安全环境:使用SimpleEvaluationContext限制表达式功能

tips

SimpleEvaluationContext不支持以下危险功能:
    Java 类型引用: 无法通过表达式引用Java类,从而防止调用静态方法
    构造函数调用: 不能通过表达式实例化新对象
    Bean 引用: 无法通过表达式访问Spring应用上下文中的bean

安全代码

public R safe(String ex) {
    ExpressionParser parser = new SpelExpressionParser();

    // 使用 SimpleEvaluationContext 限制表达式功能(Java类型引用、构造函数调用、Bean引用),防止危险的操作
    EvaluationContext simpleContext = SimpleEvaluationContext.forReadOnlyDataBinding().build();

    Expression exp = parser.parseExpression(ex);

    String result = exp.getValue(simpleContext).toString();
    return R.ok(result);
}


执行命令不成功。

SSTI注入模块

第60篇:Thymeleaf模板注入漏洞总结及修复方法(上篇)-CSDN博客

SSTI - 模板引擎注入

SSTI(Server Side Template Injection):模板引擎是一种通过将模板中的占位符替换为实际数据来动态生成内容的工具,如HTML页面、邮件等。它简化了视图层的设计,但如果未对用户输入进行有效校验,可能导致安全风险如任意代码执行
  Java中常用的模板引擎有Freemarker、Velocity、Thymeleaf等,在这里以Thymeleaf引擎为例

漏洞环境:thymeleaf模版注入

漏洞基本上分为三种情况,

第一种情况,return内容可控

第二种情况,URL路径可控

第三种情况,模板内容可控

如果学习了python的flask,php的tp等之类的框架,其实也很好理解。

tip

高版本SpringBoot/Thymeleaf不存在模板注入问题,这里SpringBoot版本为2.4.1,Thymeleaf同上

缺陷代码

public String vul1(@RequestParam String para, Model model) {
    // 用户输入直接拼接到模板路径,可能导致SSTI(服务器端模板注入)漏洞
    return "/vul/ssti/" + para;
}

public void vul2(@PathVariable String path) {
    log.info("SSTI注入:"+path);
}

    // 缺陷组件版本参考
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
<!--        <version>2.7.14</version>-->
    <version>2.4.1</version>
    <relativePath/>
</parent>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
    <version>2.4.1</version>
</dependency>

vul1 方法:

方法功能:这个方法接受一个HTTP请求参数para,并将其与字符串"/vul/ssti/"拼接后作为一个模板路径返回。

漏洞分析

  • @RequestParam注解表示从HTTP请求中获取名为para的参数。
  • 用户输入的para参数会被直接拼接到模板路径中,而没有任何过滤或校验。
  • 如果用户输入的内容是恶意的模板表达式(如${...}),并且应用使用了Spring的Thymeleaf等模板引擎,那么服务器端就可能执行这些模板代码,导致服务器端模板注入(SSTI)漏洞
  • 这意味着攻击者可以通过构造恶意的para参数,执行任意的模板语言代码,从而可能执行任意的服务器端操作,导致代码注入、信息泄露等问题。

payload:

/ssti/vul1?para=__${new java.util.Scanner(T(java.lang.Runtime).getRuntime().exec('id').getInputStream()).next()}__::.x

vul2 方法

方法功能:这个方法接受一个路径变量path,并将其作为日志的一部分记录下来。

漏洞分析

  • @PathVariable注解表示从URL路径中获取path变量。
  • 日志中直接输出了path变量的值。若该值未经验证,攻击者可能会利用这一点进行日志注入攻击,导致敏感信息泄漏或日志伪造。
  • 这个方法的风险较小,因为它仅是记录日志,但如果path中包含恶意的控制字符或表达式,可能会影响日志的完整性或内容,造成信息泄漏。

payload:

/ssti/vul2/__${T(java.lang.Runtime).getRuntime().exec('open -a Calculator')}__::.x


这里因为不是本地环境,而是起在vps上的docker,所以无法展示计算器

安全环境:thymeleaf模版注入

基于白名单的路径校验


控制器返回为void,方法参数设置为HttpServletResponse后,Spring MVC会跳过视图解析过程。

会返回白屏。

tips

安全编码规范:
  1、避免用户输入直接作为模板名称或路径
  2、对所有动态内容进行严格校验和转义,包括模板变量
  3、选择支持自动转义的安全模板引擎(如Thymeleaf的th:text)
  4、使用白名单限制动态渲染的模板,控制可访问的模板范围

安全代码

public String safe1(String para, Model model) {
    List<String> white_list = new ArrayList<>(Arrays.asList("vul", "ssti"));
    if (white_list.contains(para)){
        return "vul/ssti" + para;
    } else{
        return "common/401";
    }
}
@GetMapping("/safe2/{path}")
public void safe2(@PathVariable String path, HttpServletResponse response) {
    log.info("SSTI注入:"+path);
}

safe1方法:

该方法通过检查用户输入的 para 参数来决定返回不同的模板路径。

  • 输入参数para 是通过 HTTP 请求传入的一个字符串参数。
  • 白名单检查:方法中定义了一个白名单(white_list),其中包含了 "vul""ssti" 两个字符串。
  • 如果用户输入的 para 参数在白名单中,方法将返回一个路径 "vul/ssti" + para
  • 如果用户输入的 para 参数不在白名单中,方法返回 "common/401",这通常表示一个权限问题或访问被拒绝的页面。

safe2方法:

过程:
  • @GetMapping("/safe2/{path}"):当请求路径为 /safe2/{path} 时,这个方法会被调用,{path} 的值将会传递给 path 参数。
  • HttpServletResponse:Spring MVC 将自动注入 HttpServletResponse 对象,这使得我们可以直接操作 HTTP 响应(例如设置响应状态码、写入响应内容等)。
  • 视图解析跳过:因为返回类型是 void,Spring MVC 不会尝试通过 ViewResolver 查找视图或渲染模板,而是跳过视图解析过程,直接操作响应。
结果:
  • 响应将直接通过 HttpServletResponse 发送给客户端,而不经过视图解析。
  • 任何响应内容(如 JSON、HTML 或纯文本)都可以通过 response.getWriter()response.getOutputStream() 写入。
为什么会跳过视图解析?**

Spring MVC 会根据控制器方法的返回类型来决定是否进行视图解析:

  • 返回值是 void
    • Spring MVC 会检查方法参数。如果包含 HttpServletResponse,它会直接操作这个响应对象,跳过视图解析。
    • 这是因为返回 void 意味着没有返回视图名称或对象,Spring MVC 默认不进行视图解析,转而依赖开发者直接操作 HttpServletResponse 来构建响应。
  • 返回值是视图名称(如字符串)
    • 如果方法返回的是视图名称(例如字符串 "home"),Spring MVC 会使用视图解析器(ViewResolver)来解析这个视图名称,并渲染对应的视图(如 JSP 或 Thymeleaf 模板)。
  • 返回值是模型数据
    • 如果返回值是一个模型对象(例如 ModelAndView 或一个 POJO),Spring MVC 会将其传递给视图解析器,并在返回的视图中展示数据。
使用 HttpServletResponse 的场景**

当我们不想使用视图解析器,且想要直接控制 HTTP 响应时,HttpServletResponse 非常有用。常见的场景包括:

  • 直接返回 HTTP 状态码或响应内容:如直接返回 JSON 数据、纯文本、HTML 内容等。
  • 文件下载:通过设置响应头和响应内容,直接触发文件下载,而不依赖于视图解析。
  • 自定义错误页面:如果方法返回 void 并通过 HttpServletResponse 设置错误代码和消息,Spring MVC 不会渲染默认的错误页面视图,而是直接发送错误响应。

总结:

想要深入理解,还得是跟着链子走一遍,不能全依靠javaseclab。

1 条评论
某人
表情
可输入 255