Module: Msf::Exploit::Remote::LDAP

Defined in:
lib/msf/core/exploit/remote/ldap/server.rb,
lib/msf/core/exploit/remote/ldap.rb

Overview

This module exposes methods for querying a remote LDAP service

Defined Under Namespace

Modules: Server

Instance Method Summary collapse

Instance Method Details

#discover_base_dn(ldap) ⇒ Object


124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/msf/core/exploit/remote/ldap.rb', line 124

def discover_base_dn(ldap)
  naming_contexts = get_naming_contexts(ldap)

  unless naming_contexts
    print_error("#{peer} Base DN cannot be determined")
    return
  end

  # NOTE: We assume the first namingContexts value is the base DN
  base_dn = naming_contexts.first

  print_good("#{peer} Discovered base DN: #{base_dn}")
  base_dn
end

#get_connect_optsObject


39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/msf/core/exploit/remote/ldap.rb', line 39

def get_connect_opts
  connect_opts = {
    host: rhost,
    port: rport,
    connect_timeout: datastore['LDAP::ConnectTimeout']
  }

  if datastore['SSL']
    connect_opts[:encryption] = {
      method: :simple_tls,
      tls_options: {
        verify_mode: OpenSSL::SSL::VERIFY_NONE
      }
    }
  end

  if datastore['BIND_DN']
    connect_opts[:auth] = {
      method: :simple,
      username: datastore['BIND_DN']
    }
    if datastore['BIND_PW']
      connect_opts[:auth][:password] = datastore['BIND_PW']
    end
  end
  connect_opts
end

#get_naming_contexts(ldap) ⇒ Object


103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/msf/core/exploit/remote/ldap.rb', line 103

def get_naming_contexts(ldap)
  vprint_status("#{peer} Getting root DSE")

  unless (root_dse = ldap.search_root_dse)
    print_error("#{peer} Could not retrieve root DSE")
    return
  end

  vprint_line(root_dse.to_ldif)

  naming_contexts = root_dse[:namingcontexts]

  # NOTE: Net::LDAP converts attribute names to lowercase
  if naming_contexts.empty?
    print_error("#{peer} Empty namingContexts attribute")
    return
  end

  naming_contexts
end

#initialize(info = {}) ⇒ Object


11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/msf/core/exploit/remote/ldap.rb', line 11

def initialize(info = {})
  super

  register_options([
    Opt::RHOST,
    Opt::RPORT(389),
    OptBool.new('SSL', [false, 'Enable SSL on the LDAP connection', false]),
    OptString.new('BIND_DN', [false, 'The username to authenticate to LDAP server']),
    OptString.new('BIND_PW', [false, 'Password for the BIND_DN'])
  ])

  register_advanced_options([
    OptFloat.new('LDAP::ConnectTimeout', [true, 'Timeout for LDAP connect', 10.0])
  ])
end

#ldap_connect(opts = {}, &block) ⇒ Object


67
68
69
# File 'lib/msf/core/exploit/remote/ldap.rb', line 67

def ldap_connect(opts = {}, &block)
  Net::LDAP.open(get_connect_opts.merge(opts), &block)
end

#ldap_new(opts = {}) {|ldap| ... } ⇒ Object

Yields:

  • (ldap)

71
72
73
74
75
76
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
# File 'lib/msf/core/exploit/remote/ldap.rb', line 71

def ldap_new(opts = {})
  ldap = Net::LDAP.new(get_connect_opts.merge(opts))

  # NASTY, but required
  # monkey patch ldap object in order to ignore bind errors
  # Some servers (e.g. OpenLDAP) return result even after a bind
  # has failed, e.g. with LDAP_INAPPROPRIATE_AUTH - anonymous bind disallowed.
  # See: https://www.openldap.org/doc/admin23/security.html#Authentication%20Methods
  # "Note that disabling the anonymous bind mechanism does not prevent anonymous
  # access to the directory."
  #
  # Bug created for Net:LDAP https://github.com/ruby-ldap/ruby-net-ldap/issues/375
  #
  def ldap.use_connection(args)
    if @open_connection
      yield @open_connection
    else
      begin
        conn = new_connection
        conn.bind(args[:auth] || @auth)
        # Commented out vs. original
        # result = conn.bind(args[:auth] || @auth)
        # return result unless result.result_code == Net::LDAP::ResultCodeSuccess
        yield conn
      ensure
        conn.close if conn
      end
    end
  end
  yield ldap
end

#peerObject


35
36
37
# File 'lib/msf/core/exploit/remote/ldap.rb', line 35

def peer
  "#{rhost}:#{rport}"
end

#rhostObject


27
28
29
# File 'lib/msf/core/exploit/remote/ldap.rb', line 27

def rhost
  datastore['RHOST']
end

#rportObject


31
32
33
# File 'lib/msf/core/exploit/remote/ldap.rb', line 31

def rport
  datastore['RPORT']
end