Web 安全

SQL 注入

约 4 分钟阅读

什么是 SQL 注入

SQL 注入是一种漏洞,当用户输入未经适当处理就被嵌入数据库查询时,攻击者可以执行任意 SQL 语句。它多年来一直位列 OWASP Top 10,是最危险的 Web 漏洞之一,可能导致数据库中所有数据的窃取、篡改、删除,甚至服务器的操作系统命令执行。

自 1998 年首次被公开报告以来,经过四分之一个世纪,SQL 注入至今仍是针对 Web 应用程序的主要攻击手法。尽管根本性的防御措施已经明确,但由于实现上的缺陷,漏洞仍然层出不穷。

攻击原理与类型

SQL 注入发生在应用程序通过字符串拼接构建 SQL 查询时。例如,如果登录表单中输入的用户名被直接嵌入 SELECT * FROM users WHERE name = '输入值' 这样的查询中,攻击者输入 ' OR '1'='1 就能使 WHERE 子句始终为真,从而绕过认证。

主要攻击类型

  • UNION 型:注入 UNION SELECT 获取本不可访问的表中的数据。需要匹配列数和类型,但可以通过错误消息或响应变化推断
  • 报错型:故意触发错误,从错误消息中读取数据库信息 (表名、列名、数据)
  • 盲注:当错误消息不显示时,利用布尔型条件分支或基于时间的响应差异,逐位提取信息
  • 带外 (Out-of-Band):通过 DNS 请求或 HTTP 请求将数据从数据库发送到外部服务器

由于 sqlmap 等自动化工具的存在,即使没有高级技术知识也能检测和利用 SQL 注入。

实际危害与影响范围

SQL 注入造成的危害远不止数据窃取。

  • 数据窃取:数据库中存储的所有数据 (用户个人信息、认证信息、信用卡号等) 都可能泄露
  • 数据篡改与删除:注入 UPDATEDELETE 语句篡改或删除数据。也可以通过 DROP TABLE 删除整个表
  • 认证绕过:操纵登录查询,在不知道密码的情况下以任意账户 (包括管理员) 身份登录
  • 服务器控制权夺取:利用数据库功能 (MySQL 的 LOAD_FILE、SQL Server 的 xp_cmdshell 等) 执行操作系统级命令

许多大规模数据泄露事件都涉及 SQL 注入。通过 WAF 检测是有效的辅助措施,但利用巧妙编码和注释插入绕过 WAF 的技术也已为人所知,因此不能替代根本性的防御措施。

根本性防御措施

SQL 注入的根本防御措施是明确的,正确实现后可以完全消除漏洞。

预处理语句 (参数化查询)

将 SQL 语句结构与数据分离,防止用户输入被解释为 SQL 语法。这是最可靠且推荐的防御措施。所有数据库访问库都支持预处理语句。

使用 ORM

使用 ORM (对象关系映射) 可以减少直接编写 SQL 的机会,降低 SQL 注入风险。但在使用 ORM 的原生查询功能或自定义查询时,需要与预处理语句同样的注意。

纵深防御

  • 最小权限原则:将应用程序使用的数据库账户权限限制到最低限度。只读操作使用只读账户
  • 输入验证:数字字段只接受数字,邮箱字段只接受正确格式。但这只是辅助措施,不能替代预处理语句
  • 错误消息控制:不向用户直接显示数据库错误消息。防止通过报错型 SQL 注入泄露信息
  • 漏洞管理:通过定期安全扫描和代码审查,尽早发现 SQL 注入漏洞
  • 安全头配置:虽非直接的 SQL 注入防御措施,但可增强整体安全态势

常见误解

对输入值进行转义就能防止 SQL 注入
转义处理容易出现实现错误,字符编码差异和特殊情况会导致遗漏。预处理语句从根本上将 SQL 结构与数据分离,消除了转义遗漏的风险。应使用预处理语句而非转义。
NoSQL 数据库不会发生 SQL 注入
虽然不会发生 SQL 注入,但存在名为 NoSQL 注入的同类漏洞。在 MongoDB 中,将用户输入直接嵌入 JSON 查询可能导致查询运算符注入。无论数据库类型如何,正确处理用户输入都是必须的。

SQL 注入与 XSS 的比较

SQL 注入

以服务器端数据库为目标。可以窃取、篡改、删除数据。通过预处理语句可从根本上防御。危害影响服务器端数据。

XSS

以客户端浏览器为目标。主要危害包括 Cookie 窃取和会话劫持。通过输出转义和 CSP 进行防御。危害发生在用户的浏览器中。

分享

相关术语