Web 安全

SQL 注入

约 4 分钟阅读

什么是 SQL 注入

SQL 注入是指用户输入未经妥当处理就被嵌入 Web 应用的数据库查询,导致攻击者能够执行任意 SQL 语句的漏洞。危害可能扩大到窃取、篡改、删除数据库中的全部数据,甚至在服务器上执行操作系统命令。在 OWASP Top 10 中,SQL 注入 (CWE-89) 被归入 Injection 类别:2017 年版以 A1:2017-Injection 位列首位,2021 年版为 A03:2021,2025 年版为 A05:2025。

公开论述经由 Web 注入 SQL 的早期文献之一,是 1998 年 12 月《Phrack Magazine》第 54 期刊登的文章《NT Web Technology Vulnerabilities》。该文以 MS SQL Server 6.5 允许批量执行多条语句为例,指出在把网页输入值直接拼接而成的 SQL 语句后面还能再接上另一条 SQL 语句。距这一提醒已过去四分之一个世纪以上,截至 2026 年 8 月,尽管根本性的对策十分明确,因实现疏漏而残留该漏洞的情况仍层出不穷。

攻击原理与类型

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 等) 执行操作系统层面的命令

在 OWASP 2025 年版 Top 10 的统计中,SQL 注入 (CWE-89) 的报告频率本身低于 Cross-Site Scripting,但作为影响程度较大的漏洞,已登记超过 1 万 4 千个 CVE。WAF 的检测是有效的辅助手段,不过通过巧妙的编码或插入注释绕过 WAF 的手法也已为人所知,它并不能取代根本性的对策。

根本性防御措施

SQL 注入的根本对策十分明确。只要把 SQL 语句的结构与数据分离的实现方式贯彻到底,就能封堵大部分攻击路径。不过正如 OWASP 所提醒的,即使调用方做了参数化,只要存储过程内部的 PL/SQL 或 T-SQL 仍在做字符串拼接、或通过 EXECUTE IMMEDIATE 执行,漏洞依然存在。

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

把 SQL 语句的结构与数据分离,使用户输入不会被当作 SQL 语法来解释。OWASP Top 10 的 Injection 项目同样把不经过解释器的安全 API 与参数化接口列为首选。主流的数据库访问库都提供了相当于预处理语句的机制,因此把用字符串拼接组装查询的地方替换掉是第一步。需要注意的是,表名、列名这类 SQL 的结构部分无法放入占位符,用转义也保护不了。当排序所用的列名等要由用户输入决定时,应当用允许列表把可接受的取值固定下来。在不得不动态组装的地方使用转义,只能定位为封堵无法参数化部分的辅助手段。

运用 ORM

使用 ORM (Object-Relational Mapping) 后,需要直接编写 SQL 的场合减少,SQL 注入的风险也随之降低。不过在使用 ORM 的原始查询功能或自定义查询时,需要与预处理语句同样的注意。

多层防御

  • 最小权限原则:把应用所用数据库账户的权限压到必要的最小限度,只读操作使用只读账户
  • 输入校验:数值字段只接受数值,邮箱字段只接受符合格式的值。这是辅助性的措施,不能取代预处理语句
  • 控制错误信息:不要把数据库的错误信息直接显示给用户,以防止基于错误的 SQL 注入导致信息泄露
  • 漏洞管理:通过定期的安全扫描与代码审查,及早发现 SQL 注入漏洞
  • 安全头部的分工:安全头部是控制浏览器端行为的机制,对在服务器端组装查询的 SQL 注入无效。它承担的是经由同一输入位置进入的其他风险 (例如 XSS)

常见误解

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

SQL 注入与 XSS 的比较

SQL 注入

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

XSS

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

分享

相关术语

相关文章