Skip to content
Permalink
f92a4cfbce
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time

:title: SQL Injection

Introduction

This time we look at another common vulnerability in web pages. SQL Injection is where an attacker inserts data inside an database query in an application. This can allow the attacker to modify the query and either read, modify or insert data into the database.

Principles behind SQL injection

To perform injection we need a couple of things in place. We need:

  • Direct control over the input sent to the server (ie though GET/POST) requests
  • The Developer to have broken the Rule #1 and trusted user input

Injection occurs when we can modify the SQL query string sent to the server by adding (injecting) code that the developers were not intending us to run.

An example Query

If we think about a SQL query that can be used to check login credentials we could have something like:

SELECT * FROM user WHERE username="<USER INPUT>" AND password="<USER INPUT>"

The parts between the quotation marks are "Strings", these represent textual data in a program.

Using Comments to remove part of the Query.

Let's try to break the query.

Let's consider what happened if we supplied:

username: Evil"Hacker password: Foobar

The query then becomes :

SELECT * FROM user WHERE username="Evil"Hacker" and password="Foobar"

If you look at where the quotation marks are, you can see that we end the username after "Evil".

DG TODO: I Think a Diagram will help here

This ends up breaking the query that is sent to the server, as we have an extra Quotation mark. We can either faff around trying to add more terms to the query to make everything match up, or just get the server to ignore the part after "Evil".

We can make use of comments to do this. In SQL anything after a hash # is treated as a comment and ignored.

Therefore if we submitted

username: Evil"#Hacker password: Foobar

The input would become

SELECT * FROM user WHERE username="Evil"#Hacker" AND password="Foobar"

Which with the part after the hash ignored then gives us the query of

SELECT * FROM user WHERE username="Evil"

So we have successfully modified the first query to return values based on a Given username.

NOTE:

A Lot of SQLi works around this, we have to try to work out how the strings in the query sent to the server are processed, insert our code, then makes sure we clean up after ourselves, by closing any strings and commenting out the rest.

Getting More than one result:

We can also get the database to dump all of its results. This relies on the way a database deals with Logic. When a query is made, the database looks at each row, and compares it to the query. If the comparison is True then the row is returned.

To Illustrate this consider the following table

Username Password
Dan Swordfish
Evil Foobar
Hacker Password

Let's go back to our original search:

SELECT * FROM user WHERE username="<USER INPUT>" AND password="<USER INPUT>"

So with the input:

  • username: Evil
  • password: Foobar

We get the Query:

SELECT * FROM user WHERE username="Evil" AND password="Foobar"

Which gives the following results in the table:

Username Password Match
Dan Swordfish False
Evil Foobar True
Hacker Password False

Similarly, if we used the SQL injection using Comments from above we end up with with the same set of matches

SELECT * FROM user WHERE username="Evil"#
Username Password Match
Dan Swordfish False
Evil Foobar True
Hacker Password False

Logical Comparisons

Now the trick here is to consider how SQL processes any logical statements in the query.

  • x AND y: Return all rows where BOTH x AND y are true
  • x OR y: Return all rows where EITHER x OR y are true

So if we had the input:

SELECT * FROM user WHERE username="Evil" OR password="Swordfish"
Username Password Match
Dan Swordfish True (On Swordfish)
Evil Foobar True (On Evil)
Hacker Password False

The 1=1 Trick

So now we have almost all the pieces of our puzzle in place. If we can make a query containing "OR something that is true", we could match every row in the table.

For this we can take advantage how SQL deals with maths. If we include 1=1 then this will always come out as true (as unless something is really broken 1 is always equal to 1).

Therefore we want to try to make our query be something along the lines of:

SELECT * FROM user WHERE username="Evil" OR 1=1

Again if we think about the input (and the way strings terminate) we will need:

username: Evil" OR 1=1# password: whatever

This will then close off the string for the username, and add the OR statement afterwards.

NOTE: I don't really care what the password is, as the part after the comment gets ignored.

Our query then becomes

SELECT * FROM user WHERE username="Evil" OR 1=1#

DG: Again an Image here may help

Which matches every record in the table.

Summary

In this step we have covered the basics of SQL injection, and looked at how we can modify inputs to forms to change the way an application behaves.

SQL Injection is depressingly common, for an attack that has a well documented defence method. It has been used in Large scale "Hacks" (Such as TalkTalk) to gather user details.

In the lab session we will talk about SQLi in more detail, and demonstrate both bypassing a login page, and getting the database to display the full contents of a table.