SQL injection is a simple attack vector that is still very common today. The reason for this is none other than no patch for stupid. Why do you say this, let's take JAVA as an example to illustrate:
Suppose a table like this exists in the database:
Then use the JDBC action table:
The above code is often used by some developers. Imagine a situation where the incoming userId parameter is "3; drop table user; The SQL statement executed is as follows:
After the database is compiled and executed, the user table is deleted. Voila, a simple SQL injection attack takes effect! This is because the code above does not conform to the programming specifications.
When we program according to the specification, SQL injection is non-existent. This is also the caseThe first way to avoid SQL injection: precompiled statements, the code is as follows:
Why doesn't SQL injection exist in the above code? Because the precompiled statement is used, the precompiled statement will set "select name from user where id= ?" The statement is compiled in advance so that it only needs to be replaced with the incoming parameters when executed? Placeholders are fine. For the first non-compliant case, the program will write a SQL statement and then compile it with the content passed in by the user, which is precisely the problem.
In addition to using precompiled statements, there is a second optionWays to avoid SQL injection attacks: Stored procedures。 A stored procedure is a set of SQL statements that perform a specific function, compiled and stored in a database, and the user can execute it by calling a stored procedure and giving a parameter (if the stored procedure has parameters), which can also avoid SQL injection attacks
The corresponding stored procedure in the above code is as follows:
Of course, users can also do character checking on the frontend, which is also a way to avoid SQL injection: for example, for the userId parameter above, the user will check for a semicolon and an error will be displayed. However, the most fundamental reason is that SQL injection attacks exist because apps do not use least privilege when accessing databases. It seems that everyone has been using the root account to access the database.
So how does MyBatis avoid SQL injection attacks? Or take the table user above as an example: Let's say the mapper file is:
The corresponding java files are:
You can see that the input parameter is userId of type String, when we pass in userId="34; drop table user; After that, the printed statement reads:
Regardless of the userID entered, his sql statement is like this. This is due to the fact that mybatis uses precompiled statements in the underlying implementation. When the database executes that statement, it directly uses the precompiled statement and then replaces the placeholder with the passing userId? Just go run. Replace placeholders first? The process of compilation is carried out, so there is no room for SQL injection to survive.
So how does MyBatis do SQL precompilation? In fact, the PreparedStatement class is used at the bottom of the framework. The PreparedStaement class not only avoids SQL injection, but also saves (N-1) compilation time when the same SQL statement is executed N times, thus improving efficiency.
If you change the above statement to:
When we enter userId="34; drop table user; After that, the printed statement reads:
At this time, mybatis does not use precompiled statements, it will stitch strings first and then perform compilation, which is exactly how SQL injection takes effect.
Therefore, when writing mybatis mapping statements, try to use the format "#{xxx}". If you have to use parameters like "${xxx}", you need to manually filter them to prevent SQL injection attacks.
|