WAF / 过滤绕过篇(进阶核心)

约 9 分钟读完

WAF / 过滤绕过篇(进阶核心)

在SQL注入实战中,WAF(Web应用防火墙)、应用层过滤是最常见的拦截障碍——即使发现注入漏洞,若无法绕过过滤规则,也无法实现漏洞利用。本篇章聚焦“进阶绕过”,从常见过滤规则解析、通用绕过手法拆解、分层绕过思路落地三个核心维度,结合实战场景补充细节、Payload案例,帮助掌握可直接复用的绕过技巧,突破拦截限制,完成注入闭环。

1. 常见过滤规则(知己知彼,精准突破)

过滤规则是WAF、应用程序拦截注入Payload的核心依据,不同系统的过滤规则差异较大,但核心可归纳为4大类,需先明确目标的过滤范围,才能针对性设计绕过方案(实战中可通过“逐步测试法”判断过滤规则:依次输入关键字、符号、函数,观察页面是否拦截,确定被过滤的内容)。

1.1 关键字过滤(最核心、最常见)

核心拦截SQL注入相关的关键字,阻止恶意SQL语句的拼接与执行,是应用层过滤和WAF的首要拦截点,常见被过滤关键字分为3类:

  • 查询类关键字:select(查询数据)、union(联合查询核心)、from(指定查询表)、where(指定查询条件)—— 主要拦截联合查询、报错注入、盲注的核心语句;

  • 系统信息查询关键字:information_schema(MySQL系统数据库,存储库、表、字段信息)、database()(查询当前库名)、version()(查询数据库版本)—— 阻止攻击者获取数据库基础信息,切断注入的“信息收集”环节;

  • 操作类关键字:insert(插入数据)、update(修改数据)、delete(删除数据)、drop(删除表)、grant(赋予权限)—— 主要拦截堆叠注入的恶意操作,降低漏洞危害。

补充说明:部分过滤规则会拦截“关键字完整匹配”,部分会拦截“关键字片段”(如拦截sele,则selectselectxxx均会被拦截);部分会区分大小写(仅拦截小写select,不拦截大写SELECT),需实战中逐一验证。

1.2 符号过滤(阻断SQL语法闭合)

SQL语句的语法依赖特殊符号实现闭合、注释、逻辑判断,符号过滤的核心目的是“破坏恶意SQL的语法完整性”,使Payload无法正常执行,常见被过滤符号及拦截目的:

  • 闭合类符号:单引号(')、双引号(")—— 注入Payload需通过单/双引号闭合后台SQL语句的原有语法(如id=1' and 1=1--+),过滤后无法完成闭合,Payload失效;

  • 注释类符号:--(MySQL单行注释)、#(MySQL单行注释)、/* */(多行注释)—— 注释符号用于“注释掉后台SQL语句中多余的内容”(如注释掉闭合后的单引号、多余的查询条件),过滤后会导致SQL语法错误,无法执行;

  • 逻辑/比较类符号:=(等于)、>(大于)、<(小于)、and(逻辑与)、or(逻辑或)—— 主要拦截盲注(布尔盲注、时间盲注)的条件判断语句(如length(database())=5ascii(substr(...))>100)。

1.3 函数过滤(拦截注入核心工具)

SQL注入依赖各类函数实现信息猜解、报错触发、延迟判断,函数过滤的核心是“禁用注入所需的关键函数”,使攻击者无法构造有效的恶意Payload,常见被过滤函数分为3类:

  • 盲注相关函数:sleep()(时间盲注延迟)、benchmark()(时间盲注替代延迟)、length()(猜解长度)、substr()(截取字符)、ascii()(字符转ASCII码)—— 直接阻断布尔盲注、时间盲注的核心逻辑;

  • 报错注入相关函数:extractvalue()updatexml()(MySQL报错注入核心函数)、floor()(报错注入替代函数)—— 阻止通过报错带出敏感数据;

  • 其他关键函数:concat()(字符串拼接)、char()(ASCII码转字符)、load_file()(读取文件)、into outfile()(写入文件)—— 拦截Payload的字符串构造、文件操作相关功能。

1.4 请求特征拦截(WAF专属,精准识别恶意请求)

除了关键字、符号、函数过滤,WAF会通过“请求特征”识别恶意注入请求,无需解析Payload内容,直接拦截异常请求,常见拦截特征:

  • 异常参数特征:参数中包含“连续特殊符号”(如'';;)、“异常拼接格式”(如id=1' and 1=1)、“不符合业务逻辑的参数值”(如业务上id仅为数字,参数却为id=1');

  • Payload特征:匹配WAF内置的注入Payload规则库(如union select 1,2,3updatexml(1,concat(...),1)等常见Payload),即使修改关键字大小写,也可能因特征匹配被拦截;

  • 请求行为特征:短时间内同一IP发送大量包含敏感内容的请求、请求头异常(如缺失Referer、User-Agent)、参数长度异常(Payload过长)。

2. 通用绕过手法(实战可复用,一招破万法)

通用绕过手法是突破各类过滤规则的基础,核心思路是“不改变Payload功能,仅修改Payload的表现形式”,避开过滤规则的拦截,以下7种手法覆盖90%以上的基础过滤场景,结合案例拆解,可直接复用。

2.1 大小写混淆(最简单、最易上手)

核心原理:应用层过滤、部分WAF仅拦截“纯小写/纯大写关键字”,而MySQL、MSSQL等数据库对SQL关键字的大小写不敏感(如selectSelECtSELECT执行效果完全一致),通过大小写交替,避开关键字的完整匹配过滤。

实战案例(针对selectunion过滤):

  • 原始Payload(被拦截):id=-1 union select 1,database(),3--+

  • 绕过Payload(可用):id=-1 UNioN SelECt 1,database(),3--+

  • 关键技巧:重点修改关键字的中间字符(如select改为SelEctsElEcT),避免仅修改首字母(部分过滤规则会拦截“首字母大写”的关键字);对于多关键字组合,需同时修改所有被过滤关键字(如同时修改unionselect)。

局限性:仅适用于“不区分大小写的过滤规则”,若WAF/应用层过滤“关键字片段”(如拦截sele),则大小写混淆无效。

2.2 注释穿插(突破关键字完整匹配)

核心原理:在被过滤的关键字中间,插入数据库支持的注释符号,将关键字“拆分”,避开过滤规则的“完整关键字匹配”,同时数据库解析SQL语句时,会自动忽略注释内容,不影响Payload的执行。

常用注释符号(可穿插使用):

  • 多行注释:/**/(最通用,MySQL、MSSQL均支持);

  • 空字符注释:%00(URL编码后的空字符,MySQL支持,插入后会截断关键字后续内容,需谨慎使用);

  • 特殊注释:/*!*/(MySQL内联注释,后续单独讲解,此处可作为穿插注释使用)。

实战案例(针对selectunioninformation_schema过滤):

  • 原始Payload(被拦截):id=-1 union select 1,group_concat(table_name) from information_schema.tables--+

  • 绕过Payload(可用):id=-1 uni/**/on sel/**/ect 1,group_concat(table_name) fro/**/m info/**/rmation_schema.tab/**/les--+

  • 关键技巧:注释穿插位置无固定要求,优先插入关键字的中间位置(如select插入为sel/**/ect),避免插入关键字的首尾(如/**/select,可能仍被识别为完整关键字);对于长关键字(如information_schema),可多插入几处注释,进一步拆分。

2.3 编码绕过(突破字符、关键字过滤)

核心原理:将Payload中的敏感内容(关键字、符号、函数)进行编码,转换为另一种格式,WAF/应用层过滤若未对编码内容进行解码,则无法识别敏感内容,而数据库/应用程序会自动解码,执行Payload。

常用编码方式(按实战优先级排序),重点掌握前2种:

(1)URL编码(最通用,优先使用)

将敏感字符转换为URL编码格式(%+ASCII码),适用于GET/POST参数中的敏感内容,浏览器、应用程序会自动解码,MySQL会直接识别解码后的内容。

常用敏感字符的URL编码:

  • 单引号('):%27;双引号("):%22

  • 空格:%20=%3D>%3E<%3C

  • 关键字片段编码:如selecte编码为%65,可拼接为sel%65ct,避开完整关键字过滤。

实战案例(针对单引号、select过滤):

  • 原始Payload(被拦截):id=1' and select 1=1--+

  • 绕过Payload(可用):id=1%27 and sel%65ct 1%3D1--+

(2)双重URL编码(突破URL解码过滤)

若目标对参数进行了一次URL解码,且过滤规则仅针对解码后的内容,可对敏感字符进行“双重URL编码”(如单引号'→第一次编码%27→第二次编码%2527),应用程序解码一次后,仍为编码格式,避开过滤,数据库执行时再自动解码。

实战案例(针对单引号过滤,且目标有一次URL解码):

  • 原始Payload(被拦截):id=1%27 and 1=1--+(一次编码后仍被过滤);

  • 绕过Payload(可用):id=1%2527 and 1=1--+(双重编码,解码一次后为%27,避开过滤)。

(3)十六进制编码(针对字符串、符号过滤)

将字符串、敏感符号转换为十六进制格式,MySQL支持直接识别十六进制字符串(前缀加0x),适用于单引号、关键字被过滤,无法直接闭合语法的场景。

实战案例(针对单引号、admin字符串过滤):

  • 原始Payload(被拦截):id=1' and username='admin'--+

  • 绕过Payload(可用):id=1 and username=0x61646D696E--+0x61646D696Eadmin的十六进制编码,无需单引号闭合)。

(4)Unicode编码(补充,针对特殊过滤)

将敏感字符转换为Unicode编码(如selects转换为\u0073),适用于应用层过滤针对ASCII字符,未对Unicode编码进行过滤的场景,实战中使用频率较低,可作为备用方案。

2.4 等价函数替换(突破函数、符号过滤)

核心原理:当某类函数、符号被过滤时,使用功能完全一致(或效果等价)的函数、符号替代,不改变Payload的核心逻辑,同时避开过滤规则,这是突破“函数过滤”的核心手法。

实战常用等价替换表(直接复用,重点记忆):

  • 截取字符函数(替代substr):mid()(功能完全一致,mid(database(),1,1)等价于substr(database(),1,1))、substring()(与substr完全等价)、left()(截取左侧字符,left(database(),1)等价于substr(database(),1,1));

  • 延迟函数(替代sleep):benchmark(count, expr)(重复执行expr函数count次,达到延迟效果,如benchmark(1000000, md5('123')),延迟约1-2秒);

  • 比较符号(替代=><):like(等价于=username like 'admin'等价于username='admin')、regexp(正则匹配,等价于=username regexp 'admin'等价于username='admin')、between and(替代><length(database()) between 5 and 5等价于length(database())=5);

  • 逻辑符号(替代andor):&&(等价于and)、||(等价于or);

  • 字符串拼接函数(替代concat):concat_ws()(按分隔符拼接,concat_ws(':',username,password)等价于concat(username,':',password))、group_concat()(多结果拼接,可替代concat用于多数据查询)。

实战案例(针对substrsleep=过滤):

  • 原始Payload(被拦截):id=1' and if(ascii(substr(database(),1,1))=116, sleep(5), 0)--+

  • 绕过Payload(可用):id=1' && if(ascii(mid(database(),1,1)) like 116, benchmark(1000000, md5('123')), 0)--+

2.5 空格替换(突破空格过滤)

核心原理:SQL语句中,空格用于分隔关键字、参数、函数,若空格被过滤,可使用数据库支持的“空白字符”或“语法结构”替代空格,不影响SQL语句的解析执行,同时避开空格过滤规则。

常用空格替代方案(按兼容性排序):

  • /**/:多行注释,最通用,可替代所有空格(如select/**/1,2,3等价于select 1,2,3);

  • URL编码空白字符:%09(制表符)、%0a(换行符)、%0b(垂直制表符)、%0c(换页符),MySQL、MSSQL均支持,需进行URL编码后传入;

  • 括号():利用SQL语法特性,在函数、关键字后添加括号,替代部分空格(如select(1)from(admin)等价于select 1 from admin);

  • 其他符号:+(部分数据库支持,如MSSQL,select+1+from+admin等价于select 1 from admin)。

实战案例(针对空格过滤):

  • 原始Payload(被拦截):id=-1 union select 1,database(),3--+

  • 绕过Payload(可用):id=-1%0aunion%0aselect%0a1,database(),3--+%0a替代空格);

  • 备选Payload(可用):id=-1union/**/select(1),database(),(3)--+/**/+括号组合替代空格)。

2.6 字符串拼接(突破关键字、字符串过滤)

核心原理:当关键字、敏感字符串(如selectadmin)被完整过滤时,将关键字拆分为多个片段,通过字符串拼接函数拼接为完整关键字,数据库执行时会自动拼接,形成有效SQL语句,避开过滤规则。

常用拼接方式(2种,结合使用效果更佳):

(1)concat()函数拼接(最通用)

将关键字拆分为多个字符串片段,通过concat()拼接,适用于关键字被完整过滤,片段未被过滤的场景。

实战案例(针对selectunion过滤):

  • 原始Payload(被拦截):id=-1 union select 1,2,3--+

  • 绕过Payload(可用):id=-1 concat('uni','on') concat('sel','ect') 1,2,3--+

(2)char()函数拼接(突破符号、字符串过滤)

char()函数可将ASCII码转换为对应字符,将关键字、敏感符号的ASCII码传入char(),拼接为完整内容,适用于单引号、关键字同时被过滤的场景(无需直接输入关键字、符号)。

实战案例(针对select、单引号过滤):

  • 已知:s的ASCII码是115,e是101,l是108,e是101,c是99,t是116;

  • 原始Payload(被拦截):id=1' and select 1=1--+

  • 绕过Payload(可用):id=1 and char(115,101,108,101,99,116) 1=1--+char(115,101,108,101,99,116)等价于select)。

(3)hex()编码拼接(补充)

将字符串转换为十六进制,结合unhex()函数解码拼接,适用于关键字、符号被严格过滤的场景,如unhex(hex('sel')+hex('ect'))等价于select

2.7 内联注释(MySQL专属,突破严格过滤)

核心原理:内联注释是MySQL的专属语法,格式为/*!SQL语句*/,MySQL会将注释内的SQL语句当作正常语句执行,而其他数据库会当作注释忽略;同时,WAF/应用层过滤若未识别内联注释格式,会将注释内的关键字当作注释内容,不进行拦截——这是突破MySQL环境下严格过滤的“杀招”。

进阶技巧:内联注释中可添加MySQL版本号(如/*!50001select*/),仅当MySQL版本≥5.0.01时执行,可进一步避开WAF的特征匹配(部分WAF会拦截无版本号的内联注释)。

实战案例(针对selectunionsleep严格过滤,MySQL环境):

  • 原始Payload(被拦截):id=-1 union select 1,database(),sleep(5)--+

  • 绕过Payload(可用):id=-1 /*!union*/ /*!select*/ 1,/*!database()*/,/*!sleep(5)*/--+

  • 进阶Payload(可用):id=-1 /*!50001union*/ /*!50001select*/ 1,/*!50001database()*/,/*!50001sleep(5)*/--+(添加版本号,提升绕过成功率)。

局限性:仅适用于MySQL数据库,MSSQL、Oracle不支持内联注释语法,无法使用。

3. 分层绕过思路(进阶核心,突破复杂拦截)

实战中,单纯的“通用绕过手法”往往无法突破复杂过滤(如WAF+应用层双重过滤、多层编码+关键字片段过滤),此时需采用“分层绕过思路”——明确过滤规则的分层,针对性突破每一层的拦截,最后组合手法,构造可执行的Payload。

过滤规则分为3层(从外到内,依次拦截),绕过顺序为“从外到内,逐层突破”,最终实现Payload正常执行。

3.1 第一层:参数接收端(应用层过滤,最外层)

这是应用程序自身实现的过滤(而非WAF),通常在“参数接收、验证”阶段,对用户输入的参数进行过滤、转义,核心特点是“过滤规则相对简单,可通过基础手法绕过”,常见过滤方式及绕过思路:

  • 常见过滤方式:关键字替换(如将select替换为空字符串)、符号转义(如将单引号'转义为\')、长度限制(限制参数长度,截断Payload);

  • 绕过思路:

    1. 关键字替换过滤:使用注释穿插、大小写混淆、字符串拼接绕过(如将select改为sel/**/ect,避免被完整匹配替换);

    2. 符号转义过滤:使用宽字节注入(MySQL+GBK编码,%df'吃掉转义符\)、十六进制编码(无需单引号闭合)绕过;

    3. 长度限制过滤:精简Payload(使用短函数、简化语法)、分段注入(将Payload拆分为多个参数,拼接执行)。

实战案例(应用层过滤select、转义单引号):

  • 过滤规则:将select替换为空,单引号'转义为\'

  • 绕过Payload:id=1%df' and /*!sel*/ect 1=1--+%df'吃掉转义符,/*!sel*/ect避开关键字替换)。

3.2 第二层:WAF/IDS/IPS 规则(中间层,最严格)

这是最核心的拦截层,WAF(或IDS/IPS)会对请求的URL、参数、请求头进行全面检测,匹配内置的恶意特征库,拦截异常请求,核心特点是“过滤规则复杂,特征匹配严格”,绕过思路核心是“避开WAF的特征匹配”:

  • 绕过核心思路:

    1. 特征混淆:使用内联注释、注释穿插、大小写混淆,修改Payload的特征,避免匹配WAF内置Payload库(如将union select 1,2,3改为/*!union*/ /*!select*/ (1),(2),(3));

    2. 编码绕过:使用双重编码、十六进制编码,将敏感内容编码,使WAF无法识别(如单引号'改为%2527,双重URL编码);

    3. 请求特征伪装:修改请求头(添加正常的Referer、User-Agent)、控制请求频率(避免短时间大量请求)、拆分Payload(将Payload拆分为多个参数,拼接执行),伪装成正常请求;

    4. 特征绕过:利用WAF的规则缺陷,添加无关字符、冗余语法,干扰WAF的特征匹配(如在Payload中添加/*abc*/1=1等冗余内容)。

实战案例(WAF拦截union selectsleepPayload):

  • WAF特征库:拦截union selectsleep(5)等常见Payload;

  • 绕过Payload:id=-1 /*!50001uni*/on/*abc*/ /*!50001sel*/ect 1,2,/*!50001benchmark*/(1000000,md5('123'))--+(内联注释+冗余注释+等价函数,避开WAF特征)。

3.3 第三层:数据库解析层特性(最内层,最终突破)

这是最后一层拦截,即使Payload绕过了应用层和WAF,若不符合数据库的解析特性,也无法执行——核心思路是“利用数据库的语法特性,调整Payload格式,确保数据库能正常解析执行”,常见数据库特性及利用:

  • MySQL特性:内联注释(/*!SQL语句*/)、宽字节编码(GBK编码%df')、十六进制识别(0x前缀)、函数兼容性(mid()substr()等价);

  • MSSQL特性:waitfor delay(延迟函数,替代sleep)、+号拼接字符串、注释符号--/* */兼容;

  • Oracle特性:dbms_lock.sleep()(延迟函数)、字符串拼接||、注释符号--

  • 绕过思路:根据目标数据库类型,利用其专属语法特性,调整Payload格式(如MySQL用内联注释,MSSQL用waitfor delay),确保Payload能被数据库正常解析,同时避开前两层过滤。

3.4 多层组合绕过 Payload 构造(实战落地,核心重点)

复杂场景下(应用层+WAF双重过滤),单一绕过手法无效,需“组合多种手法”,逐层突破,构造可执行的Payload,核心构造流程(实战可直接套用):

  1. 第一步:测试过滤规则。依次输入关键字(selectunion)、符号('=)、函数(sleepsubstr),观察页面是否拦截,确定每一层的过滤内容(如应用层过滤select,WAF过滤sleep,数据库是MySQL);

  2. 第二步:设计分层绕过方案。针对每一层的过滤,选择对应的绕过手法(应用层用注释穿插,WAF用内联注释+等价函数,数据库用MySQL特性);

  3. 第三步:组合手法,构造Payload。将各层的绕过手法组合,确保Payload能绕过所有过滤,且能被数据库解析执行;

  4. 第四步:验证Payload。逐步调整Payload格式(如修改注释位置、调整等价函数),测试是否能正常执行(如时间盲注观察延迟,报错注入观察报错信息),直至成功绕过。

实战组合案例(复杂场景):

  • 场景:应用层过滤selectunion,WAF过滤sleepsubstr,数据库是MySQL(GBK编码),单引号被转义;

  • 分层绕过方案:

    • 应用层过滤:注释穿插+大小写混淆;

    • WAF过滤:内联注释+等价函数(mid替代substrbenchmark替代sleep);

    • 单引号转义:宽字节%df'

    • 数据库特性:MySQL内联注释、GBK宽字节。

  • 最终组合Payload:id=1%df' && /*!if*/(ascii(/*!mid*/(database(),1,1))like116,/*!benchmark*/(1000000,md5('123')),0)--+

  • 验证:若请求延迟1-2秒,说明绕过成功,Payload正常执行。

4. 绕过实战注意事项(避坑关键)

  • 逐步测试,精准定位:不要直接使用复杂Payload,先逐步测试被过滤的内容(关键字、符号、函数),明确过滤规则后,再设计绕过方案,避免盲目尝试导致IP被封禁;

  • 适配数据库类型:不同数据库的语法、特性不同,绕过手法需针对性调整(如MySQL用内联注释,Oracle不可用),避免因数据库不兼容导致Payload失效;

  • 控制请求频率:WAF会检测“短时间大量异常请求”,测试、绕过过程中,需控制请求间隔(如每3-5秒发送一次请求),避免IP被封禁;

  • 备用方案准备:若某一种绕过手法失效,需准备备用方案(如sleep被过滤,用benchmark替代;注释穿插被过滤,用编码绕过),灵活调整;

  • 合法性提醒:所有绕过、注入操作,仅用于合法的渗透测试场景,需提前获得目标授权,严禁用于非法攻击,否则将承担相应法律责任。

    (注:文档部分内容可能由 AI 生成)

← windows内网渗透常用的60个命令,以及使用技巧,w字解析 2025年安全团队必备的40款开源安全工具 →