diff --git a/lib/metasploit/framework/credential_collection.rb b/lib/metasploit/framework/credential_collection.rb index 342d3f523471..4ae037740e3a 100644 --- a/lib/metasploit/framework/credential_collection.rb +++ b/lib/metasploit/framework/credential_collection.rb @@ -282,19 +282,19 @@ def each_unfiltered_password_first File.open(pass_file, 'r:binary') do |pass_fd| pass_fd.each_line do |pass_from_file| pass_from_file.chomp! + if username.present? + yield Metasploit::Framework::Credential.new(public: username, private: pass_from_file, realm: realm, private_type: :password) + end if user_as_pass yield Metasploit::Framework::Credential.new(public: pass_from_file, private: pass_from_file, realm: realm, private_type: :password) end - if user_fd - user_fd.each_line do |user_from_file| - user_from_file.chomp! - yield Metasploit::Framework::Credential.new(public: user_from_file, private: pass_from_file, realm: realm, private_type: private_type(pass_from_file)) - end - user_fd.seek(0) - end - additional_privates.each do |add_private| - yield Metasploit::Framework::Credential.new(public: user_from_file, private: add_private, realm: realm, private_type: private_type(add_private)) + next unless user_fd + + user_fd.each_line do |user_from_file| + user_from_file.chomp! + yield Metasploit::Framework::Credential.new(public: user_from_file, private: pass_from_file, realm: realm, private_type: private_type(pass_from_file)) end + user_fd.seek(0) end end end @@ -313,6 +313,17 @@ def each_unfiltered_password_first end end + additional_privates.each do |add_private| + if username.present? + yield Metasploit::Framework::Credential.new(public: username, private: add_private, realm: realm, private_type: private_type(add_private)) + end + user_fd.each_line do |user_from_file| + user_from_file.chomp! + yield Metasploit::Framework::Credential.new(public: user_from_file, private: add_private, realm: realm, private_type: private_type(add_private)) + end + user_fd.seek(0) + end + additional_publics.each do |add_public| if password.present? yield Metasploit::Framework::Credential.new(public: add_public, private: password, realm: realm, private_type: private_type(password) ) diff --git a/spec/lib/metasploit/framework/credential_collection_spec.rb b/spec/lib/metasploit/framework/credential_collection_spec.rb index 064c81033986..44fa477fc95b 100644 --- a/spec/lib/metasploit/framework/credential_collection_spec.rb +++ b/spec/lib/metasploit/framework/credential_collection_spec.rb @@ -159,6 +159,91 @@ end end + context 'when given a username and password' do + let(:password) { 'password' } + let(:username) { 'root' } + + specify do + expected = [ + Metasploit::Framework::Credential.new(public: 'root', private: 'password'), + ] + expect { |b| collection.each(&b) }.to yield_successive_args(*expected) + end + end + + context 'when given a pass_file, user_file, password spray and a default username' do + let(:password) { nil } + let(:username) { 'root' } + let(:password_spray) { true } + let(:pass_file) do + filename = "pass_file" + stub_file = StringIO.new("password1\npassword2\n") + allow(File).to receive(:open).with(filename,/^r/).and_yield stub_file + + filename + end + let(:user_file) do + filename = "user_file" + stub_file = StringIO.new("user1\nuser2\nuser3\n") + allow(File).to receive(:open).with(filename,/^r/).and_return stub_file + + filename + end + + specify do + expected = [ + Metasploit::Framework::Credential.new(public: "root", private: "password1"), + Metasploit::Framework::Credential.new(public: "user1", private: "password1"), + Metasploit::Framework::Credential.new(public: "user2", private: "password1"), + Metasploit::Framework::Credential.new(public: "user3", private: "password1"), + Metasploit::Framework::Credential.new(public: "root", private: "password2"), + Metasploit::Framework::Credential.new(public: "user1", private: "password2"), + Metasploit::Framework::Credential.new(public: "user2", private: "password2"), + Metasploit::Framework::Credential.new(public: "user3", private: "password2"), + ] + expect { |b| collection.each(&b) }.to yield_successive_args(*expected) + end + end + + context 'when given a pass_file, user_file, password spray and additional privates' do + let(:password) { nil } + let(:username) { 'root' } + let(:password_spray) { true } + let(:additional_privates) { ['foo'] } + let(:pass_file) do + filename = "pass_file" + stub_file = StringIO.new("password1\npassword2\n") + allow(File).to receive(:open).with(filename,/^r/).and_yield stub_file + + filename + end + let(:user_file) do + filename = "user_file" + stub_file = StringIO.new("user1\nuser2\nuser3\n") + allow(File).to receive(:open).with(filename,/^r/).and_return stub_file + + filename + end + + specify do + expected = [ + Metasploit::Framework::Credential.new(public: "root", private: "password1"), + Metasploit::Framework::Credential.new(public: "user1", private: "password1"), + Metasploit::Framework::Credential.new(public: "user2", private: "password1"), + Metasploit::Framework::Credential.new(public: "user3", private: "password1"), + Metasploit::Framework::Credential.new(public: "root", private: "password2"), + Metasploit::Framework::Credential.new(public: "user1", private: "password2"), + Metasploit::Framework::Credential.new(public: "user2", private: "password2"), + Metasploit::Framework::Credential.new(public: "user3", private: "password2"), + Metasploit::Framework::Credential.new(public: "root", private: "foo"), + Metasploit::Framework::Credential.new(public: "user1", private: "foo"), + Metasploit::Framework::Credential.new(public: "user2", private: "foo"), + Metasploit::Framework::Credential.new(public: "user3", private: "foo"), + ] + expect { |b| collection.each(&b) }.to yield_successive_args(*expected) + end + end + context 'when given a username, user_file and pass_file' do let(:password) { nil } let(:username) { 'my_username' }