@@ -177,17 +177,20 @@ def run_host(ip)
177177 case result . status
178178 when Metasploit ::Model ::Login ::Status ::SUCCESSFUL
179179 print_brute :level => :good , :ip => ip , :msg => "Success: '#{ result . credential } ' '#{ result . proof . to_s . gsub ( /[\r \n \e \b \a ]/ , ' ' ) } '"
180- credential_core = create_credential ( credential_data )
181- credential_data [ :core ] = credential_core
182- create_credential_login ( credential_data )
183- tmp_key = result . credential . private
184- ssh_key = SSHKey . new tmp_key
180+ ssh_key = Net ::SSH ::KeyFactory . load_data_private_key ( credential_data [ :private_data ] , datastore [ 'key_pass' ] , false )
181+
182+ begin
183+ credential_core = create_credential ( credential_data )
184+ credential_data [ :core ] = credential_core
185+ create_credential_login ( credential_data )
186+ rescue ::StandardError => e
187+ print_error ( "Failed to create credential: #{ e . class } #{ e } " )
188+ credential_core = nil
189+ end
190+
185191 if datastore [ 'CreateSession' ]
186- if credential_core . is_a? Metasploit ::Credential ::Core
187- session_setup ( result , scanner , ssh_key . fingerprint , credential_core . private_id )
188- else
189- session_setup ( result , scanner , ssh_key . fingerprint , nil )
190- end
192+ cred_id = credential_core . is_a? ( Metasploit ::Credential ::Core ) ? credential_core . private_id : nil
193+ session_setup ( result , scanner , ssh_key . public_key . fingerprint , cred_id )
191194 end
192195 if datastore [ 'GatherProof' ] && scanner . get_platform ( result . proof ) == 'unknown'
193196 msg = "While a session may have opened, it may be bugged. If you experience issues with it, re-run this module with"
@@ -224,7 +227,7 @@ class KeyCollection < Metasploit::Framework::CredentialCollection
224227
225228 # Override CredentialCollection#has_privates?
226229 def has_privates?
227- ! @key_data . empty ?
230+ @key_data . present ?
228231 end
229232
230233 def realm
@@ -235,49 +238,62 @@ def valid?
235238 @error_list = [ ]
236239 @key_data = Set . new
237240
238- unless @private_key . present? || @key_path . present?
241+ if @private_key . present?
242+ results = validate_private_key ( @private_key )
243+ elsif @key_path . present?
244+ results = validate_key_path ( @key_path )
245+ else
246+ @error_list << "No key path or key provided"
239247 raise RuntimeError , "No key path or key provided"
240248 end
241249
242- if @key_path . present?
243- if File . directory? ( @key_path )
244- @key_files ||= Dir . entries ( @key_path ) . reject { |f | f =~ /^\x2e |\x2e pub$/ }
245- @key_files . each do |f |
246- begin
247- data = read_key ( File . join ( @key_path , f ) )
248- @key_data << data if valid_key? ( data )
249- rescue StandardError => e
250- @error_list << "#{ File . join ( @key_path , f ) } : #{ e } "
251- end
252- end
253- elsif File . file? ( @key_path )
254- begin
255- data = read_key ( @key_path )
256- @key_data << data if valid_key? ( data )
257- rescue StandardError => e
258- @error_list << "#{ @key_path } could not be read, #{ e } "
259- end
260- else
261- raise RuntimeError , "Invalid key path"
262- end
250+ if results [ :key_data ] . present?
251+ @key_data . merge ( results [ :key_data ] )
252+ else
253+ @error_list . concat ( results [ :error_list ] ) if results [ :error_list ] . present?
263254 end
264255
265- if @private_key . present?
266- data = Net ::SSH ::KeyFactory . load_data_private_key ( @private_key , @password , false ) . to_s
267- if valid_key? ( data )
268- @key_data << data
269- else
270- raise RuntimeError , "Invalid private key"
256+ @key_data . present?
257+ end
258+
259+ def validate_private_key ( private_key )
260+ key_data = Set . new
261+ error_list = [ ]
262+ begin
263+ if Net ::SSH ::KeyFactory . load_data_private_key ( private_key , @password , false ) . present?
264+ key_data << private_key
271265 end
266+ rescue StandardError => e
267+ error_list << "Error validating private key: #{ e } "
272268 end
273-
274- !@key_data . empty?
269+ { key_data : key_data , error_list : error_list }
275270 end
276271
277- def valid_key? ( key_data )
278- !!( key_data . match ( /BEGIN [RECD]SA PRIVATE KEY/ ) && !key_data . match ( /Proc-Type:.*ENCRYPTED/ ) )
272+ def validate_key_path ( key_path )
273+ key_data = Set . new
274+ error_list = [ ]
275+
276+ if File . file? ( key_path )
277+ key_files = [ key_path ]
278+ elsif File . directory? ( key_path )
279+ key_files = Dir . entries ( key_path ) . reject { |f | f =~ /^\x2e |\x2e pub$/ } . map { |f | File . join ( key_path , f ) }
280+ else
281+ return { key_data : nil , error : "#{ key_path } Invalid key path" }
282+ end
283+
284+ key_files . each do |f |
285+ begin
286+ if read_key ( f ) . present?
287+ key_data << File . read ( f )
288+ end
289+ rescue StandardError => e
290+ error_list << "#{ f } : #{ e } "
291+ end
292+ end
293+ { key_data : key_data , error_list : error_list }
279294 end
280295
296+
281297 def each
282298 prepended_creds . each { |c | yield c }
283299
@@ -307,7 +323,7 @@ def each_key
307323
308324 def read_key ( file_path )
309325 @cache ||= { }
310- @cache [ file_path ] ||= Net ::SSH ::KeyFactory . load_data_private_key ( File . read ( file_path ) , password , false , key_path ) . to_s
326+ @cache [ file_path ] ||= Net ::SSH ::KeyFactory . load_private_key ( file_path , password , false )
311327 @cache [ file_path ]
312328 end
313329 end
0 commit comments