As a classic web security issue, SQL injection is something that almost every student who has taken a cybersecurity course has encountered to some extent.
The underlying principle is actually quite simple: by inserting specially crafted characters into an SQL statement, an attacker can manipulate the query condition into a tautology, thereby bypassing checks such as username and password validation and directly retrieving data from the database.
In more severe cases, SQL injection can even lead to database corruption or data loss, causing extremely serious consequences.
Below is a simple example of SQL injection.
Suppose we have a login form where users enter a username and password. The backend validates these credentials and returns the corresponding data.
1
SELECT*FROM users WHERE username = ${} AND password = ${};
Now, if a malicious user enters special input such as:
1
' OR '1'='1
The original SQL statement becomes:
1
SELECT*FROM users WHERE username =''OR'1'='1'AND password ='';
Since '1'='1' is always true, the condition becomes a tautology, and the attacker can retrieve all records from the database.
Another example:
1
admin'; DROP TABLE users; --
After concatenation, the SQL becomes:
1
SELECT*FROM users WHERE username ='admin'; DROPTABLE users; --'
After executing the first query, the DROP TABLE statement will also be executed, potentially deleting the entire users table.
Prevention Measures
Use precompiled (prepared) SQL statements to avoid directly concatenating user input into SQL queries, such as Java’s PreparedStatement.
Use ORM frameworks such as MyBatis or Hibernate.
Below, we’ll introduce how to use the MyBatis framework to perform SQL queries. (Of course, MyBatis can also be integrated into Spring Boot, but that will not be covered here.)
From the logs, we can clearly see that a precompiled SQL statement is being used. The user-provided parameter does not become part of the SQL structure itself; instead, it is bound as a parameter value. This effectively prevents SQL injection.
MyBatis achieves this through JDBC’s underlying PreparedStatement. The SQL statement is precompiled before execution, and parameters are safely bound during runtime.
To better understand the difference, consider the following example.
It is clear that when using ${}, the SQL is directly constructed by string concatenation. This approach does not prevent SQL injection and is highly risky.
In contrast, #{} is much safer because it relies on precompilation and parameter binding, fundamentally preventing SQL injection.
Hello everyone,I'm 4pril. This website is solely for recording the learning process and the journey of coding. If there is any infringement, please feel free to contact me. Meanwhile, I welcome everyone to share and exchange experiences with me. Have fun ;)