Edit: I have confirmed that this is still valid for the all versions of SQL Server 2012 and above. As of this last update (Oct 2019), this works even on the yet-to-be-released SQL Server 2019. The binary paths may change across versions, but the idea is the same.
If you recall one of my previous blog posts, titled Think Your Windows Administrators Don’t Have Access to SQL Server 2008 by Default? Think Again I exploited the fact that NT AUTHORITY\SYSTEM was granted membership to the sysadmin server role by setup in SQL Server 2008 R2 and below to gain access to a SQL instance to which I had no access, since as Administrator on the box I could launch a cmd session as NT AUTHORITY\SYSTEM with Sysinternals’ psexec utility.
My friend and SQL Server MVP Jorge Segarra [blog|twitter] correctly pointed out shortly after that NT AUTHORITY\SYSTEM is not a member of the sysadmin server role in SQL Server 2012, codename Denali. And as of Release Candidate 0 for this version, this holds true.
What also holds true as of RC0 is that the Service SID for a number of services (at least three, the SQL Engine itself, SQL VSS Writer and Winmgmt) are members of the sysadmin role. And so in this post I’d like to demonstrate that it is possible to exploit one of these services’ level of access to hop onto a 2012 (or 2014) instance as sysadmin.
The target: a named SQL instance called “DENALI_RC0” on one of my desktop PCs. Having dropped my login on SQL, when I try to logon to the instance I get the usual message:
I picked a service to become “the victim”. The SQL VSS Writer service seemed to be a good candidate: innocuous enough. If I stop it and restart it, no big deal.
I launched regedit and browsed to HKLM\SYSTEM\CurrentControlSet\services\SQLWriter – this is what I saw:
Now being an Administrator of this PC as I am, I went ahead and renamed sqlwriter.exe to sqlwriter.exe.orig, and put a copy of SQLCMD.EXE on C:\Program Files\Microsoft SQL Server\90\Shared.
Then I renamed SQLCMD.EXE to sqlwriter.exe.
Obviously kicking off the SQL VSS Writer service was not going to do anything – just error out:
So I replaced the ImagePath for sqlwriter on the registry with this:
“C:\Program Files\Microsoft SQL Server\90\Shared\sqlwriter.exe” -S CSHQAFERNANDEZD\DENALI_RC0 -E -Q “CREATE LOGIN [CORP\Argenis.Fernandez] FROM WINDOWS; EXECUTE sp_addsrvrolemember @loginame = ‘CORP\Argenis.Fernandez’, @rolename = ‘sysadmin'”
And now I kick off the sqlwriter service again, expecting it to error out…but with a nice side effect.
Sure enough, launched SSMS 2012 and was able to login. And guess what, my login has sysadmin privileges.
And so I’m sure some of you have already yelled “SECURITY HOLE!!!!” by now – yeah, to a degree…but remember kids, if you’re a local Administrator on the box, you already own the box. Very little applications like SQL Server can do to protect themselves from a “rogue” Admin. Maybe a few adjustments to the security model for Windows’ SCM (Service Control Manager) are needed here, but I’ll let you decide on that.
UPDATE FOR SQL EXPRESS USERS: If you need to leverage this trick on a SQL Server Express install, you can use the “Winmgmt” service – Windows Management Instrumentation, aka WMI service.