@@ -22,7 +22,8 @@ def http_options_for(datastores)
22
22
mysql_keys = %w[ RHOSTS RPORT USERNAME PASSWORD ]
23
23
postgres_keys = %w[ RHOSTS RPORT USERNAME PASSWORD DATABASE ]
24
24
ssh_keys = %w[ RHOSTS RPORT USERNAME PASSWORD ]
25
- required_keys = dynamic_keys + http_keys + smb_keys + mysql_keys + postgres_keys + ssh_keys
25
+ ldap_keys = %w[ RHOSTS RPORT SSL LDAPDomain LDAPUsername LDAPPassword BASE_DN ]
26
+ required_keys = dynamic_keys + http_keys + smb_keys + mysql_keys + postgres_keys + ssh_keys + ldap_keys
26
27
datastores . map do |datastore |
27
28
# Workaround: Manually convert the datastore to a hash ourselves as `datastore.to_h` coerces all datatypes into strings
28
29
# which prevents this test suite from validating types correctly. i.e. The tests need to ensure that RPORT is correctly
@@ -154,6 +155,33 @@ def initialize
154
155
mod
155
156
end
156
157
158
+ let ( :ldap_mod ) do
159
+ mod_klass = Class . new ( Msf ::Auxiliary ) do
160
+ include Msf ::Exploit ::Remote ::LDAP
161
+ include Msf ::Exploit ::Remote ::LDAP ::Queries
162
+
163
+ def initialize
164
+ super (
165
+ 'Name' => 'mock ldap module' ,
166
+ 'Description' => 'mock ldap module' ,
167
+ 'Author' => [ 'Unknown' ] ,
168
+ 'License' => MSF_LICENSE
169
+ )
170
+
171
+ register_options ( [
172
+ Msf ::OptString . new ( 'BASE_DN' , [ false , 'LDAP base DN if you already have it' ] )
173
+ ] )
174
+ end
175
+ end
176
+
177
+ mod = mod_klass . new
178
+ datastore = Msf ::ModuleDataStore . new ( mod )
179
+ allow ( mod ) . to receive ( :framework ) . and_return ( nil )
180
+ mod . send ( :datastore= , datastore )
181
+ datastore . import_options ( mod . options )
182
+ mod
183
+ end
184
+
157
185
let ( :mysql_mod ) do
158
186
mod_klass = Class . new ( Msf ::Auxiliary ) do
159
187
include Msf ::Exploit ::Remote ::MYSQL
@@ -908,6 +936,74 @@ def create_tempfile(content)
908
936
expect ( each_host_for ( ssh_mod ) ) . to have_datastore_values ( expected )
909
937
end
910
938
end
939
+
940
+ context 'when using the ldap scheme' do
941
+ it 'enumerates ldap schemes for scanners when no user or password are specified' do
942
+ ldap_mod . datastore [ 'RHOSTS' ] = 'ldap://example.com/ ldaps://example.com/'
943
+ expected = [
944
+ { 'RHOSTNAME' => 'example.com' , 'RHOSTS' => '192.0.2.2' , 'RPORT' => 389 , 'SSL' => false , 'LDAPDomain' => nil , 'LDAPUsername' => nil , 'LDAPPassword' => nil , 'BASE_DN' => nil } ,
945
+ { 'RHOSTNAME' => 'example.com' , 'RHOSTS' => '192.0.2.2' , 'RPORT' => 636 , 'SSL' => true , 'LDAPDomain' => nil , 'LDAPUsername' => nil , 'LDAPPassword' => nil , 'BASE_DN' => nil }
946
+ ]
947
+ expect ( each_host_for ( ldap_mod ) ) . to have_datastore_values ( expected )
948
+ end
949
+
950
+ it 'enumerates ldap schemes for scanners when a port is specified' do
951
+ ldap_mod . datastore [ 'RHOSTS' ] = 'ldap://example.com:1389/ ldaps://example.com:1636/'
952
+ expected = [
953
+ { 'RHOSTNAME' => 'example.com' , 'RHOSTS' => '192.0.2.2' , 'RPORT' => 1389 , 'SSL' => false , 'LDAPDomain' => nil , 'LDAPUsername' => nil , 'LDAPPassword' => nil , 'BASE_DN' => nil } ,
954
+ { 'RHOSTNAME' => 'example.com' , 'RHOSTS' => '192.0.2.2' , 'RPORT' => 1636 , 'SSL' => true , 'LDAPDomain' => nil , 'LDAPUsername' => nil , 'LDAPPassword' => nil , 'BASE_DN' => nil }
955
+ ]
956
+ expect ( each_host_for ( ldap_mod ) ) . to have_datastore_values ( expected )
957
+ end
958
+
959
+ it 'enumerates ldap schemes for scanners when no user or password are specified and uses the default option values instead' do
960
+ ldap_mod . datastore . import_options (
961
+ Msf ::OptionContainer . new (
962
+ [
963
+ Msf ::OptString . new ( 'LDAPUsername' , [ true , 'The username to authenticate as' , 'db2admin' ] , fallbacks : [ 'USERNAME' ] ) ,
964
+ Msf ::OptString . new ( 'LDAPPassword' , [ true , 'The password for the specified username' , 'db2admin' ] , fallbacks : [ 'PASSWORD' ] ) ,
965
+ ]
966
+ ) ,
967
+ ldap_mod . class ,
968
+ true
969
+ )
970
+ ldap_mod . datastore [ 'RHOSTS' ] = 'ldap://example.com/ ldap://[email protected] / ldap://user:[email protected] ldap://:@example.com'
971
+ expected = [
972
+ { 'RHOSTNAME' => 'example.com' , 'RHOSTS' => '192.0.2.2' , 'RPORT' => 389 , 'SSL' => false , 'LDAPDomain' => nil , 'LDAPUsername' => 'db2admin' , 'LDAPPassword' => 'db2admin' , 'BASE_DN' => nil } ,
973
+ { 'RHOSTNAME' => 'example.com' , 'RHOSTS' => '192.0.2.2' , 'RPORT' => 389 , 'SSL' => false , 'LDAPDomain' => '' , 'LDAPUsername' => 'user' , 'LDAPPassword' => 'db2admin' , 'BASE_DN' => nil } ,
974
+ { 'RHOSTNAME' => 'example.com' , 'RHOSTS' => '192.0.2.2' , 'RPORT' => 389 , 'SSL' => false , 'LDAPDomain' => '' , 'LDAPUsername' => 'user' , 'LDAPPassword' => 'password' , 'BASE_DN' => nil } ,
975
+ { 'RHOSTNAME' => 'example.com' , 'RHOSTS' => '192.0.2.2' , 'RPORT' => 389 , 'SSL' => false , 'LDAPDomain' => '' , 'LDAPUsername' => '' , 'LDAPPassword' => '' , 'BASE_DN' => nil }
976
+ ]
977
+ expect ( each_host_for ( ldap_mod ) ) . to have_datastore_values ( expected )
978
+ end
979
+
980
+ it 'enumerates ldap schemes for scanners when a user and password are specified' do
981
+ ldap_mod . datastore [ 'RHOSTS' ] = 'ldap://user:[email protected] /'
982
+ expected = [
983
+ { 'RHOSTNAME' => 'example.com' , 'RHOSTS' => '192.0.2.2' , 'RPORT' => 389 , 'SSL' => false , 'LDAPDomain' => '' , 'LDAPUsername' => 'user' , 'LDAPPassword' => 'pass' , 'BASE_DN' => nil } ,
984
+ ]
985
+ expect ( each_host_for ( ldap_mod ) ) . to have_datastore_values ( expected )
986
+ end
987
+
988
+ it 'enumerates ldap schemes for scanners when a domain, user and password are specified' do
989
+ ldap_mod . datastore [ 'RHOSTS' ] = 'ldap://domain;user:[email protected] /'
990
+ expected = [
991
+ { 'RHOSTNAME' => 'example.com' , 'RHOSTS' => '192.0.2.2' , 'RPORT' => 389 , 'SSL' => false , 'LDAPDomain' => 'domain' , 'LDAPUsername' => 'user' , 'LDAPPassword' => 'pass' , 'BASE_DN' => nil } ,
992
+ ]
993
+ expect ( each_host_for ( ldap_mod ) ) . to have_datastore_values ( expected )
994
+ end
995
+
996
+ it 'enumerates ldap schemes for when the module has BASE_DN available' do
997
+ ldap_mod . datastore [ 'RHOSTS' ] = 'ldap://[email protected] ldap://[email protected] / ldap://[email protected] /dc=msflab,dc=local'
998
+ expected = [
999
+ { 'RHOSTNAME' => 'example.com' , 'RHOSTS' => '192.0.2.2' , 'RPORT' => 389 , 'SSL' => false , 'LDAPDomain' => '' , 'LDAPUsername' => 'user' , 'LDAPPassword' => nil , 'BASE_DN' => nil } ,
1000
+ { 'RHOSTNAME' => 'example.com' , 'RHOSTS' => '192.0.2.2' , 'RPORT' => 389 , 'SSL' => false , 'LDAPDomain' => '' , 'LDAPUsername' => 'user' , 'LDAPPassword' => nil , 'BASE_DN' => nil } ,
1001
+ { 'RHOSTNAME' => 'example.com' , 'RHOSTS' => '192.0.2.2' , 'RPORT' => 389 , 'SSL' => false , 'LDAPDomain' => '' , 'LDAPUsername' => 'user' , 'LDAPPassword' => nil , 'BASE_DN' => 'dc=msflab,dc=local' }
1002
+ ]
1003
+ expect ( each_host_for ( ldap_mod ) ) . to have_datastore_values ( expected )
1004
+ end
1005
+ end
1006
+
911
1007
# TODO: Discuss adding a test for the datastore containing an existing TARGETURI,and running with a HTTP url without a path. Should the TARGETURI be overridden to '/', '', or unaffected, and the default value is used instead?
912
1008
913
1009
it 'enumerates a combination of all syntaxes' do
0 commit comments