bWAPP – SQL Injection
In this write up I’ll be using SQL Injection for the purposes of information disclosure, enumerating the remote OS and spawning a reverse shell (with a little help from LFI, thanks to the permissions set on the box).
Let’s start with the webpage – sqli_1.php
The first step is to check if the page is actually vulnerable to SQLi (it definitely is…) by searching for ‘
If an error message pops up, the page is most likely vulnerable, this is because the apostrophe cuts off the query before it can be completed.
By placing the apostrophe at the start of the statement I can trick the query into thinking that there are additional fields to search, and using — at the end of the statement tells the query that everything following that is a comment, which allows me to control when the statement ends.
This particular table holds information from movies, which I’m not interested in, I want some slightly more sensitive information such as usernames and passwords. I can see that there are 5 columns, so using a union statement to find information from other tables will take at least 5 arguments.
The error message here informs me that there isn’t 5 columns, this is a case of trial an error by adding new columns until there’s a match.
I quickly found that there are 7 columns in the table with the most columns. Only 5 columns show here because the table that I am bringing this information to only has 5 columns, 4 of which it seems that I can display information on.
With a little trial and error I find the database name (bWAPP) by replacing the second column with database()
The next step is to find the table names within the database. Replacing database() with table_name will display the table names instead of the database name, I’ll also be selecting table_name from the schema for tables within the database.
This provides the names for all of the tables within bWAPP.
Almost there, now I need column names within the tables, users looks interesting so I modified my query to search for the column schema for the users table. This shows every column for that table.
Now I have the information I need I can create a query to find the login and password of all the accounts on the website by replacing the 1’s with the column name I want to view! The passwords are hashed but any weak ones will easily be cracked (that’s for another time though!)
Ok, I’ve pretty much owned the users on the site, maybe I can get into the server hosting the site now?
I can read some sensitive files like passwd by using the load_file function.
Ok great, I can read some sensitive information, now I want a shell, I tried writing to the web root directory but unfortunately I didn’t have permission. Instead I decided to go for the /tmp directory as this normally has fairly lax permissions. I used the INTO OUTFILE functions to achieve writing a simple php command into a new file called ncshell.php.
Once I set up a listener using nc –lvp 4444 I tried to trigger the reverse shell by using the load_file() function again but with no success. I am confident however that my shell has been written to the server, and I’m forced to try a different route to triggering it, which ended up being LFI.
Whilst this isn’t quite the result I was hoping for I think it proves how dangerous SQL injection can be, I successfully pulled sensitive information from the server and even managed to write files to it, which eventually led to a shell (albeit not the route I wanted), had the permission been a little more lax I would have liked to create a new page where I could issue OS commands.