Class: Metasploit::Framework::LoginScanner::SMB

Inherits:
Object
  • Object
show all
Includes:
Base, RexSocket, Tcp::Client
Defined in:
lib/metasploit/framework/login_scanner/smb.rb

Overview

This is the LoginScanner class for dealing with the Server Messaging Block protocol.

Defined Under Namespace

Modules: AccessLevels, StatusCodes

Constant Summary collapse

CAN_GET_SESSION =
true
DEFAULT_REALM =
'WORKSTATION'
LIKELY_PORTS =
[ 445 ]
LIKELY_SERVICE_NAMES =
[ "smb" ]
PRIVATE_TYPES =
[ :password, :ntlm_hash ]
REALM_KEY =
Metasploit::Model::Realm::Key::ACTIVE_DIRECTORY_DOMAIN

Instance Attribute Summary collapse

Attributes included from Tcp::Client

#max_send_size, #send_delay, #sock

Instance Method Summary collapse

Methods included from Tcp::Client

#chost, #cport, #disconnect, #proxies, #rhost, #rport, #set_tcp_evasions, #ssl, #ssl_version

Instance Attribute Details

#dispatcherRubySMB::Dispatcher::Socket

Returns:

  • (RubySMB::Dispatcher::Socket)

53
54
55
# File 'lib/metasploit/framework/login_scanner/smb.rb', line 53

def dispatcher
  @dispatcher
end

Instance Method Details

#attempt_bogus_login(domain) ⇒ Result

If login is successul and Result#access_level is not set then arbitrary credentials are accepted. If it is set to Guest, then arbitrary credentials are accepted, but given Guest permissions.

Parameters:

  • domain (String)

    Domain to authenticate against. Use an empty string for local accounts.

Returns:


63
64
65
66
67
68
69
70
71
72
73
# File 'lib/metasploit/framework/login_scanner/smb.rb', line 63

def (domain)
  if defined?(@result_for_bogus)
    return @result_for_bogus
  end
  cred = Credential.new(
    public: Rex::Text.rand_text_alpha(8),
    private: Rex::Text.rand_text_alpha(8),
    realm: domain
  )
  @result_for_bogus = (cred)
end

#attempt_login(credential) ⇒ Object


77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/metasploit/framework/login_scanner/smb.rb', line 77

def (credential)

  begin
    connect
  rescue ::Rex::ConnectionError => e
    result = Result.new(
      credential:credential,
      status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT,
      proof: e,
      host: host,
      port: port,
      protocol: 'tcp',
      service_name: 'smb'
    )
    return result
  end
  proof = nil

  begin
    realm       = (credential.realm   || "").force_encoding('UTF-8')
    username    = (credential.public  || "").force_encoding('UTF-8')
    password    = (credential.private || "").force_encoding('UTF-8')
    client      = RubySMB::Client.new(self.dispatcher, username: username, password: password, domain: realm)
    status_code = client.

    if status_code == WindowsError::NTStatus::STATUS_SUCCESS
      # Windows SMB will return an error code during Session
      # Setup, but nix Samba requires a Tree Connect. Try admin$
      # first, since that will tell us if this user has local
      # admin access. Fall back to IPC$ which should be accessible
      # to any user with valid creds.
      begin
        tree = client.tree_connect("\\\\#{host}\\admin$")
        # Check to make sure we can write a file to this dir
        if tree.permissions.add_file == 1
          access_level = AccessLevels::ADMINISTRATOR
        end
      rescue Exception => e
        client.tree_connect("\\\\#{host}\\IPC$")
      end
    end

    case status_code.name
      when 'STATUS_SUCCESS', 'STATUS_PASSWORD_MUST_CHANGE', 'STATUS_PASSWORD_EXPIRED'
        status = Metasploit::Model::Login::Status::SUCCESSFUL
      when 'STATUS_ACCOUNT_LOCKED_OUT'
        status = Metasploit::Model::Login::Status::LOCKED_OUT
      when 'STATUS_LOGON_FAILURE', 'STATUS_ACCESS_DENIED'
        status = Metasploit::Model::Login::Status::INCORRECT
      when *StatusCodes::CORRECT_CREDENTIAL_STATUS_CODES
        status = Metasploit::Model::Login::Status::DENIED_ACCESS
      else
        status = Metasploit::Model::Login::Status::INCORRECT
    end
  rescue ::Rex::ConnectionError, Errno::EINVAL, RubySMB::Error::NetBiosSessionService => e
    status = Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
    proof = e
  rescue RubySMB::Error::UnexpectedStatusCode => e
    status = Metasploit::Model::Login::Status::INCORRECT
  ensure
    client.disconnect! if client
  end

  if status == Metasploit::Model::Login::Status::SUCCESSFUL && credential.public.empty?
    access_level ||= AccessLevels::GUEST
  end

  result = Result.new(credential: credential, status: status, proof: proof, access_level: access_level)
  result.host         = host
  result.port         = port
  result.protocol     = 'tcp'
  result.service_name = 'smb'
  result
end

#connectObject


152
153
154
155
156
# File 'lib/metasploit/framework/login_scanner/smb.rb', line 152

def connect
  disconnect
  self.sock       = super
  self.dispatcher = RubySMB::Dispatcher::Socket.new(self.sock)
end

#set_sane_defaultsObject


158
159
160
161
162
# File 'lib/metasploit/framework/login_scanner/smb.rb', line 158

def set_sane_defaults
  self.connection_timeout           = 10 if self.connection_timeout.nil?
  self.max_send_size                = 0 if self.max_send_size.nil?
  self.send_delay                   = 0 if self.send_delay.nil?
end