After my previous two posts about xp_cmdshell exploits, a friend asked this question:
"Same issue if the SQL service account is a domain admin (rather than Local system)?"
My immediate answer to this is, yes – the Domain Admins group is a member of the local Administrators group on every member machine by default. So it stands to reason they have the keys to the city. What is interesting about this scenario, however, is not just the risk associated with compromising the local machine. It's the risk associated with being able to compromise every other member of the domain – including Domain Controllers.
If this doesn't give you a reason to check your SQL Server's service accounts, nothing will. Consider this scenario, one which I consider to be a near-perfect storm of stupidity:
- The SQL Server service account is configured to use an account that is a member of the Domain Admins group.
- The SQL Proxy account is configured with an account that is a member of Domain Admins – perhaps the same account as the SQL Server service account
- xp_cmdshell is enabled.
You'll recall that xp_cmdshell lets you run pretty much anything under the context of the SQL Server service account (if you are a sysadmin) or the context of the SQL Proxy account (if you're not in the sysadmin role). As you saw in my last couple demos, this seems to be limited to commands that run non-interactively. But that doesn't mean there's any less risk associated with it.
Let's first of all try this as someone who's a member of the Domain Admins group.
xp_cmdshell 'whoami.exe'
Let's see if we can use DSRM to trash an OU in Active Directory.
xp_cmdshell '\\dc1\c$\windows\system32\dsrm.exe -subtree -noprompt -c OU=Marketing,DC=sql,DC=local'
Those of you familiar with Windows Server 2008 R2 will no doubt be pleased that objects created in AD have this option selected by default:
If you're using an ealier revision of Windows for your DCs, or if you have not yet moved up to the appropriate Functional Level, this option won't be available to you. Let's see what happens if you do not have this option enabled:
xp_cmdshell '\\dc1\c$\windows\system32\dsrm.exe -subtree -noprompt -c OU=Marketing,DC=sql,DC=local'
It should not really be a surprise that someone who is a Domain Admin, running TSQL commands on a box that is poorly-configured, can do this. I wonder about a regular user?
Don't forget that for that to happen, we need to create a SQL login associated with that user, the user needs to be granted permission to run xp_cmdshell, and we need to configure the SQL Proxy account. And because we're talking about a very silly administrator, the Proxy account is configured to use an account that is a member of Domain Admins.
use master go EXEC sp_xp_cmdshell_proxy_account 'SQL\administrator','password' grant execute on xp_cmdshell to [sql\gpotest]
Now when the user runs the whoami command, they see this:
Yay! A regular unprivileged account can now run commands under the context of the Domain's administrator! Great news!
And just to prove it…
xp_cmdshell '\\dc1\c$\windows\system32\dsrm.exe -subtree -noprompt -c OU=Marketing,DC=sql,DC=local'
Oh, fuck.
So, your boss is in your ear about how all the people in the Marketing department have lost their user accounts – and all the things they want to access with those accounts. Your boss wants to know who did this! Let's look at the Domain Controller logs:
The event logs are clear. It's not the unprivileged account that deleted the user accounts. It was the Administrator account. Sure, the logs will tell you.. with a bit of hunting.. that the Administrator account was logged onto the SQL box, but by then, it won't really matter. The finger will still be pointing at the person who's supposed to be safeguaring the Administrator account. And that's not Mr Unprivileged. No. It's a naive sysadmin who should've known better than to configure his SQL box to use elevated accounts.
This could've easily been prevented. Even if the SQL Server service account was privileged (which it should not be, but for the purposes of this discussion….), using an unprivileged account for the SQL Proxy account would've prevented it:
xp_cmdshell 'whoami.exe'
xp_cmdshell '\\dc1\c$\windows\system32\dsrm.exe -subtree -noprompt -c OU=Marketing,DC=sql,DC=local'
The regular user account can't access \\dc1\c$\windows\system32. A good thing, too. But what if this person is really determined, and makes a copy of dsrm (and its supporting files) somewhere else?
xp_cmdshell '\\fileshare\openshare\dsrm.exe -subtree -noprompt -c OU=Marketing,DC=sql,DC=local'
In spite of the poorly-configured service account, this particular disaster was averted because the Proxy account is unprivileged.
Windows, SQL Server, and to an extent, the tools that come with them, prevent us from doing overtly stupid things – so long as we follow a few basic rules. If we configure our servers loosely, against best practice, ignoring all conventional advice… then we really do deserve what we get. In the words of the great Forrest Gump, stupid is as stupid does.