最后更新:2026-04-17
SQL 注入(SQL Injection)是一种代码注入攻击,攻击者通过在应用程序的输入字段中插入恶意 SQL 代码,操纵后端数据库执行非预期的命令。
| 维度 | 评级 |
|---|---|
| OWASP Top 10 | A05:2025 - Injection |
| CWE | CWE-89 |
| 严重程度 | 高危/严重 |
' AND 1=1 --
' AND 1=2 --
' UNION SELECT username, password FROM users --
' AND SLEEP(5) --
'; DROP TABLE users; --
// 漏洞代码
public User findByUsername(String username) {
String sql = "SELECT * FROM users WHERE username = '" + username + "'";
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(sql);
// ...
}
// 攻击输入: ' OR '1'='1
// 实际执行: SELECT * FROM users WHERE username = '' OR '1'='1'
<!-- 漏洞代码:使用 ${} 会直接拼接 -->
<select id="findByUsername" resultType="User">
SELECT * FROM users WHERE username = '${username}'
</select>
<!-- 安全代码:使用 #{} 会预编译 -->
<select id="findByUsername" resultType="User">
SELECT * FROM users WHERE username = #{username}
</select>
// 漏洞代码
TypedQuery<User> query = em.createQuery(
"SELECT u FROM User u WHERE u.username = '" + username + "'", User.class);
// 安全代码
TypedQuery<User> query = em.createQuery(
"SELECT u FROM User u WHERE u.username = :username", User.class);
query.setParameter("username", username);
grep -rn "executeQuery.*+" src/
grep -rn '\${' src/
semgrep --config ./semgrep-rules/sql-injection.yml src/
sqlmap -u "http://example.com/user?id=1" --batch
// JDBC
String sql = "SELECT * FROM users WHERE username = ?";
PreparedStatement pstmt = connection.prepareStatement(sql);
pstmt.setString(1, username);
// MyBatis
SELECT * FROM users WHERE username = #{username}
// JPA
@Query("SELECT u FROM User u WHERE u.username = :username")
User findByUsername(@Param("username") String username);
// 白名单校验
if (!username.matches("^[a-zA-Z0-9_]{3,20}$")) {
throw new IllegalArgumentException("Invalid username");
}
-- 应用程序数据库用户只授予必要权限
GRANT SELECT, INSERT, UPDATE ON app_db.* TO 'app_user'@'localhost';
// Spring Data JPA
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
User findByUsername(String username); // 自动参数化
}
// 安全的动态查询
Specification<User> spec = (root, query, cb) ->
cb.equal(root.get("username"), username);
配置 Web 应用防火墙过滤 SQL 注入攻击特征。