From 897b0b1ee5cfad1c110facc548d8dcabf09ca5fc Mon Sep 17 00:00:00 2001 From: David Maloney Date: Sun, 15 Jun 2014 13:37:50 -0500 Subject: [PATCH] wordlist enumerators with some specs started the enumerators on the wordlist class and began adding the specs for them --- lib/metasploit/framework/jtr/wordlist.rb | 178 +++++++++++++++++- spec/file_fixtures/fake_common_roots.txt | 3 + spec/file_fixtures/fake_default_wordlist.txt | 3 + .../metasploit/framework/jtr/wordlist_spec.rb | 30 ++- 4 files changed, 198 insertions(+), 16 deletions(-) create mode 100644 spec/file_fixtures/fake_common_roots.txt create mode 100644 spec/file_fixtures/fake_default_wordlist.txt diff --git a/lib/metasploit/framework/jtr/wordlist.rb b/lib/metasploit/framework/jtr/wordlist.rb index 827deb7dc7..6f4c544b3c 100644 --- a/lib/metasploit/framework/jtr/wordlist.rb +++ b/lib/metasploit/framework/jtr/wordlist.rb @@ -77,23 +77,169 @@ module Metasploit end end - def each_word - # Make sure are attributes are all valid first! - valid! + # This method searches all saved Credentials in the database + # and yields all passwords, usernames, and realm names it finds. + # + # @yieldparam word [String] the expanded word + # @return [void] + def each_cred_word + Metasploit::Credential::Password.all.each do |password| + yield password.data + end - # Yield the expanded form of each line of the custom wordlist if one was given - if custom_wordlist.present? - ::File.open(custom_wordlist, "rb") do |fd| - fd.each_line do |line| - expanded_words(line) do |word| + Metasploit::Credential::Public.all.each do |public| + yield public.username + end + + Metasploit::Credential::Realm.all.each do |realm| + yield realm.value + end + end + + # This method reads the file provided as custom_wordlist and yields + # the expanded form of each word in the list. + # + # @yieldparam word [String] the expanded word + # @return [void] + def each_custom_word + ::File.open(custom_wordlist, "rb") do |fd| + fd.each_line do |line| + expanded_words(line) do |word| + yield word + end + end + end + end + + # This method searches the notes in the current workspace + # for DB instance names, database names, table names, and + # column names gathered from live database servers. It yields + # each one that it finds. + # + # @yieldparam word [String] the expanded word + # @return [void] + def each_database_word + # Yield database, table and column names from any looted database schemas + myworkspace.notes.where('ntype like ?', '%.schema%').each do |note| + expanded_words(note.data['DBName']) do |word| + yield word + end + + note.data['Tables'].each do |table| + expanded_words(table['TableName']) do |word| + yield word + end + + table['Columns'].each do |column| + expanded_words(column['ColumnName']) do |word| yield word end end end end + # Yield any capture MSSQL Instance names + myworkspace.notes.find(:all, :conditions => ['ntype=?', 'mssql.instancename']).each do |note| + expanded_words(note.data['InstanceName']) do |word| + yield word + end + end + end + # This method yields expanded words taken from the default john + # wordlist that we ship in the data directory. + # + # @yieldparam word [String] the expanded word + # @return [void] + def each_default_word + ::File.open(default_wordlist_path, "rb") do |fd| + fd.each_line do |line| + expanded_words(line) do |word| + yield word + end + end + end + end + # This method yields the expanded words out of all the hostnames + # found in the current workspace. + # + # @yieldparam word [String] the expanded word + # @return [void] + def each_hostname_word + myworkspace.hosts.all.each do |host| + unless host.name.nil? + expanded_words(host.name) do |word| + yield nil + end + end + end + end + + # This method reads the common_roots.txt wordlist + # expands any words in the list and yields them. + # + # @yieldparam word [String] the expanded word + # @return [void] + def each_root_word + ::File.open(common_root_words_path, "rb") do |fd| + fd.each_line do |line| + expanded_words(line) do |word| + yield word + end + end + end + end + + # This method checks all the attributes set on the object and calls + # the appropriate enumerators for each option and yields the results back + # up the call-chain. + # + # @yieldparam word [String] the expanded word + # @return [void] + def each_word + # Make sure are attributes are all valid first! + valid! + + # Yield the expanded form of each line of the custom wordlist if one was given + if custom_wordlist.present? + each_custom_word do |word| + yield word + end + end + + # Yield each word from the common root words list if it was selected + if use_common_root + each_root_word do |word| + yield word + end + end + + # If the user has selected use_creds we yield each password, username, and realm name + # that currently exists in the database. + if use_creds + each_cred_word do |word| + yield word + end + end + + if use_db_info + each_database_word do |word| + yield word + end + end + + if use_default_wordlist + each_default_word do |word| + yield word + end + end + + if use_hostnames + each_hostname_word do |word| + yield word + end + end end @@ -121,6 +267,22 @@ module Metasploit nil end + private + + # This method returns the path to the common_roots.txt wordlist + # + # @return [String] the file path to the common_roots.txt file + def common_root_words_path + ::File.join(Msf::Config.data_directory, 'john', 'wordlists', 'common_roots.txt') + end + + # This method returns the path to the passwords.lst wordlist + # + # @return [String] the file path to the passwords.lst file + def default_wordlist_path + ::File.join(Msf::Config.data_directory, 'john', 'wordlists', 'password.lst') + end + end end diff --git a/spec/file_fixtures/fake_common_roots.txt b/spec/file_fixtures/fake_common_roots.txt new file mode 100644 index 0000000000..9316db735d --- /dev/null +++ b/spec/file_fixtures/fake_common_roots.txt @@ -0,0 +1,3 @@ +password +root +toor \ No newline at end of file diff --git a/spec/file_fixtures/fake_default_wordlist.txt b/spec/file_fixtures/fake_default_wordlist.txt new file mode 100644 index 0000000000..0e27467f4b --- /dev/null +++ b/spec/file_fixtures/fake_default_wordlist.txt @@ -0,0 +1,3 @@ +changeme +summer123 +admin \ No newline at end of file diff --git a/spec/lib/metasploit/framework/jtr/wordlist_spec.rb b/spec/lib/metasploit/framework/jtr/wordlist_spec.rb index 740d4f4b26..e1e8fd33bb 100644 --- a/spec/lib/metasploit/framework/jtr/wordlist_spec.rb +++ b/spec/lib/metasploit/framework/jtr/wordlist_spec.rb @@ -7,6 +7,8 @@ describe Metasploit::Framework::JtR::Wordlist do let(:custom_wordlist) { File.expand_path('string_list.txt',FILE_FIXTURES_PATH) } let(:expansion_word) { 'Foo bar_baz-bat.bam\\foo//bar' } + let(:common_root_path) { File.expand_path('fake_common_roots.txt',FILE_FIXTURES_PATH) } + let(:default_wordlist_path) { File.expand_path('fake_default_wordlist.txt',FILE_FIXTURES_PATH) } it { should respond_to :appenders } it { should respond_to :custom_wordlist } @@ -70,17 +72,29 @@ describe Metasploit::Framework::JtR::Wordlist do end end - describe '#each_word' do - before(:each) do - expect(wordlist).to receive(:valid!) + describe '#each_custom_word' do + + it 'yields each word in that wordlist' do + wordlist.custom_wordlist = custom_wordlist + expect{ |b| wordlist.each_custom_word(&b) }.to yield_successive_args('foo', 'bar','baz') end - context 'when given a custom wordlist' do - it 'yields each word in that wordlist' do - wordlist.custom_wordlist = custom_wordlist - expect{ |b| wordlist.each_word(&b) }.to yield_successive_args('foo', 'bar','baz') - end + end + + describe '#each_root_word' do + it 'yields each word in the common_roots.txt list' do + expect(wordlist).to receive(:common_root_words_path).and_return common_root_path + expect { |b| wordlist.each_root_word(&b) }.to yield_successive_args('password', 'root', 'toor') + end + end + + describe '#each_default_word' do + it 'yields each word in the passwords.lst list' do + expect(wordlist).to receive(:default_wordlist_path).and_return default_wordlist_path + expect { |b| wordlist.each_default_word(&b) }.to yield_successive_args('changeme', 'summer123', 'admin') + end end + end \ No newline at end of file