### SQL 注入防御方法 **1. 使用预编译语句** 这是最有效、也是最推荐的防御方法。预编译语句会先将 SQL 语句发送到数据库进行编译,然后将用户输入作为参数传递给编译好的语句。这样一来,用户输入的数据就无法改变 SQL 语句本身的结构 - **原理**:将 SQL 语句与用户输入的数据分开处理。数据库会把用户输入的内容看作纯粹的**数据**,而不是可执行的**代码** - **示例**: - **不安全的代码**:`"SELECT * FROM users WHERE username = '" + userInput + "';"` - 如果 `userInput` 是 `' OR 1=1 --`,整个语句就变成了 `SELECT * FROM users WHERE username = '' OR 1=1 --;`,从而绕过登录验证 - **安全的预编译语句**:`"SELECT * FROM users WHERE username = ?;"` - 这里的问号 `?` 是一个占位符。无论用户输入什么,都会被当作 `username` 字段的值来处理,而不是 SQL 代码 **2. 对所有用户输入进行严格验证和过滤** 永远不要相信用户的任何输入。在将数据送入数据库之前,必须对其进行验证和过滤 - **白名单验证**:只允许特定的字符、格式或值通过。例如,如果某个输入框只接受数字,那么就只允许数字通过 - **黑名单过滤**:禁止某些特定的危险字符或字符串,如单引号 `'`、分号 `;`、双破折号 `--` 等。但是,这种方法很容易被绕过,不推荐作为主要的防御手段 **3. 使用 ORM 框架** 许多现代编程语言的框架都提供了 ORM 工具,例如 Java 的 Hibernate、Python 的 SQLAlchemy、PHP 的 Eloquent。这些框架通常内置了对 SQL 注入的保护机制 - **优点**: - **安全性**:ORM 框架会自动处理参数绑定,将开发者从手动编写安全 SQL 语句的繁琐工作中解放出来 - **易用性**:开发者可以使用面向对象的方式操作数据库,无需直接编写 SQL 语句 **4. 最小权限原则** 为数据库账户分配最小的权限。一个账户如果只需要读取数据,就只给它 `SELECT` 权限,不要给它 `INSERT`、`UPDATE` 或 `DELETE` 权限 - **好处**:即使攻击者成功注入了 SQL 代码,也无法执行超出该账户权限范围的操作,如删除整个数据库 **5. 错误信息处理** 不要向用户暴露详细的数据库错误信息。攻击者可以利用这些信息来了解数据库结构、版本等,从而更容易发起下一次攻击 - **正确做法**:当数据库查询失败时,只向用户显示一个通用的、友好的错误页面,并在后台日志中记录详细信息,供开发者排查 **6. 使用 Web 应用防火墙(WAF)** WAF 可以在 Web 应用之前对 HTTP 请求进行过滤和拦截,它可以识别并阻止包含 SQL 注入特征的恶意请求 - **优点**: - **全面保护**:可以为整个应用提供一层额外的保护 - **实时拦截**:在攻击到达应用之前就将其阻止 - **局限性**: - WAF 的规则可能需要不断更新,以应对新的攻击方式 - 可能会有误报,影响正常用户的访问