Skip to content

MySQL FILE Privilege Detection

3 min read Created Mar 26, 2026 Last updated Mar 26, 2026

The FILE privilege in MySQL allows a user to read files from the server filesystem using LOAD_FILE() and write files using SELECT ... INTO OUTFILE or SELECT ... INTO DUMPFILE. On a web server where MySQL runs with sufficient OS permissions, FILE privilege enables reading sensitive files like /etc/passwd and writing webshells to the web root. It is one of the most impactful misconfigurations in a MySQL deployment and is frequently present on over-provisioned application database accounts.

Check Current User Grants

The fastest check once connected is to inspect the grants for the current user:

┌──(kali㉿kali)-[~]
└─$ mysql -h $TARGET_IP -P ${PORT:-3306} -u $USER -p$PASSWORD -e "SHOW GRANTS FOR CURRENT_USER();"
+---------------------------------------------------------------------------+
| Grants for app@%                                                          |
+---------------------------------------------------------------------------+
| GRANT SELECT, INSERT, UPDATE, DELETE, FILE ON *.* TO 'app'@'%'           |
+---------------------------------------------------------------------------+

FILE appearing in the grant list confirms the privilege is held. Even on a non-root account, FILE privilege enables reading any file the MySQL process user can access and writing to any directory the process user can write to.

Query the Privilege Directly

Check the mysql.user table for the FILE column on the current account:

┌──(kali㉿kali)-[~]
└─$ mysql -h $TARGET_IP -P ${PORT:-3306} -u $USER -p$PASSWORD -e "SELECT user, host, File_priv FROM mysql.user WHERE user = CURRENT_USER();"
+------+------+-----------+
| user | host | File_priv |
+------+------+-----------+
| app  | %    | Y         |
+------+------+-----------+

File_priv = Y confirms FILE privilege. If the mysql.user table is not accessible with the current account, use the SHOW GRANTS approach instead.

Confirm MySQL FILE Privilege Detection with a Safe Read Test

Verify FILE privilege is actually functional by reading a file that is always readable:

┌──(kali㉿kali)-[~]
└─$ mysql -h $TARGET_IP -P ${PORT:-3306} -u $USER -p$PASSWORD -e "SELECT LOAD_FILE('/etc/hostname');"
+-------------------------+
| LOAD_FILE('/etc/hostname') |
+-------------------------+
| webserver01             |
+-------------------------+

A non-null result confirms LOAD_FILE is working. A NULL result despite the privilege being present usually means the secure_file_priv variable is restricting the read path. Check it:

┌──(kali㉿kali)-[~]
└─$ mysql -h $TARGET_IP -P ${PORT:-3306} -u $USER -p$PASSWORD -e "SHOW VARIABLES LIKE 'secure_file_priv';"
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| secure_file_priv |       |
+------------------+-------+

The three possible secure_file_priv states:

  • Empty string: no path restriction, LOAD_FILE and INTO OUTFILE reach any path the MySQL process user can access
  • Specific directory path: file operations restricted to that directory only
  • NULL: file operations disabled entirely regardless of FILE privilege

Check the MySQL Process User on the Host

The FILE privilege operates with the permissions of the OS user running MySQL. On Linux this is typically mysql but on misconfigured systems it may be root. If you have shell access confirm:

┌──(kali㉿kali)-[~]
└─$ ps aux | grep mysqld
mysql    1482  0.5  4.2 1234567 87654 ?  Sl   09:12   0:42 /usr/sbin/mysqld

MySQL running as root combined with FILE privilege and no secure_file_priv restriction means the account can read any file on the system and write to any directory. This is the highest-severity FILE privilege configuration and enables direct webshell deployment to the web root. Exploitation is covered in the FILE read and INTO OUTFILE pages.

References