Damn it, SQL injection actually broke our system!

Preface

Let me show you a comic first, the original is xkcd, I translated it into Chinese. 

If you can smile when you read the comics, you basically understand what SQL injection is. Here are two more verbose sentences. Here is a simpler example. For example, this SQL does string splicing:

"select * from user where id= " + userID

There is no problem under normal circumstances, but if the userID is entered as a parameter:

1 or 1=1

The final executed SQL will become:

select * from  user  where id=1 or 1=1

Among them, the or 1=1previous id=1 is useless, and all users are selected at once!

This is a very simple case. In fact, when I was in my old company, a SQL injection directly disrupted our payment service.

1. Restore the scene of the accident

One day the operating lady came over and told me that many users couldn't pay. This payment service is an old system. Three people have changed hands. It has been very stable without any problems.

I started locating the problem without a second word. I first looked at the server log and found a lot of exceptions that reported too many database connections. Because the payment function is too important, at that time, in order to ensure the rapid recovery of the payment function, the two nodes of the payment service were restarted by the operation and maintenance.

It temporarily returned to normal after 5 minutes.

I will continue to locate the reason. According to my experience at the time, there are generally too many database connections, which may be 连接忘了关闭caused. But careful investigation of the code did not find the problem. The database connection pool we used at the time would automatically recycle idle connections 排除了这种可能.

After a while, another node has too many database connections.

But at this time, I haven't found the reason yet, so I have no choice but to ask the operation and maintenance to restart the service. However, this time the database 最大连接数调大is set to 100 by default. The 500 we set at the time was adjusted to 1000 later. (In fact, most companies now set this parameter to 1000)

Use the command:

set GLOBAL max_connections=500;

Can take effect in time, without restarting the mysql service.

This time I bought me more time and asked dba to help me troubleshoot the cause.

Use the show processlist;command to view the current thread execution:

You can also view the current connection status to help identify problematic queries. (It needs to be noted that the above picture is just an example I gave, the real result on the line is not like this)

  • id thread id

  • User account for executing sql

  • Host ip and port number of the database where SQL is executed

  • db database name

  • Command Execute commands, including: Daemon, Query, Sleep, etc.

  • Time The time spent executing sql

  • State execution state

  • info Execution information, which may contain sql information.

Sure enough, I found an unusual query SQL, which has not been executed after almost an hour!

dba copied the sql and sent it to me. Then kill -9kill the SQL thread that takes a long time to execute.

Later, the problem of too many database connections did not reappear.

I got the sql and analyzed it carefully, and found that an order query statement was injected by the attacker with a long piece of sql, which must have been written by a master. I have never seen some of the grammar.

But it can be confirmed that it is correct and was injected by sql.

Through the information in that piece of sql, I quickly found the relevant code. When querying the data, the input parameter was used Statmentinstead of the PrepareStatementpre-compilation mechanism.

It's easy to deal with knowing the reason, preparestatementand the problem is finally solved after changing the query data to the precompilation mechanism.

2. Why does it cause too many database connections?

I believe that many students will have a question after seeing this: Why does sql injection cause too many database connections?

I will use a picture below to explain to everyone:

  1. An attacker sql injection parameters such similar: -1;锁表语句--.

  2. The ;previous query statement is executed first.

  3. Since the --following statement will be commented, only the lock table statement will be executed next to lock the table.

  4. After a normal business request successfully obtains a connection from the database connection pool, when the table needs to be manipulated, it tries to obtain a table lock, but it cannot be obtained until it times out. Note that a large number of database connections may be occupied here, and they will not be returned in time.

  5. The database connection pool is not enough and there are no idle connections.

  6. A new business request cannot obtain a connection from the database connection pool, and an exception of too many database connections is reported.

SQL injection causes too many database connections. The most fundamental reason is the long-term lock table.

3. How is the table information leaked?

Some careful students may ask a question: In the example of locking the table above, how did the attacker get the table information?

Method 1: Blind guess

The attacker guesses the name of the table that may exist based on common sense.

Suppose we have such query conditions:

select * from t_order where  id = ${id};

Incoming parameters:-1;select * from user

The final execution sql becomes:

select * from t_order where  id = -1; select * from  user;

If the sql has data returned, it means that the user table exists, and it has been guessed correctly.

It is recommended that the table name should not be too simple and can be prefixed with an appropriate prefix, such as t_user. This can increase the difficulty of blind guessing.

Method 2: Through the system table

In fact, mysql has some system tables, you can check the information of our customized databases and tables.

Suppose we still take this sql as an example:

select code,name  from t_order where  id = ${id};

The first step is to obtain the database and account name.

Pass the parameters as:-1 union select database(),user()#

The final execution sql becomes:

select code,name  from t_order where  id = -1  union  select  database(),user()#

It returns the current database name: sueand the name of the account: root@localhost.

The second step is to obtain the table name.

The parameter transfer is changed to: the -1 union select table_name,table_schema from information_schema.tables where table_schema='sue'#final execution of sql becomes:

select code,name  from t_order where  id = -1  union  select table_name,table_schema from information_schema.tables where table_schema='sue'#

Will return sueall the table names under the database .

It is recommended that the database account accessed by the generating environment program should be separated from the administrator account, and must have control permissions and cannot access system tables.

4. What are the hazards of SQL injection?

1. Core data breach

The purpose of most attackers is to make money. To put it bluntly, it is to obtain valuable information and sell it for money, such as user account numbers, passwords, mobile phone numbers, ID card information, bank card numbers, addresses and other sensitive information.

They can inject statements like this:

-1; select * from  user; --

All the information in the user table can be easily obtained.

Therefore, it is recommended that you encrypt and store these sensitive information, you can use AESsymmetric encryption.

2. Delete library and run away

There are also some attackers who do not play cards according to common sense, and directly delete the system tables or databases after SQL injection.

They can inject statements like this:

-1; delete  from  user; --

The above statement will delete all data in the user table.

-1; drop  database  test; --

The above statement will delete all the contents of the entire test database.

Under normal circumstances, we need to control the permissions of online accounts, and only allow DML (data manipulation language) data manipulation language statements, including: select, update, insert, delete, etc.

DDL (data definition language) database definition language statements are not allowed, including: create, alter, drop, etc.

DCL (Data Control Language) database control language statements are also not allowed, including grant, deny, revoke, etc.

DDL and DCL statements can only be operated by the dba administrator account.

By the way: If the table or the database is deleted, there is actually a remedy, which is to restore from the backup file. You may only lose a small amount of real-time data, so there must be a backup mechanism.

3. Hang the system

Some attackers can even hang up our service directly, which was the case with the old company.

They can inject statements like this:

-1;锁表语句;--

After the table is locked for a long time, the database connection may be exhausted.

At this time, we need to monitor the database thread. If the execution time of a certain SQL is too long, an email warning is required. In addition, setting the timeout period of the database connection reasonably can also alleviate this kind of problem a bit.

From the above three aspects, it can be seen that the sql injection problem is really harmful. We must avoid this type of problem and don't be lucky. If you encounter some attackers who do not issue tickets according to common sense, once you are attacked, you may suffer heavy losses.

5. Why can pre-compilation prevent SQL injection?

preparestatementThe pre-compilation mechanism will perform grammatical analysis, compilation and optimization of the SQL statement before it is executed, and placeholders are used to ?replace the parameter positions .

When it is actually running, the passed parameters will be regarded as a plain text, will not be recompiled, and will not be treated as sql commands.

In this way, even if the input parameters are passed into SQL injection instructions such as:

id; select 1 --

The final executed sql will become:

select * from user order by 'id; select 1 --' limit 1,20

In this way, there will be no SQL injection problems.

6. Pre-compilation must be safe?

I don’t know if you have used the like statement when querying data. For example, if you query a user with the word "Su" in the name, you may use a statement like this to query:

select * from user where name like '%苏%';

There is no problem under normal circumstances.

However, in some scenarios, the incoming conditions are required. For example, name is required. If you inject:, the %last executed sql will become like this:

select * from user where name like '%%%';

In this case, the precompilation mechanism is passed normally, but the execution result of sql will not return the included %users, but all users.

The required name field becomes useless, and the attacker can also get all the data in the user table.

Why does this problem occur?

%It is a keyword in mysql. If used like '%%%', the like condition will be invalid.

How to solve it?

We need to %be /%escaped: .

The escaped sql becomes:

select * from user where name like '%/%%';

Only included %users will be returned .

7. What about some special scenes?

In Java, if it is used mybatisas a persistence framework, in the mapper.xmlfile, if the input parameter is #passed by value, the precompilation mechanism will be used.

Generally we use it like this:

<sql id="query">
   select * fromuser
   <where>
     name = #{name}
   </where>
</sql>

In most cases, everyone is encouraged to use #this method to transfer parameters, which is safer and more efficient.

But sometimes there are special circumstances, such as:

<sql id="orderBy">
   order by ${sortString}
</sql>

The content of the sortString field is dynamically calculated in a method. In this case, it cannot be used #. Instead $, the program will report an error.

Use $case there is the risk of sql injection.

So what should we do in this situation?

  1. Write your own util tool to filter out all injected keywords, and call this tool during dynamic calculation.

  2. If the data source uses Ali's druid, you can turn on the wall (firewall) in the filter, which includes the function of preventing sql injection. But there is a problem, that is, it does not allow multiple statements to operate at the same time by default, and also intercepts batch update operations, which requires us to customize the filter.

8. Other means to prevent SQL injection

1. To catch exceptions

All exceptions need to be captured. Remember that the interface directly returns exception information, because some exception information contains sql information, including: library name, table name, field name, etc. With this information, the attacker can attack your database at will through SQL injection. The current mainstream approach is to have a dedicated gateway service that uniformly exposes external interfaces. When a user requests an interface, it passes through it first, and then it forwards the request to the business service. The advantage of this is that the returned body of the returned data can be packaged uniformly, and if an exception occurs, the unified exception information can be returned, and sensitive information can be hidden. In addition, it can do current limiting and permission control.

2. Use code inspection tools

Using code detection tools such as sqlMap, it can detect sql injection vulnerabilities.

3. There must be monitoring

Need to monitor the execution of the database sql, if there is an abnormal situation, timely email or SMS reminder.

4. Database account needs to control permissions

Create a separate account for the database in the production environment, assign only DMLrelevant permissions, and cannot access system tables. Do not use the administrator account directly in the program.

5. Code review

The establishment of a code review mechanism can identify some hidden problems and improve code quality.

6. Use other means to deal with

When precompiled parameters cannot be used, either enable druidthe filterfirewall or write code logic to filter out all possible injected keywords.

The best articles of 3 years

Comic: Kangxi can't learn binary

Comic: Seven unspoken rules programmers must be careful

Comic: Brother, have to stay up all night again tonight!

Architect dismissal guide

The fate of programmers

Who is the number one IDE in the universe?

HTTP Server: A poor counterattack

How to reduce programmer's salary?

Programmer, you have to choose the right time to run!

Javascript: a counterattack from a dick

I am a thread

Daming Postman of TCP/IP

Https after a story

CPU Forrest

Guess you like

Origin blog.csdn.net/coderising/article/details/113931025