题目
用户登录模块的SQL注入防护实践
信息
- 类型:问答
- 难度:⭐⭐
考点
SQL注入原理,参数化查询应用,输入验证机制,防御措施实现
快速回答
SQL注入是通过恶意SQL代码插入应用程序输入字段的攻击手段。核心防御措施:
- 使用参数化查询:分离SQL代码与数据(如PreparedStatement)
- 实施输入验证:白名单过滤特殊字符(如正则表达式)
- 最小化数据库权限:应用账户使用最低必要权限
原理说明
SQL注入发生在攻击者通过用户输入(如表单字段)插入恶意SQL片段时。当应用程序直接拼接SQL语句而未验证或转义输入时,攻击者可操纵查询逻辑,例如绕过登录验证或窃取数据。
攻击示例
// 危险代码:直接拼接用户输入
String query = "SELECT * FROM users WHERE username='" + username + "' AND password='" + password + "'";
// 攻击者输入:username = "admin'--",password任意
// 最终SQL:SELECT * FROM users WHERE username='admin'--' AND password='xxx'
// "--"注释掉后续语句,直接以admin身份登录防御方法及最佳实践
1. 参数化查询(最有效)
// 使用PreparedStatement
String sql = "SELECT * FROM users WHERE username=? AND password=?";
PreparedStatement stmt = connection.prepareStatement(sql);
stmt.setString(1, username); // 自动处理特殊字符
stmt.setString(2, password);
ResultSet rs = stmt.executeQuery();为什么有效:数据库区分代码与数据,用户输入始终被视为字符串而非可执行代码。
2. 输入验证与转义
// 白名单验证(示例:仅允许字母数字)
if (!username.matches("[a-zA-Z0-9]+")) {
throw new IllegalArgumentException("Invalid input");
}
// 必要时转义(但非首选)
String safeInput = ESAPI.encoder().encodeForSQL(new OracleCodec(), input);注意:转义是最后防线,因不同数据库转义规则不同。
3. 纵深防御策略
- 最小权限原则:应用数据库账户禁用DROP、DELETE等高危权限
- 错误处理:返回通用错误信息(避免泄露数据库结构)
- 定期扫描:使用SQLMap等工具进行渗透测试
常见错误
- 仅前端验证:攻击者可绕过浏览器直接发送恶意请求
- 部分参数化:混合使用拼接和参数化(如"WHERE id=" + id + " AND name=?")
- 过度依赖存储过程:存储过程自身也可能存在注入漏洞
扩展知识
- 二次注入:已转义数据存入数据库后,被取出再次使用时不转义
- ORM框架风险:Hibernate的HQL/Criteria虽安全,但原生SQL查询仍需参数化
- 新型攻击:NoSQL注入(如MongoDB)、布尔盲注等