In my previous post, I demonstrated how it was possible to execute custom C# code via the creation of a custom CLR stored procedure on a target SQL Server, entirely in memory. In this post I will provide and discuss a working command execution PowerShell script for this technique and possible ways to mitigate it.
Recently I was given the task of performing command execution on a compromised MSSQL server with the following restrictions:
- No use of the xp_cmdshell stored procedure.
- No writing anything to disk.
These restrictions matched those of a recent pentest that a member of my team, Lee Christensen (@tifkin_), was involved in. Through my research I found that there were basically two means to achieve this objective. The first is through the use of SQL Agent jobs, as documented here. The other option was to create a custom stored procedure using the Common Language Runtime (CLR), which would allow for the execution of code from any of the supported programming languages, such as C#. While both methods require the attacker to have the sysadmin role, each option also has their own unique restrictions. The SQL Agent method requires that the SQL Agent service be active (which it is not by default), and that the SQL Agent service account has the necessary privileges required for the command to execute successfully. The CLR stored procedure method requires the ability to create custom stored procedures, the ability to enable the use of CLR on the SQL Server, and requires that the SQL Server service account has the necessary permissions for the command/code to be executed. I also initially believed that that the stored procedure had to be available externally as a DLL file, and then loaded into the SQL Server for execution, thus failing the second restriction. This turned out not to be the case.