SQL注入
jdbc
需要将mysql-connector-java-8.0.28.jar放到tomcat的lib目录下面
SQL代码
CREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR(50) NOT NULL
);
INSERT INTO users (id, name)
VALUES (1, 'Alice'), (2, 'Bob'), (3, 'Charlie');漏洞代码
<%@page import="java.sql.*"%>
<%
String name = request.getParameter("name");
String query = "SELECT * FROM users WHERE name = '" + name + "'";
// 设置数据库连接
String url = "jdbc:mysql://192.168.32.130:3306/test";
String username = "root";
String password = "123456";
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection(url, username, password);
// 执行查询
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(query);
// 显示查询结果
out.println("<table>");
out.println("<tr><th>ID</th><th>Name</th></tr>");
while (rs.next()) {
int id = rs.getInt("id");
String uname = rs.getString("name");
out.println("<tr><td>" + id + "</td><td>" + uname + "</td></tr>");
}
out.println("</table>");
// 关闭数据库连接
rs.close();
stmt.close();
conn.close();
%>
修复代码(预编译)
预编译语句是一种更安全和更高效的处理方式,它无法处理某些情况,例如like和order by子句中的动态值。
为了解决这些问题,有几种可行的方法:
在使用字符串拼接构建SQL语句时,必须对动态值进行适当的转义和验证,以避免SQL注入攻击。
例如,在使用like子句时,可以这样处理:
对于无法使用预编译的查询,可以在编写代码时尽量将动态值分离出来,使其成为固定的字符串。
例如,在使用order by子句时,可以这样处理:
mybatis+springboot
使用MyBatis和Spring Boot的示例代码的典型目录结构
创建一个maven项目,名字是example。

修复代码
在 MyBatis 中,你可以使用占位符(?)来表示参数,这样就可以将参数值与 SQL 语句分离。在 mapper XML 文件中,你可以使用 <select>、<insert> 或 <update> 标签来定义 SQL 语句,然后使用 #{} 占位符来引用参数。例如:
当你使用参数化查询时,MyBatis 会自动将 SQL 语句转换为预编译语句,从而避免 SQL 注入攻击。预编译语句将会在 SQL 执行之前进行编译和解析,因此恶意注入的代码将无法被执行。
在 mapper XML 文件中,你可以使用 #{} 占位符来引用参数。例如:
避免在 SQL 语句中拼接参数值,因为这样容易受到 SQL 注入攻击。如果你需要在 SQL 语句中拼接字符串或其他类型的值,请使用 MyBatis 内置的字符串函数或者使用占位符来引用参数。
在 mapper XML 文件中,你可以使用 <select>、<insert> 或 <update> 标签来定义 SQL 语句,然后使用 #{} 占位符来引用参数。例如:
在这个例子中,findUsers 方法将会接收一个 Map 类型的参数,并返回匹配的 User 对象列表。#{orderByColumn} 和 #{orderByDirection} 占位符将会将参数值安全地插入到 SQL 语句中,并避免了 SQL 注入攻击。
为了避免 SQL 注入攻击,你应该限制 ORDER BY 子句中的列名只能为预定义的值。你可以在代码中定义一个白名单,只允许一些特定的列名。例如:
最后更新于
这有帮助吗?