返回文章列表
网络安全

什么是 SQL 注入?如何彻底防御 SQL 注入?

筱筱
2025-12-06
3天前
什么是 SQL 注入?如何彻底防御 SQL 注入?

在互联网时代,数据就是核心资产。无论是用户信息、交易记录,还是后台管理权限,都存储在数据库中。如果网站对数据库访问处理不当,就可能被攻击者利用 SQL 注入(SQL Injection) 攻破,之后不仅仅是“可以查看数据库”,其危害是系统性的、多层面的,严重时足以导致整个企业或组织的业务崩溃。

SQL 注入可以说是 Web 安全领域最古老、最危险、也最常见的漏洞之一。

什么是 SQL 注入?

SQL 注入是一种常见的 Web 安全漏洞,它允许攻击者将恶意的 SQL 语句注入到程序原本执行的 SQL 中,从而获取、修改甚至删除数据库中的数据。攻击者通过将恶意的SQL代码插入或“注入”到应用程序的查询字符串中,最终欺骗服务器执行这些恶意SQL命令的行为。 其根本原因是程序没有严格地将用户输入的数据与代码(SQL指令)进行分离。

通俗说:

程序把用户输入“当成数据”,攻击者却让它“变成了指令”。

例如:

SELECT * FROM users WHERE username = '$username' AND password = '$password';

如果程序未做任何过滤,攻击者输入:

username: adminpassword: ' OR 1=1 --

实际执行的 SQL 将变成:

SELECT * FROM users WHERE username='admin' AND password='' OR 1=1 --';

OR 1=1 永远为真,而 -- 会注释掉后续内容,结果——

攻击者无需密码直接登录后台!


SQL 注入的常见类型

联合查询注入(Union-based Injection)

利用 UNION SELECT 合并查询结果,从数据库读取敏感表信息。

?id=1 UNION SELECT username, password FROM users

报错型注入(Error-based Injection)

利用报错信息直接泄露数据库内容,例如 updatexml、extractvalue 等函数。

布尔盲注(Boolean-based Injection)

页面无明显回显,通过判断返回页是否变化来“猜字段”。

时间盲注(Time-based Injection)

利用 SQL 延时函数(如 sleep(5))通过响应时间差获取数据。

堆叠注入(Stacked Queries)

一次请求执行多条 SQL,如:

?id=1; DROP TABLE users;

(部分数据库与驱动不支持)

宽字节注入(宽字节绕过)

利用编码特性(如 GBK)绕过转义逻辑,常见于 PHP + MySQL 早期组合。


SQL 注入能造成什么危害?

数据泄露 - 最直接、最常见的危害

这是 SQL 注入最直接的目的和危害。

  • • 用户数据:用户名、邮箱、手机号、哈希密码、甚至明文密码。
  • • 个人信息:身份证号、住址、银行卡信息等,直接导致严重的个人信息泄露。
  • • 商业机密:公司的客户名单、交易记录、产品配方、源代码、未公开的战略计划等。竞争对手可能利用此漏洞获取这些信息。

数据篡改 - 破坏数据完整性与真实性

攻击者不仅可以“读”,还可以“写”。

  • • 修改数据:恶意修改其他用户的信息,如修改其密码、邮箱,从而接管账户。
  • • 篡改财务数据:在电商、金融平台中,修改订单金额、账户余额、充值记录等。
  • • 污染数据:向数据库中插入大量垃圾、虚假或侮辱性数据,破坏平台内容的真实性,导致运营瘫痪。
  • • 案例:通过 UPDATE 语句将某个商品的价格改为 0 元,或者将管理员账户的密码重置为已知值。

身份绕过与权限提升

  • • 管理员权限获取:通过注入,攻击者可以绕过登录验证,直接以管理员身份登录系统。
  • • 权限提升:普通用户通过注入可以执行本应只有管理员才能执行的操作,访问未授权的功能模块。
  • • 案例:经典的 ' OR 1=1 -- 注入,使登录验证的WHERE条件永远为真,从而绕过密码检查。

数据库服务器被完全控制

这是危害的升级,攻击者不再满足于操作数据库本身。

  • • 执行系统命令:在某些数据库系统(如 MySQL、SQL Server)中,如果配置不当且数据库进程具有足够权限,攻击者可以利用特定函数(如 xp_cmdshell)在服务器上执行任意系统命令。
  • • 案例:通过注入执行 xp_cmdshell('format C:') 或 xp_cmdshell('net user hacker Password123! /add'),后果不堪设想。

文件系统读写

  • • 读取服务器文件:利用如 LOAD_FILE()(MySQL)等功能,读取服务器上的敏感文件,如配置文件(内含数据库密码)、源代码、系统文件(/etc/passwd)等。
  • • 写入文件到服务器:利用如 INTO OUTFILE/INTO DUMPFILE(MySQL)等功能,将恶意文件(如 Webshell)写入服务器的 Web 目录。
  • • 案例:通过注入将一个 PHP 的 Webshell 写入 Web 目录,攻击者便可以通过浏览器远程控制整个服务器。

对业务运行的直接攻击 - 拒绝服务

  • • 资源耗尽:通过执行极其复杂的SQL查询(如笛卡尔积联接),或者利用 WAITFOR DELAY 等函数发起睡眠型攻击,大量消耗数据库的 CPU、内存和连接数资源,导致正常服务无法访问,造成拒绝服务。
  • • 删除数据:执行 DROP TABLE 或 DELETE 语句,清空整个或部分数据库表,导致业务数据完全丢失且难以恢复。
  • • 案例:攻击者注入 '; DROP TABLE users; --,瞬间删除整个用户表,导致业务直接停摆。

波及内网,成为跳板

如果数据库服务器处于内网,且应用程序服务器可以访问内网其他资源,那么攻击者可以利用被攻陷的数据库服务器作为跳板,进一步攻击内网中的其他更敏感的系统(如财务系统、OA 系统等)。


常见的 SQL 注入利用流程(攻防视角)

信息收集

识别系统类型、数据库种类、URL 参数、隐藏请求等。

判断是否可注入

例如访问:

?id=1'

页面报错 → 可疑。页面无变化 → 用布尔注入/时间注入进一步测试。

构造 payload

使用 union select、报错函数、sleep 探测字段数和数据。

数据库指纹识别

MySQL?PostgreSQL?MSSQL?Oracle?每种语法不同。

获取表结构

如 MySQL:

SELECT table_name FROM information_schema.tables;

获取敏感信息

如用户表、密码(注意:如果是明文/弱加密,危害更大)。

写入 WebShell(若权限允许)

MySQL:

select "<?php eval($_POST['cmd']); ?>" into outfile "/var/www/html/shell.php";


真实案例:曾经的“灾难级漏洞”

2012 年:LinkedIn 650 万密码泄露

原因之一是弱输入过滤导致 SQL 注入。

某教育系统泄露数百万学生信息

攻击者通过 URL 参数的 SQL 注入获取全部学生数据。

企业内部系统也中招

后台系统登录框缺少过滤,攻击者轻松登录后台导出数据库。

SQL 注入被 OWASP TOP10 长期列为最高危漏洞之一。


如何彻底防御 SQL 注入?

防御 SQL 注入并不难,关键在于 不相信用户输入


使用准备语句 / 预编译语句(强烈推荐)

无论前后端语言,只要使用 参数化查询,99% SQL 注入都会消失。

常用写法(以 Python + MySQL 为例)

cursor.execute("SELECT * FROM users WHERE id=%s", (user_id,))

Java / PHP / Node.js / Golang 都有类似机制。


永远不要拼接 SQL 字符串

错误写法:

sql = "SELECT * FROM users WHERE id=" + user_input

正确写法:

sql = "SELECT * FROM users WHERE id=%s"


严格限制数据库权限

  • • web 用户应为只读或最小权限
  • • 禁止使用 root 连接数据库
  • • 禁止写文件 / 执行系统命令


过滤和校验输入

适用于不便使用预编译的场景(如传统动态 SQL):

  • • ID 必须是数字
  • • 字段名从白名单选择
  • • 长度限制
  • • 拒绝敏感关键字


禁止显示数据库报错信息

线上环境请关闭 debug,统一使用通用错误提示。


定期安全扫描

使用工具如:

  • • sqlmap(自动化注入测试)
  • • Burp Suite
  • • 企业级代码扫描平台(如 SonarQube、Fortify)


写在最后

SQL 注入永不过时,但可以被彻底避免,数据安全不应仅靠补救,而应从设计开始。

SQL 注入是出现最早、影响最大、被利用最多的 Web 安全漏洞之一。但只要开发者从源头使用 预编译最小权限输入校验,就可以彻底消灭它。

SQL 注入虽然是一个存在多年的老问题,但由于其实施简单、危害巨大,至今仍是网络安全领域的重要威胁。作为开发者,我们有责任编写安全的代码,保护用户数据;作为普通用户,了解这些安全知识也能帮助我们更好地保护自己的信息安全,今天就检查一下你的 Web 服务是否存在 SQL 注入风险吧。

本文内容仅供参考,不构成任何专业建议。使用本文提供的信息时,请自行判断并承担相应风险。

分享文章
合作伙伴

本站所有广告均是第三方投放,详情请查询本站用户协议