@@ -24,112 +24,137 @@ def ldap_connect_opts(rhost, rport, connect_timeout, ssl: true, opts: {})
24
24
25
25
case opts [ :ldap_auth ]
26
26
when Msf ::Exploit ::Remote ::AuthOption ::SCHANNEL
27
- pfx_path = opts [ :ldap_cert_file ]
28
- raise Msf ::ValidationError , 'The LDAP::CertFile option is required when using SCHANNEL authentication.' if pfx_path . blank?
29
- raise Msf ::ValidationError , 'The SSL option must be enabled when using SCHANNEL authentication.' if ssl != true
27
+ raise Msf ::ValidationError , 'The SSL option must be enabled when using SCHANNEL authentication.' unless ssl
30
28
31
- unless ::File . file? ( pfx_path ) && ::File . readable? ( pfx_path )
32
- raise Msf ::ValidationError , 'Failed to load the PFX certificate file. The path was not a readable file.'
33
- end
34
-
35
- begin
36
- pkcs = OpenSSL ::PKCS12 . new ( File . binread ( pfx_path ) , '' )
37
- rescue StandardError => e
38
- raise Msf ::ValidationError , "Failed to load the PFX file (#{ e } )"
39
- end
40
-
41
- connect_opts [ :auth ] = {
42
- method : :sasl ,
43
- mechanism : 'EXTERNAL' ,
44
- initial_credential : '' ,
45
- challenge_response : true
46
- }
47
- connect_opts [ :encryption ] = {
48
- method : :start_tls ,
49
- tls_options : {
50
- verify_mode : OpenSSL ::SSL ::VERIFY_NONE ,
51
- cert : pkcs . certificate ,
52
- key : pkcs . key
53
- }
54
- }
29
+ connect_opts . merge! ( ldap_auth_opts_scahnnel ( opts ) )
55
30
when Msf ::Exploit ::Remote ::AuthOption ::KERBEROS
56
- raise Msf ::ValidationError , 'The Ldap::Rhostname option is required when using Kerberos authentication.' if opts [ :ldap_rhostname ] . blank?
57
- raise Msf ::ValidationError , 'The DOMAIN option is required when using Kerberos authentication.' if opts [ :domain ] . blank?
58
-
59
- offered_etypes = Msf ::Exploit ::Remote ::AuthOption . as_default_offered_etypes ( opts [ :ldap_krb_offered_enc_types ] )
60
- raise Msf ::ValidationError , 'At least one encryption type is required when using Kerberos authentication.' if offered_etypes . empty?
61
-
62
- kerberos_authenticator = Msf ::Exploit ::Remote ::Kerberos ::ServiceAuthenticator ::LDAP . new (
63
- host : opts [ :domain_controller_rhost ] . blank? ? nil : opts [ :domain_controller_rhost ] ,
64
- hostname : opts [ :ldap_rhostname ] ,
65
- realm : opts [ :domain ] ,
66
- username : opts [ :username ] ,
67
- password : opts [ :password ] ,
68
- framework : opts [ :framework ] ,
69
- framework_module : opts [ :framework_module ] ,
70
- cache_file : opts [ :ldap_krb5_cname ] . blank? ? nil : opts [ :ldap_krb5_cname ] ,
71
- ticket_storage : opts [ :kerberos_ticket_storage ] ,
72
- offered_etypes : offered_etypes
73
- )
74
-
75
- connect_opts [ :auth ] = {
76
- method : :sasl ,
77
- mechanism : 'GSS-SPNEGO' ,
78
- initial_credential : proc do
79
- kerberos_result = kerberos_authenticator . authenticate
80
- kerberos_result [ :security_blob ]
81
- end ,
82
- challenge_response : true
83
- }
31
+ connect_opts . merge! ( ldap_auth_opts_kerberos ( opts ) )
84
32
when Msf ::Exploit ::Remote ::AuthOption ::NTLM
85
- ntlm_client = RubySMB ::NTLM ::Client . new (
86
- opts [ :username ] ,
87
- opts [ :password ] ,
88
- workstation : 'WORKSTATION' ,
89
- domain : opts [ :domain ] . blank? ? '.' : opts [ :domain ] ,
90
- flags :
91
- RubySMB ::NTLM ::NEGOTIATE_FLAGS [ :UNICODE ] |
92
- RubySMB ::NTLM ::NEGOTIATE_FLAGS [ :REQUEST_TARGET ] |
93
- RubySMB ::NTLM ::NEGOTIATE_FLAGS [ :NTLM ] |
94
- RubySMB ::NTLM ::NEGOTIATE_FLAGS [ :ALWAYS_SIGN ] |
95
- RubySMB ::NTLM ::NEGOTIATE_FLAGS [ :EXTENDED_SECURITY ] |
96
- RubySMB ::NTLM ::NEGOTIATE_FLAGS [ :KEY_EXCHANGE ] |
97
- RubySMB ::NTLM ::NEGOTIATE_FLAGS [ :TARGET_INFO ] |
98
- RubySMB ::NTLM ::NEGOTIATE_FLAGS [ :VERSION_INFO ]
99
- )
100
-
101
- negotiate = proc do |challenge |
102
- ntlmssp_offset = challenge . index ( 'NTLMSSP' )
103
- type2_blob = challenge . slice ( ntlmssp_offset ..-1 )
104
- challenge = [ type2_blob ] . pack ( 'm' )
105
- type3_message = ntlm_client . init_context ( challenge )
106
- type3_message . serialize
107
- end
108
-
109
- connect_opts [ :auth ] = {
110
- method : :sasl ,
111
- mechanism : 'GSS-SPNEGO' ,
112
- initial_credential : ntlm_client . init_context . serialize ,
113
- challenge_response : negotiate
114
- }
33
+ connect_opts . merge! ( ldap_auth_opts_ntlm ( opts ) )
115
34
when Msf ::Exploit ::Remote ::AuthOption ::PLAINTEXT
116
- connect_opts [ :auth ] = {
117
- method : :simple ,
118
- username : opts [ :username ] ,
119
- password : opts [ :password ]
120
- }
35
+ connect_opts . merge! ( ldap_auth_opts_plaintext ( opts ) )
121
36
when Msf ::Exploit ::Remote ::AuthOption ::AUTO
122
- unless opts [ :username ] . blank? # plaintext if specified
123
- connect_opts [ :auth ] = {
124
- method : :simple ,
125
- username : opts [ :username ] ,
126
- password : opts [ :password ]
127
- }
37
+ if opts [ :username ] . present? && opts [ :domain ] . present?
38
+ connect_opts . merge! ( ldap_auth_opts_ntlm ( opts ) )
39
+ elsif opts [ :username ] . present?
40
+ connect_opts . merge! ( ldap_auth_opts_plaintext ( opts ) )
128
41
end
129
42
end
130
43
131
44
connect_opts
132
45
end
46
+
47
+ private
48
+
49
+ def ldap_auth_opts_kerberos ( opts )
50
+ auth_opts = { }
51
+ raise Msf ::ValidationError , 'The Ldap::Rhostname option is required when using Kerberos authentication.' if opts [ :ldap_rhostname ] . blank?
52
+ raise Msf ::ValidationError , 'The DOMAIN option is required when using Kerberos authentication.' if opts [ :domain ] . blank?
53
+
54
+ offered_etypes = Msf ::Exploit ::Remote ::AuthOption . as_default_offered_etypes ( opts [ :ldap_krb_offered_enc_types ] )
55
+ raise Msf ::ValidationError , 'At least one encryption type is required when using Kerberos authentication.' if offered_etypes . empty?
56
+
57
+ kerberos_authenticator = Msf ::Exploit ::Remote ::Kerberos ::ServiceAuthenticator ::LDAP . new (
58
+ host : opts [ :domain_controller_rhost ] . blank? ? nil : opts [ :domain_controller_rhost ] ,
59
+ hostname : opts [ :ldap_rhostname ] ,
60
+ realm : opts [ :domain ] ,
61
+ username : opts [ :username ] ,
62
+ password : opts [ :password ] ,
63
+ framework : opts [ :framework ] ,
64
+ framework_module : opts [ :framework_module ] ,
65
+ cache_file : opts [ :ldap_krb5_cname ] . blank? ? nil : opts [ :ldap_krb5_cname ] ,
66
+ ticket_storage : opts [ :kerberos_ticket_storage ] ,
67
+ offered_etypes : offered_etypes
68
+ )
69
+
70
+ auth_opts [ :auth ] = {
71
+ method : :sasl ,
72
+ mechanism : 'GSS-SPNEGO' ,
73
+ initial_credential : proc do
74
+ kerberos_result = kerberos_authenticator . authenticate
75
+ kerberos_result [ :security_blob ]
76
+ end ,
77
+ challenge_response : true
78
+ }
79
+ auth_opts
80
+ end
81
+
82
+ def ldap_auth_opts_ntlm ( opts )
83
+ auth_opts = { }
84
+ ntlm_client = RubySMB ::NTLM ::Client . new (
85
+ opts [ :username ] ,
86
+ opts [ :password ] ,
87
+ workstation : 'WORKSTATION' ,
88
+ domain : opts [ :domain ] . blank? ? '.' : opts [ :domain ] ,
89
+ flags :
90
+ RubySMB ::NTLM ::NEGOTIATE_FLAGS [ :UNICODE ] |
91
+ RubySMB ::NTLM ::NEGOTIATE_FLAGS [ :REQUEST_TARGET ] |
92
+ RubySMB ::NTLM ::NEGOTIATE_FLAGS [ :NTLM ] |
93
+ RubySMB ::NTLM ::NEGOTIATE_FLAGS [ :ALWAYS_SIGN ] |
94
+ RubySMB ::NTLM ::NEGOTIATE_FLAGS [ :EXTENDED_SECURITY ] |
95
+ RubySMB ::NTLM ::NEGOTIATE_FLAGS [ :KEY_EXCHANGE ] |
96
+ RubySMB ::NTLM ::NEGOTIATE_FLAGS [ :TARGET_INFO ] |
97
+ RubySMB ::NTLM ::NEGOTIATE_FLAGS [ :VERSION_INFO ]
98
+ )
99
+
100
+ negotiate = proc do |challenge |
101
+ ntlmssp_offset = challenge . index ( 'NTLMSSP' )
102
+ type2_blob = challenge . slice ( ntlmssp_offset ..-1 )
103
+ challenge = [ type2_blob ] . pack ( 'm' )
104
+ type3_message = ntlm_client . init_context ( challenge )
105
+ type3_message . serialize
106
+ end
107
+
108
+ auth_opts [ :auth ] = {
109
+ method : :sasl ,
110
+ mechanism : 'GSS-SPNEGO' ,
111
+ initial_credential : ntlm_client . init_context . serialize ,
112
+ challenge_response : negotiate
113
+ }
114
+ auth_opts
115
+ end
116
+
117
+ def ldap_auth_opts_plaintext ( opts )
118
+ auth_opts = { }
119
+ auth_opts [ :auth ] = {
120
+ method : :simple ,
121
+ username : opts [ :username ] ,
122
+ password : opts [ :password ]
123
+ }
124
+ auth_opts
125
+ end
126
+
127
+ def ldap_auth_opts_scahnnel ( opts )
128
+ auth_opts = { }
129
+ pfx_path = opts [ :ldap_cert_file ]
130
+ raise Msf ::ValidationError , 'The LDAP::CertFile option is required when using SCHANNEL authentication.' if pfx_path . blank?
131
+
132
+ unless ::File . file? ( pfx_path ) && ::File . readable? ( pfx_path )
133
+ raise Msf ::ValidationError , 'Failed to load the PFX certificate file. The path was not a readable file.'
134
+ end
135
+
136
+ begin
137
+ pkcs = OpenSSL ::PKCS12 . new ( File . binread ( pfx_path ) , '' )
138
+ rescue StandardError => e
139
+ raise Msf ::ValidationError , "Failed to load the PFX file (#{ e } )"
140
+ end
141
+
142
+ auth_opts [ :auth ] = {
143
+ method : :sasl ,
144
+ mechanism : 'EXTERNAL' ,
145
+ initial_credential : '' ,
146
+ challenge_response : true
147
+ }
148
+ auth_opts [ :encryption ] = {
149
+ method : :start_tls ,
150
+ tls_options : {
151
+ verify_mode : OpenSSL ::SSL ::VERIFY_NONE ,
152
+ cert : pkcs . certificate ,
153
+ key : pkcs . key
154
+ }
155
+ }
156
+ auth_opts
157
+ end
133
158
end
134
159
end
135
160
end
0 commit comments