Class: Rex::Proto::LDAP::Auth

Inherits:
Object
  • Object
show all
Defined in:
lib/rex/proto/ldap/auth.rb

Constant Summary collapse

SUPPORTS_SASL =
%w[GSS-SPNEGO NTLM]
NTLM_CONST =
Rex::Proto::NTLM::Constants
NTLM_CRYPT =
Rex::Proto::NTLM::Crypt
MESSAGE =
Rex::Proto::NTLM::Message

Instance Method Summary collapse

Constructor Details

#initialize(challenge, domain, server, dnsname, dnsdomain) ⇒ Auth

Initialize the required variables

Parameters:

  • challenge (String)

    NTLM Server Challenge

  • domain (String)

    Domain value used in NTLM

  • server (String)

    Server value used in NTLM

  • dnsname (String)

    DNS Name value used in NTLM

  • dnsdomain (String)

    DNS Domain value used in NTLM



21
22
23
24
25
26
27
# File 'lib/rex/proto/ldap/auth.rb', line 21

def initialize(challenge, domain, server, dnsname, dnsdomain)
  @domain = domain.nil? ? 'DOMAIN' : domain
  @server = server.nil? ? 'SERVER' : server
  @dnsname = dnsname.nil? ? 'server' : dnsname
  @dnsdomain = dnsdomain.nil? ? 'example.com' : dnsdomain
  @challenge = [challenge.nil? ? Rex::Text.rand_text_alphanumeric(16) : challenge].pack('H*')
end

Instance Method Details

#handle_anonymous_request(user_login, auth_info = {}) ⇒ Object

Handle Anonymous authentication requests

Parameters:

  • user_login (OpenStruct)

    User login information

  • auth_info (Hash) (defaults to: {})

    Processed authentication information



58
59
60
61
62
63
64
65
66
67
# File 'lib/rex/proto/ldap/auth.rb', line 58

def handle_anonymous_request(, auth_info = {})
  if .name.empty? && .authentication.empty?
    auth_info[:user] = .name
    auth_info[:pass] = .authentication
    auth_info[:domain] = nil
    auth_info[:result_code] = Net::LDAP::ResultCodeSuccess
    auth_info[:auth_type] = 'Anonymous'
  end
  auth_info
end

#handle_sasl_request(user_login, auth_info = {}) ⇒ Object

Handle SASL authentication requests

Parameters:

  • user_login (OpenStruct)

    User login information

  • auth_info (Hash) (defaults to: {})

    Processed authentication information



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/rex/proto/ldap/auth.rb', line 145

def handle_sasl_request(, auth_info = {})
  case .authentication[1]
  when /NTLMSSP/
    message = Net::NTLM::Message.parse(.authentication[1])
    if message.is_a?(::Net::NTLM::Message::Type1)
      auth_info[:server_creds] = generate_type2_response(message)
      auth_info[:result_code] = Net::LDAP::ResultCodeSaslBindInProgress
    elsif message.is_a?(::Net::NTLM::Message::Type3)
      auth_info = handle_type3_message(message, auth_info)
      auth_info[:result_code] = Net::LDAP::ResultCodeAuthMethodNotSupported
    end
  else
    auth_info[:result_code] = Net::LDAP::ResultCodeAuthMethodNotSupported
    auth_info[:error_msg] = 'Invalid LDAP Login Attempt => Unsupported SASL Format'
  end
  auth_info[:auth_type] = 'SASL'
  auth_info
end

#handle_simple_request(user_login, auth_info = {}) ⇒ Object

Handle Simple authentication requests

Parameters:

  • user_login (OpenStruct)

    User login information

  • auth_info (Hash) (defaults to: {})

    Processed authentication information



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
# File 'lib/rex/proto/ldap/auth.rb', line 89

def handle_simple_request(, auth_info = {})
  domains = []
  names = []
  if !.name.empty?
    if .name =~ /@/
      pub_info = .name.split('@')
      if pub_info.length <= 2
        auth_info[:user], auth_info[:domain] = pub_info
      else
        auth_info[:result_code] = Net::LDAP::ResultCodeInvalidCredentials
        auth_info[:error_msg] = "Invalid LDAP Login Attempt => DN:#{.name}"
      end
    elsif .name =~ /,/
      begin
        dn = Net::LDAP::DN.new(.name)
        dn.each_pair do |key, value|
          if key == 'cn'
            names << value
          elsif key == 'dc'
            domains << value
          end
        end
        auth_info[:user] = names.join('')
        auth_info[:domain] = domains.empty? ? nil : domains.join('.')
      rescue Net::LDAP::InvalidDNError => e
        auth_info[:error_msg] = "Invalid LDAP Login Attempt => DN:#{.name}"
        raise e
      end
    elsif .name =~ /\\/
      pub_info = .name.split('\\')
      if pub_info.length <= 2
        auth_info[:domain], auth_info[:user] = pub_info
      else
        auth_info[:result_code] = Net::LDAP::ResultCodeInvalidCredentials
        auth_info[:error_msg] = "Invalid LDAP Login Attempt => DN:#{.name}"
      end
    else
      auth_info[:user] = .name
      auth_info[:domain] = nil
      auth_info[:result_code] = Net::LDAP::ResultCodeInvalidCredentials
    end
    auth_info[:private] = .authentication
    auth_info[:private_type] = :password
    auth_info[:result_code] = Net::LDAP::ResultCodeAuthMethodNotSupported if auth_info[:result_code].nil?
    auth_info[:auth_type] = 'Simple'
    auth_info
  end
end

#handle_unknown_request(user_login, auth_info = {}) ⇒ Object

Handle Unknown authentication requests

Parameters:

  • user_login (OpenStruct)

    User login information

  • auth_info (Hash) (defaults to: {})

    Processed authentication information



76
77
78
79
80
# File 'lib/rex/proto/ldap/auth.rb', line 76

def handle_unknown_request(, auth_info = {})
  auth_info[:result_code] = Net::LDAP::ResultCodeAuthMethodNotSupported
  auth_info[:error_msg] = 'Invalid LDAP Login Attempt => Unknown Authentication Format'
  auth_info
end

#process_login_request(user_login) ⇒ Object

Process the incoming LDAP login requests from clients

Parameters:

  • user_login (OpenStruct)

    User login information



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/rex/proto/ldap/auth.rb', line 35

def ()
  auth_info = {}

  if .name.empty? && .authentication.empty? # Anonymous
    auth_info = handle_anonymous_request(, auth_info)
  elsif !.name.empty? # Simple
    auth_info = handle_simple_request(, auth_info)
  elsif sasl?()
    auth_info = handle_sasl_request(, auth_info)
  else
    auth_info = handle_unknown_request(, auth_info)
  end

  auth_info
end