MySQL Credential Harvesting from Application Configs
Application configuration files on the web server contain plaintext MySQL credentials used by the application to connect to the database. These credentials are separate from those stored in mysql.user: they are OS-level files readable through shell access or through MySQL's LOAD_FILE function when FILE privilege is present. The recovered credentials often have elevated database privileges compared to what the current MySQL session provides, and frequently reuse passwords across multiple services on the same host.
LOAD_FILE requires the FILE privilege on the MySQL user. The target file must also be readable by the mysql OS user. Without FILE privilege, every LOAD_FILE call returns NULL. Shell access bypasses this restriction entirely. Backup files and staging configs are often overlooked but frequently contain the same credentials as production.
Read Config Files via LOAD_FILE
Target common CMS and framework configuration file locations. Start with the most widely deployed platforms:
LOAD_FILE returns NULL when the file does not exist, when the mysql OS user cannot read it, or when secure_file_priv restricts reads to a specific directory. A NULL result does not confirm the file is absent. Run SHOW VARIABLES LIKE 'secure_file_priv'; to check the restriction. If the variable holds a non-empty path, LOAD_FILE only reads files inside that directory. In that case, switch to shell access to read configs outside the allowed path.
define('DB_NAME', 'wordpress');
define('DB_USER', 'wpuser');
define('DB_PASSWORD', 'Sup3rS3cret!');
define('DB_HOST', 'localhost');
Search for Config Files via Shell Access
If shell access is available on the host, search the filesystem directly for configuration files containing MySQL credentials:
Check paths outside /var/www/ too. Applications deployed in /srv/, /opt/, and /home/ often carry their own config files. The second grep pipes matched filenames through xargs to extract credential lines directly. A config file with an empty password field is still useful: it reveals the database username and database name, which narrows further attacks. Backup copies of config files (such as wp-config.php.bak or config.php.old) are common and may contain old credentials that still work.
/var/www/html/wp-config.php /var/www/html/app/.env /var/www/backup/config.php
Read .env Files
Modern frameworks store database credentials in .env files which are often world-readable and contain all service credentials in one place:
An empty DB_PASSWORD is not a dead end. Some applications connect without a password, and the username alone may allow unauthenticated access. Laravel .env files also contain APP_KEY, queue connection credentials, and cache backend passwords. Redis and Memcached credentials in the same file are common. Test each credential pair separately against its service. The MAIL_PASSWORD and AWS_SECRET_ACCESS_KEY fields in the same file are worth collecting even if MySQL is the primary target.
/var/www/html/.env:DB_CONNECTION=mysql /var/www/html/.env:DB_HOST=127.0.0.1 /var/www/html/.env:DB_DATABASE=production /var/www/html/.env:DB_USERNAME=laraveluser /var/www/html/.env:DB_PASSWORD=LaravelProd2024!
Check MySQL Client Credential Files
Users who connect to MySQL frequently from the command line store credentials in .my.cnf files in their home directories to avoid typing passwords. These files contain plaintext credentials:
Also check /etc/mysql/debian.cnf. On Debian and Ubuntu systems this file contains the debian-sys-maint account, which carries broad MySQL privileges used for system maintenance tasks. The file is normally root-readable only, but misconfigured systems leave it world-readable. If LOAD_FILE returns this file, the credentials inside typically allow full database access. Try the recovered password against the root MySQL account as well, since administrators often reuse passwords between maintenance and root accounts.
[client] user=root password=AdminPass123
Test Recovered Credentials
Test each recovered credential set against MySQL directly and against other services on the host. Run SHOW GRANTS FOR CURRENT_USER(); immediately after authenticating with the recovered credentials. Look for high-value grants:
FILEenables file read and webshell deploymentSUPERorSYSTEM_VARIABLES_ADMINenables server configuration changesALL PRIVILEGESorWITH GRANT OPTIONindicates DBA-level access
Try the same password against SSH, FTP, and any other services running on the host. Application database users are often created with a shared password that administrators reuse across multiple accounts on the same system. A credential that fails on MySQL may still work for SSH or a control panel.
References
-
MySQL: End-user password securityDOCS: MySQL: End-user password security, dev.mysql.com/doc/refman/8.0/en/password-security-user.html (opens in new tab)
.my.cnf credential file format and location reference