Detailed SQL injection, see this is enough

Introduction

First look at a very interesting comic:

I am sure the schools are bad operation and maintenance of the network environment and the means are already experience, this will not do Tucao. Today we chat relevant content SQL injection.

What is SQL injection?

SQL injection is a very common database attacks, SQL injection, one of the world's vulnerability is the most common network vulnerabilities. You may have heard certain things seniors modify their performance by attacking the school database, these seniors are generally used is the SQL injection method.

SQL injection is actually a malicious user to fill in data contained in the form of SQL keywords to make the process database to perform unconventional code. Simply put, the data "pre-empt" made a code to do things.

The source of this problem is that SQL database operation is performed by SQL statements, regardless of the implementation of the code or data items must be written in SQL statements, which led to if we added some SQL statements in a data item keyword (for example, SELECT, DROP, etc.), these keywords are likely to be implemented in the database write or read data.

Say no good, we get to talk to real cases. Let us first establish a student file table using SQLite.

SQL database operations example:

import sqlite3

Connect to the database:

conn = sqlite3.connect('test.db')

Create a new data table:

conn.executescript('''DROP TABLE IF EXISTS students;
       CREATE TABLE students
       (id INTEGER PRIMARY KEY AUTOINCREMENT,
       name TEXT NOT NULL);''')

Insert student information:

students = ['Paul','Tom','Tracy','Lily']


for name in students:
    query = "INSERT INTO students (name) VALUES ('%s')" % (name)
    conn.executescript(query);

View existing student information:

cursor = conn.execute("SELECT id, name from students")
print('IDName')
for row in cursor:
    print('{0}{1}'.format(row[0], row[1]))


conn.close()

Click the Run button will print the contents of the current table. The above program we have created a database test.db students and a data table and write the four student information table.

So SQL injection is how it all about? We try to insert a malicious data, data content is the comic book "Robert '); DROP TABLE students ; -", and see what happens.

SQL database injection Example:

conn = sqlite3.connect('test.db')

Insert injection contains information code:

name = "Robert');DROP TABLE students;--"
query = "INSERT INTO students (name) VALUES ('%s')" % (name)


conn.executescript(query)

View existing student information:

cursor = conn.execute("SELECT id, name from students")
print('IDName')
for row in cursor:
    print('{0}{1}'.format(row[0], row[1]))


conn.close()

You will find that running, the program does not output the contents of any data, but returns an error message: Form students can not be found!

Why is this? The problem is that we have inserted a data item contains SQL keywords DROP TABLE, meaning these two keywords is to clear a form from the database.

And before the keyword Robert '); SQL allows the actuator think the previous command has ended, so that the risk of DROP TABLE command is executed.

In other words, this contains DROP TABLE key data items so that the original simple SQL Insert contact information:

INSERT INTO students (name) VALUES ('Robert')

It becomes a form contains additional command a clear statement:

INSERT INTO students (name) VALUES ('Robert');DROP TABLE students;

The SQL database after performing the above operations, students form is cleared, so the form can not be found, all data items is missing.

How to prevent SQL injection problem?

You may have thought, injection problems because of the implementation of the data entry SQL keywords, then just check whether there is data entry SQL keywords are not on it yet?

Yes it is, many database management systems are adopted this seemingly "quick and easy" way of filtering, but this is not a solution to the fundamental, if Americans really called "Drop Table" yet ? You can not change the name of it is pressing home.

There are many reasonable protective measures. First, try to avoid using common database and database structure. In the above case, if the form name is not the students, then the code will inject an error in the implementation process, data loss will not occur - SQL injection is not as we imagine so simple, it requires the attacker itself has sufficient understanding of the structure of the database to be successful, so try to use a more complex structure and naming when building the database will greatly reduce the probability of a successful attack.

Using regular expressions and other means to limit the format string filtering, the number of characters and other data items is also a good protective measures. In theory, as long as avoid quotation marks, semicolons, and other special characters exist in the data item can largely avoid SQL injection occurs.

Another is the use of various types of program documentation recommended way to perform database query operations and write operations of data items, such as in the above case, if we slightly modified, first use the execute () method to ensure that each execution only a statement can be executed, and the data items in a SQL statement as arguments separated, completely avoided execute SQL injection problem, the following SQL database exemplary anti injection.

conn = sqlite3.connect('test.db')

Insert information in a secure manner comprises injecting code:

name = "Robert');DROP TABLE students;--"
query = "INSERT INTO students (name) VALUES (?)"
conn.execute(query, [name])

View existing student information:

cursor = conn.execute("SELECT id, name from students")
print('IDName')
for row in cursor:
    print('{0}{1}'.format(row[0], row[1]))
conn.close()

For PHP, it can escape, if necessary, review the data item if it is safe to combat mysql_real_escape_string by methods such as SQL keywords SQL injection .

Of course, make a backup of the database, and encrypt sensitive content is always the most important. Some security issues may never have the perfect solution, only if we do the most basic protective measures in order to remedy the situation in the event of a problem, to ensure minimal losses.

Note: Whenever a program SQL injection vulnerability, because the program parameters to accept user input from a client variable or URL passed, and the variable or parameter forms part of the SQL statement, or for user input parameters passed we should be vigilant, this is the principle of security in the field of "external data can not be trusted" Web security areas throughout a variety of attacks, mostly because developers violate this principle caused, so Nature can think of, that is, from the detection variables, filtering, validation start, ensure that the variable is the developer envisioned.

1, variable data type and format checks

If your SQL statement is similar where id = {$ id} this form, all of the database id are numbers, then they should be executed before SQL, check to ensure that the variable is of type int id; if it is accepted mailbox, that they should check and ensure that the variable must be strict mailbox format, other types such as date, time, etc. is also a reason. To sum up: as long as there is a fixed format of variables in SQL statements before execution, should be strictly in accordance with the fixed format to be examined, to ensure that the variable is the format we expected, so largely to avoid SQL injection attacks.

For example, we accept the argument the previous example username in our product design should be registered in the user's start, there is a regular user names, such as 5-20 characters, only uppercase and lowercase letters, numbers, and some security symbols, does not contain special characters. At this point we should have a function to check_username unified examination. However, there are still many exceptions and can not be applied to this criterion, such as article distribution system, comment system must allow users to submit any string of scenes, which requires the use of other programs such as a filter.

2, special symbols filtration

For fixed format variables can not be determined, a special symbol must be filtered or escaped.

3, bind variables, using a prepared statement  

The MySQL mysqli driver provides support for precompiled statements, different programming languages, there are methods using precompiled statements were

In fact, bind variables using precompiled statement is the best way to prevent SQL injection, use the pre-compiled SQL statement does not change the semantics, in a SQL statement, the variable with a question mark? Represents, even if hackers skill is bigger, can not changes in the structure of the SQL statement

What is precompiled sql

1.1: What is a pre-compiled statement 

Usually we are in a sql db finished receiving the final return can be divided into the following three processes:

Lexical and semantic parsing, optimization sql statements, the implementation of the development plan, execute and return results

We refer to this general statement called Immediate Statements.  

But in many cases, we are a sql statement may be executed repeatedly, each execution or when only the individual values ​​are different (such as different values ​​query where clause, the clause different set of values ​​update, insert different values ​​of values).

If you need to go through every lexical semantic parsing above statement optimizer to develop the implementation plan, the efficiency is clearly not.

The so-called pre-compiled statement that the value of such statements with placeholders instead be regarded as the sql statement templated or parameterization, called the general said such statements or Parameterized Statements Prepared Statements

Prepared Statement advantage is summarized as follows: a compilation, run multiple times, eliminating the need for optimization and other analytic process; furthermore prepared statement to prevent sql injection.

Optimization of course, many times the optimal execution plan is not alone knows template sql statement can determine, it is often required to estimate the cost of the price by a specific value.

1.2: MySQL pre-compiled function

Note that older versions of MySQL (prior to 4.1) is not supported by the server pre-compiled, but based on the industry production environment prevailing circumstances, which can be considered pre-compiled MySQL support services end.

Here we look at the use of MySQL in a prepared statement.

(1) First, we have built a test table table t, the structure is as follows:

mysql> show create table t\G
*************************** 1. row ***************************
       Table: t
Create Table: CREATE TABLE `t` (
  `a` int(11) DEFAULT NULL,
  `b` varchar(20) DEFAULT NULL,
  UNIQUE KEY `ab` (`a`,`b`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

(2) Compile

We next to a precompiled sql statement by the grammar PREPARE stmt_name FROM preparable_stm

mysql> prepare ins from 'insert into t select ?,?';
Query OK, 0 rows affected (0.00 sec)
Statement prepared

(3) execution

We EXECUTE stmt_name [USING @var_name [, @var_name] ...] syntax to execute a prepared statement

mysql> set @a=999,@b='hello';
Query OK, 0 rows affected (0.00 sec)
 
mysql> execute ins using @a,@b;
Query OK, 1 row affected (0.01 sec)
Records: 1  Duplicates: 0  Warnings: 0
 
mysql> select * from t;
+------+-------+
| a    | b     |
+------+-------+
|  999 | hello |
+------+-------+
1 row in set (0.00 sec)

You can see, the data has been successfully inserted into the table.

Pre-compiled MySQL statement scope is session-level, but we can control the global maximum storage of a prepared statement by max_prepared_stmt_count variables.

mysql> set @@global.max_prepared_stmt_count=1;
Query OK, 0 rows affected (0.00 sec)
 
mysql> prepare sel from 'select * from t';
ERROR 1461 (42000): Can't create more than max_prepared_stmt_count statements (current value: 1)

When the pre-compiled article has reached a threshold number can see MySQL error will be reported as shown above.

(4) release

If we want to release a prepared statement, you can use the {DEALLOCATE | DROP} PREPARE stmt_name operate syntax:

mysql> deallocate prepare ins;
Query OK, 0 rows affected (0.00 sec)

Why PrepareStatement can prevent sql injection

Principle is a method for precompiled SQL statements first set of parameters may be controlled to compile client, generating a corresponding set of temporary variables, and then using the corresponding setting method, which sets the temporary variable element assignment, assignment function setString (), have passed mandatory parameter type checking and security checks, so we avoid the generation of SQL injection. The following specific analysis

(1): Why Statement will be sql injection

The reason is because the Statement inject sql SQL statement because the structure has changed. such as:

"select*from tablename where username='"+uesrname+  
"'and password='"+password+"'"

After the user inputs 'or true or' structural changes sql statement.

select*from tablename where username=''or true or'' and password=''

This would have to determine the user name and password when the match will count, but after changing into a logical relationship or, regardless of the user name and password matches the type of the return value is always true;

(2) Why Preparement can prevent SQL injection.

Because the style is Preparement

select*from tablename where username=? and password=?

The SQL statement will carry out before getting the user's input with pre-compiled database, so no matter what the user enters a user name and password are always judgments and logical relations, preventing SQL injection

A brief summary, the reasons parameterization can prevent implantation of that statement is the statement, the parameter is part of the value of the parameter, the parameter is not a statement, the database only run semantically statement, as time is running with a normal backpack or a monster, will not affect the route, the difference is nothing travels faster and slow points.

How to prevent SQL injection mybatis

1, first look at the difference between the following two sql statements:

<select id="selectByNameAndPassword" parameterType="java.util.Map" resultMap="BaseResultMap">
select id, username, password, role
from user
where username = #{username,jdbcType=VARCHAR}
and password = #{password,jdbcType=VARCHAR}
</select>


<select id="selectByNameAndPassword" parameterType="java.util.Map" resultMap="BaseResultMap">
select id, username, password, role
from user
where username = ${username,jdbcType=VARCHAR}
and password = ${password,jdbcType=VARCHAR}
</select>

mybatis the # and $ difference:

1, # incoming data as a string, the incoming data will automatically add a double quotation mark.

Such as: where username = # {username}, if the incoming value is 111, then the value where username when parsed into sql = "111", if the incoming value id, is then parsed into sql where username = "id". 

2, $ incoming data directly show the sql generated.

Such as: where username = $ {username}, if the incoming value is 111, then when the value of the parsed into sql where username = 111;

If the incoming value; drop table user ;, parsing into sql to: select id, username, password, role from user where username =; drop table user;

3, # way possible to a large extent prevent sql injection, $ Sql ​​injection method can not prevent.

4, $ mode is generally used for incoming database objects, such as passing a table name.

5, generally can not use $ # would, if forced to use "$ {xxx}" such parameters, to do the work manually filtering to prevent sql injection attacks.

6, with MyBatis, "$ {xxx}" parameter will be directly involved in this format SQL compiler, and thus can not prevent injection attacks. But when it comes to dynamic table and column names, using only "$ {xxx}" This parameter format. Therefore, such parameters we need to manually code processing to prevent implantation.

[Conclusion] In the preparation of MyBatis mapped statement, as far as possible "# {xxx}" this format. If you forced to use "$ {xxx}" such parameters, to do the work manually filtering to prevent SQL injection attacks.

How mybatis is done to prevent sql injection

MyBatis framework as the persistence layer framework of a semi-automated, which SQL statements should write our own manual, this time of course, the need to prevent SQL injection. In fact, the SQL is MyBatis having a "+ Input Output" function, similar to the structure of the function, with reference to two examples above. Wherein, parameterType represents the type of input parameters, resultType parameter indicates the type of output. In response to the above, if we want to prevent SQL injection, of course, to work hard in the input parameters. # Use the code above, ie input parameters in SQL stitching section, after passing parameters, print out the execution of SQL statements, SQL will see something like this:

select id, username, password, role from user where username=? and password=?

No matter what the input parameters, print out SQL are like this. This is because MyBatis pre-compiled function is enabled, before SQL execution, it first sends compile the above SQL to the database; When executed, the direct use of compiled SQL, replace the placeholder on it "?." Because SQL injection can only build process works, so this is very good way to avoid the problem of SQL injection.

The principle underlying [is] how MyBatis SQL pre-compiler to do it? In fact, in the bottom of the frame, is the JDBC PreparedStatement class at work, we are very familiar with the PreparedStatement Statement subclass, its object contains compiled SQL statement. When this "ready" approach will not only improve safety, but also in the implementation of the same SQL repeatedly, it can improve efficiency. The reason is that SQL has been compiled, when executed again without having to re-compile

参考来源:jizhi.im/blog/post/sql_injection_intro
https://www.cnblogs.com/myseries/p/10821372.html

you may also like

1, GitHub starred 3.2w! The most complete history and technical personnel interview Manual! FackBoo initiated and summary

2, how to become a good architect?

3, starting from scratch to build a back-end technology stack start-up companies

4, programmers can generally take private live from what platform?

5, 37-year-old programmer to be cut, 120 days not find a job, but unfortunately to small companies, the result of senseless ...

6, drops in Taiwan to build business practice, for the first time exposure

7, do not accept their fate, 10 years from assembly line workers to the work program Google Yuan, an inspirational story of Hunan sister

8, 15 and fuss FIG understand the difference between efficient!

Released eight original articles · won praise 17 · views 60000 +

Guess you like

Origin blog.csdn.net/emprere/article/details/104305966