CTF中preg_match函数的利用技巧

CTF赛场上,preg_match往往是把握关键权限的刀锋。它的匹配结果直接决定了后端逻辑的分支,稍有不慎就会让payload化为乌有。于是,熟悉其正则语法、PCRE特性以及PHP对输入的预处理方式,成为选手们在逆向题目中抢占先机的必修课。

正则表达式的核心要点

PCRE引擎支持的断言((?=...)(?!...))以及字符类的细粒度控制,是构造“看似合法、实则匹配”模式的基石。忽略大小写可通过i修饰符实现,而s则让点号匹配换行,常被用来跨行捕获。

常见的绕过技巧

  • 利用x00插入空字符,迫使trimstrlen误判长度。
  • 在字符类中混入[:punct:][:graph:]等 POSIX 类,扩大匹配范围,却不破坏整体结构。
  • 用非捕获分组(?:...)隐藏冗余子表达式,防止$match数组膨胀导致后续检查失效。

实战案例分析

某题给出的代码片段如下:

<?php
$key = 'KEY{********}';
$IM = preg_match("/key.*key.{4,7}key://.//(.*key)[a-z][[:punct:]]/i", trim($_GET["id"]), $match);
if ($IM) { die('key is: '.$key); }
?>

要让$IM为真,只需让正则成功捕获任意子串。一个常用的payload是:

http://example.com/vuln.php?id=keyABCkey12345key:/x/foobarkeyb!

这里keyABCkey12345key满足key.*key.{4,7}key的长度要求,随后:/x/foobar填补.//的占位,最后的b!匹配[a-z][[:punct:]]。一旦匹配成功,die立即泄露KEY{...}

细节决定成败:若在浏览器地址栏直接输入#?id=后留空,trim会去掉所有空白,导致正则匹配失败;而在payload中加入%00则可以制造隐藏字符,使得strlen判断仍为非零,却让正则看到完整模式。

参与讨论

0 条评论

    暂无评论,快来发表你的观点吧!