How to Attack and Defend Your Website (2015)
Chapter 2. Exploitation
We take a closer look at the Burp Suite site map and Spider. This chapter then covers bypassing client-side controls, cross-site scripting (XSS), and how to use Stored XSS to deface a website.
Burp Suite site map
bypassing client-side controls
Let us look at the Burp Suite site map and Spider.
Within Burp Suite we have selected the “Target” tab and then the “Sitemap” (see Image 27).
What you see is a list of the targets that Burp Suite will automatically pick up as you browse around the web. Burp Suite automatically maps out websites and presents them in an intuitive way for you – how nice! The first thing you see in our example is just the localhost since we have only visited Damn Vulnerable Web App (DVWA) so far, which is on our local machine (see the box in Image 28).
If we double click on the localhost target, you can see the webroot that shows us the request that we generated when we navigated to the DVWA in the browser.
We can see the HTTP request that was sent when we navigated to DVWA in our web browser. We have tabs for viewing the raw HTTP requests and the responses, as well as the headers (see box in Image 29).
In this image, you can see how Burp Suite maps out the application for us, showing us that there are folders called about.php, index.php, instructions.php, login.php, and so forth. (see the box in Image 30).
In the “vulnerabilities” folder, you can see all the requests we made to the various pages of the DVWA application in our earlier exercises.
When you right-click on any of these folders or on the root, you can select to “Spider This Host” that helps to discover additional content or “Spider This Branch,” which will constrain the spider to specific branches, or subfolders.
If we select to “Spider the Host” at the root level, we notice that it automatically detects form submissions and lets us provide information for the spider to input into the form, for example, a username and password (see Image 33). The Burp Suite Spider tool is quite useful.
2.1. Bypassing client side controls
The first exploit that we will examine is being able to bypass client-side controls, which as we mentioned earlier are constraints on the information that your browser is allowed to pass to the application. Developers have a misconceived notion that they control the data that comes from your browser. As a user you are always in control of everything that comes from your machine: you just need to learn how.
2.1.1. Steps for Bypassing Controls
1. Look for places where client-side controls are being used.
2. Look for disabled check boxes, disabled radio buttons, check parameters in POST and GET requests that look unsafe.
3. Use the Burp Suite intercepting proxy to capture requests and analyze GET and POST request parameters. Use context clues to understand what these parameters are actually for. Developers typically try to develop things such that when they debug them, they can look at the code and understand what it is doing. Therefore, developers typically do not create GET and POST parameters that are just a random series of strings and numbers, because they will not know what these things mean when they go to debug the application. They are usually given some kind of a logical name. So we can try to understand what that name is, what the parameter is doing for the web application and what kind of data it is passing.
4. Look for parameters that appear to be unsafe, tweak them, and see what happens. If, for example, there is a debug parameter being passed through a POST request and it says “debug = off,” see what happens if you change it to “debug = on.” The application might give you additional data on what it is doing and provide you with additional information that can be used to plan an attack.
5. Rinse and repeat. Do this for every GET and POST parameter in the web application to allow you to see what each link and each page is doing.
2.2. Bypassing client-side controls – example
Visit http://course.hyperiongray.com to access this exercise and click on “client-example” (see Image 34).
Like always, the first thing to do is to behave like a normal user to see how a web application functions normally, so once you have clicked the “client-example” link, just pretend you are a normal user and enter your zip code. If we enter 22222 as our zip code, we notice that the application prints “thank you, your zip code has been entered as: 22222.”
We notice that we are unable to enter more than five characters because zip codes in the United States are limited by five characters. Now let us see if we can hack this. The first check is to view the source code of the page (in Firefox, right-click and select “View Page Source”).
The page source code tells us that it is limiting the maximum length attribute in the input to five characters. My browser, not the web server, is therefore preventing me from entering more than five characters, which means there is an opportunity to bypass client-side controls.
Let us see what the request looks like through Burp Suite by entering my zip code as 66666.
We notice that the application is sending a POST request to “client-example/formhandler.php” (see the top box in Image 36).
At the bottom, we can see the actual POST data, the data that has been passed to the web application. As mentioned before, GET requests are actually visible in the URL, however, POST requests are not (see the bottom box in Image 36). The zip-code data is being passed through the “zip” POST parameter so let us forward it along and see what the web application does under normal conditions.
Since we entered “66666” in the zip parameter, it prints the same on the page (see Image 37).
Now that we have discovered the raw HTTP request, we have total freedom – we have “broken out” of the browser and what the application developer has permitted us to do. Try passing a string longer than five characters and see what happens (see the box inImage 38).
There are additional things that you could do with this, just do not forget to percentage encode your text before inserting it into the HTTP request.
2.2.1. Short Exercise: Bypassing Client-Side Control
Goal: Buy a movie for $0.01
1. Go to http://course.hyperiongray.com
2. Click on the “client” folder. Explore the application, understand it, and see how it is passing data. Identify if anything looks suspicious or hackable.
As you probably figured out, this application is a movie-buying application. Your goal is to pick a movie from the list and try to buy it for one cent. Do not worry, this is a dummy site that we created for this book, you will not actually be purchasing anything.
2.3. Bypassing client-side controls – exercise solution
As always, first behave like a normal user to see how things work. For this example, I selected to buy “Big Momma’s House” for $10.99.
Now take a look using Burp Suite – turn “Intercept On,” click “buy” and take a look at the raw requests.
This is a very similar to the last example, we can see that it is POSTing to “/client/formhandler.php” (see the box in Image 41). We can also see that the host is “course/hyperiongray.com,” which is useful information.
We see that it is passing the price of the movie as $10.99 within a POST parameter. This is a huge vulnerability because a hacker can potentially manipulate the price.
Edit the HTTP request and enter $0.01 as the price. Forward the request on, and you will see that you have complete control over the price just by being able to edit the raw HTTP request.
2.4. SQL injection
SQL injection is a very common vulnerability.
As we learned earlier, SQL is an abbreviation for “Structured Query Language.” Typically a server-side language (like SQL) will build the query and execute it on the server and database to return useful data.
Here is a quick example of SQL working:
In a terminal, we have opened a MySQL shell and connected to the DVWA database, which is a MySQL database, one of the most common types of SQL databases used on the web. The MySQL shell allows me to navigate the database easily.
I typed the “Show Tables” command that lists the tables stored with the DVWA database.
Next, I am telling the database to give me all the data from the Users table with the command
mysql>SELECT * FROM users
(see the box in Image 44).
SQL stores data in columns and rows. You can see a series of columns, that is, User ID, First Name, Last Name, User, Password, Avatar, and so forth with unique entries listed in the rows (see box in Image 45).
Notice that the password is not the actual password but a hash of the password. Hashing is a one-way algorithm that converts the password to an encoded value. This is used so that if a hacker steals the database they would not know the users’ passwords, because (in theory) you cannot un-hash a hashed password.
2.5. SQL injection
SQL injection is all about syntax. As we have discovered, if we take the following SQL normal query,
SELECT first_name, last_name FROM users WHERE user_id= ‘1’
…this would return rows stored in the Users table for the user where user_id is 1.
(see the box in Image 47)
Exactly the same is applicable to user_id=2. In our example, user_id=2 would be “Gordon” and “Brown” – see the box in Image 47.
PHP (server-side language) passes the SQL commands as strings. PHP stores the query as a piece of text that the application can use when it is passed to the backend database – but there is a disconnect here. The server-side language has no context as to what the user is asking for. It is just passing a “dumb” piece of text. This is an important concept to understand.
Let us say the user is given the ability to enter whatever user_id that they want in the above query, and they decide to enter “1” or “1”=“1” – what is that going to do to the query? For example:
SELECT * FROM users WHERE user_id= ’1’ OR ’1’=’1’
The above syntax tells the application to get all of the rows from the database where the user_id is 1 or where 1 = 1. Since 1 always equals 1, this is going to return the First_Name and Last_Name records of everybody in the users table. Essentially, what we have done is messed with the logic of the query, simply by entering some unusual syntax.
You might be asking yourself, how do I actually open a SQL shell? That is an important question!
The real answer is that you do not. You will not need to work in a SQL shell. Unless a web application is really bad, you will not have access to the backend database nor an SQL shell. You will not be able to see the database or navigate around it as we have been doing in the above examples.
All you are going to see is the web application, and from here you need to figure out how to inject and form your syntax in a way that makes the application do something unexpected.
Let us look at an example of that right now.
Back in the DVWA application on the SQL Injection page, it asks me for a User ID. The first step as always is to treat the application like a normal user (have we repeated this enough yet?).
As you can see in Image 49, if I enter the user ID of 1 and you see that it prints “First name: admin” and “Surname: admin.”
If we put a user ID of 2, then we see that the database spits out “Gordon” and “Brown”. This should all look somewhat familiar as we have already navigated the backend database and taken a look at it. Under normal conditions you would not have had that luxury.
Let us see what this looks like in Burp Suite. Turn “Intercept On” and enter the User ID as 1 again.
In Burp Suite, we see that it is conducting a GET request to “/vulnerabilities/sqli” and you see that the “ID” and “Submit” are passed over in parameters (see the box in Image 51). Another thing to notice is that security is set to “high.”
Before we continue this exercise, we want to turn the security to “low” in DVWA. Once we are elite hackers, we can turn it up to “high.”
Going back to the SQL injection example, we need to identify if there is a SQL injection possibility or not, so let us throw unusual SQL syntax at it and see what happens.
Typically an apostrophe is a good way to test for SQL injection. When we were in a SQL shell we used apostrophes to surround the strings we want to give to the application. Let us see what happens if we enter just an apostrophe.
We see a very common error: you have an error in your SQL syntax (see Image 54). Now 99.9% of the time I know that this means the application is vulnerable to SQL injection. We will talk a little bit more about finding vulnerabilities later, but all you need to know for now is that I put an apostrophe, it broke the SQL syntax, which means that I can edit that syntax.
Armed with the knowledge that the SQL syntax can be broken, we can now predict user_id’s and request other such data.
So, let us try this:
SELECT firstname,surname FROM users WHERE id=’1’
The above is very typical since the table users is often called “users.” So, let us mess with the logic while not actually breaking the syntax. To achieve this, let us see what happens if we input an apostrophe that does not always break the syntax but can produce interesting results. We know that the query is going to be passed with an opening and closing apostrophe. So, let us alter the syntax assuming that these apostrophes will be added by the web application, so it looks like this:
SELECT firstname,surname FROM users WHERE id=1’ OR ‘1’=’1
In the example, we can see some unexpected results. What this should do is print out every first name and last name (see the box in Image 57).
It does in fact give me every first name and last name, and the reason it does that is because of the “1=1” statement. We have now established arbitrary access to the backend database.
This next part is going to get a little bit complicated in that you need to know SQL syntax to perform the next hack, which is to steal the database.
Having used SQL for many years, I know that the UNION statement allows me to concatenate data together. I know that instead of entering “1,” I can do the following:
SELECT firstname,surname FROM users WHERE id=’1’ UNION SELECT user,password FROM users’
The above syntax will break something because there is a rogue apostrophe at the end of the line (the web application will automatically put it there), but the comment character (pound sign) instructs SQL to ignore everything after the #.
This syntax instructs SQL to give me the users and passwords from the users table and combine it with the data that was previously given to me. Entering the above string in DVWA gives me the following:
As we can see we have broken the web application. The first record is “admin admin,” which is expected, because we entered a command requesting the first record, id=“1.”
I also requested other users and passwords from the users table that generated the hashed passwords within the surname field.
We mentioned that hashed passwords cannot, in theory, be un-hashed, but people have generated hashes for many common passwords and posted them online, so you can often simply Google hashed passwords to obtain the un-hashed version.
2.6. Short Exercise: Pwning with SQLMap
The goal of this exercise is to steal a username/password combo (besides admin/password) and login to the DVWA as another user.
We have looked at the manual (and complicated) way of SQL injection. The good news is that there are automatic database takeover tools such as SQLMap, which automates every step in the process of a SQL injection.
Let us see it in action.
2.6.1. Hack Steps
1. Navigate in your browser to the site and page that you want to inject (with the Burp Suite Proxy enabled).
2. Attempt some normal queries against that page (e.g., type something into the form and click submit).
3. Find that submission page in the Burp Suite sitemap and left click on it.
4. On the right-hand side, find your raw request.
5. Right-click on the request and choose “Copy To File.”
6. Save it in your SQLmap directory under an easy-to-remember name.
7. Go back to your terminal and cd to your SQLmap root by typing:
8. Check out the available SQLmap options by typing:
python sqlmap.py -hh
9. We will be using the -r option which allows us to specify our Burp Suite file to determine the injection point that we would like to try. First, we will enumerate the database tables and columns by typing:
python sqlmap.py -r file_from_burp --tables
10. Look through the output and choose an interesting looking table that will have user information.
11. Steal that table by typing:
python sqlmap.py -r file_from_burp -T table_to_target --dump
12. SQLMap will ask if you want to attempt password cracking automatically – choose “yes”!
2.6.2. Solution: Pwning with SQLMap
From within my tools directory in my terminal, I want to change directories to my SQLMap directory. To access this I type:
python sqlmap.py -hh
As we can see there are dozens of SQLMap options, but we are just going to be using a few of them.
We are going to be using the -r option that loads an HTTP request and saves time from, for example, specifying specific URLs, parameters, and so forth to test for. It is going to parse the HTTP request and use that to determine the target.
Go back to DVWA and click around. Go into Burp Suite to make sure that “Intercept” is off but that traffic is still running through it.
Let us start by using the SQL Injection page of the DVWA normally for a bit, and then take a look at Burp Suite. To see the requests navigate to /vulnerabilities/sqli/ and check the submissions (see the box in Image 64).
Click on a request and it will populate over on the right side. From here, right-click on it and select “Copy to File.” (see the box in Image 65)
Save it to the same directory that you have SQLMap in to make it easier. For this exercise, I will save mine as sqli-exercise.txt.
We can make sure the file is saved by executing an “ls” command in the my SQLMap directory in the terminal. You should see your file listed there.
We are going to use this .txt file to feed SQLMap. We will use this code:
python sqlmap.py -r sqli-exercise.txt --tables
We are using the --tables options to list all the tables so that we can see what is available in all of our databases.
We see here the database information schema that lists all the tables, but the one that we are interested in is the database for the DVWA – and we see that there are two tables: “guestbook” and “users.”
Moving on and escalating the hack, we use that same HTTP request with additions, so:
python sqlmap.py -r sqli-exercise.txt --tables -T users -D dvwa --dump
The -T tells the tool which table we want to steal, in this case the table “users.” We can also specify the database, in this case DVWA, and the --dump simply tells it to dump that database.
We are prompted with a question if we would like to store hashes to temporary file for eventual further processing with other tools – the answer is yes! The next question is: Do you want to crack them via dictionary-based attack – also yes!
In summary, SQLmap has taken the table “users” from the database DVWA and listed all of the entries. The tool has taken this data and formatted it nicely and it has also cracked the passwords!
2.7. Cross-site scripting (XSS)
Cross-site scripting is another very common vulnerability.
Let us look at the XSS Reflected page in DVWA where we are asked for our name.
I am going to put “Alex” and the output prints my name. Let us see the request in Burp Suite.
We see that the application performed a GET request to “/vulnerabilities/xss_r?name”
This time let us enter my name with a bunch of x’s at the end and forward this.
We continue seeing that whatever is placed in the input box is being passed in to the web application through a GET parameter, in fact you can actually see the GET parameter in the URL that is being echoed back to the page.
In fact, we see that the browser executed the code, which means it executes everything in between the script tags. This means that we can insert anything we want, which could potentially be dangerous. However, are we not just exploiting ourselves by getting our own browser to execute code? The answer is yes, that is exactly what we are doing – but this same attack can be used on other people.
2.8. Stored cross-site scripting XSS
The attack can be crafted in such a way that any user that visits a hacked page can have sensitive information stolen from them and sent back to an attacker. Having a strong password in this case would make no difference.
This type of vulnerability can also be used to deface a web page, which will be our next exercise. A quick disclaimer: defacing a webpage that you do not own is illegal.
2.9. Short exercise: using stored XSS to deface a website
The goal of this exercise is to deface the DVWA “XSS Stored” page with a defacement message.
*Warning*: This exercise is the most difficult one of this book!
1. Go to “XSS Stored” in the DVWA.
2. Check out how the functionality works under normal conditions (without exploiting anything).
Hint: The “Name” and “Message” fields limit the number of characters that you can enter into the text boxes…. I wonder if there is a way around that?
Hint: You will need to use the Intercepting Proxy and the Decoder for this one.
document.body.innerHTML=“enter text here”;
Make sure you get the lower case and caps straight there. Make sure when you put your text there that you include those apostrophes and the semi-colon in the string!
2.9.1. Solution – Using Stored XSS
Open up the DVWA and navigate to the XSS Stored page
As usual, we treat the application as an average user to understand how it all works, so let us go ahead and sign the guestbook.
The application is taking my name and the message that I entered and just putting that data into a box on the page. I know that the signing of the guest book is persistent because even if I refresh the page, the data stays there. Let us now turn Burp Suite “Intercept On” and see what is going on under the hood.
Sign the guestbook again, intercept that request, and we can see that the application is sending a POST request to “vulnerabilities/xss_s.”
A couple of other important things to note:
First, you can see that the name and message are being passed in a parameter called “txtName” “mtxMessage,” respectively (see the box in Image 93). Let us now forward that along to understand the flow of the page.
We notice that my name and message are stored in a database and then echoed back to the page.
Back in Burp Suite, we take the URL encoded information, insert it to the mtxMessage parameter, and forward that along. Let us see what happens to the application.
As you can see, our XSS Stored page has been replaced by our message! Success!