PHP数组绕过intval和preg_match的CTF技巧
原题目
<?php
include("flag.php"); // 引入flag文件,flag变量在这里定义
show_source("index.php"); // 显示index.php文件的源码(方便选手查看)
// 判断是否通过GET方式传入了pangoulin参数
if(isset($_GET['pangoulin'])){
$pangoulin = $_GET['pangoulin']; // 获取pangoulin参数的值
// 检查pangoulin中是否包含数字(0-9),如果有则终止程序并输出提示
if(preg_match("/[0-9]/", $pangoulin)){
die("no no no!"); // 包含数字则直接退出
}
// 判断pangoulin转换为整数后是否为真(非0),如果为真则输出flag
if(intval($pangoulin)){
echo $flag; // 满足条件,输出flag
}
}
参数传递与数字过滤 :题目要求通过GET传递pangoulin参数,但参数值不能包含数字字符(0-9),否则会被preg_match拦截并终止脚本。
intval判断逻辑 intval($pangoulin)需要返回非零值才能输出flag。常规字符串(如"abc")经intval转换结果为0,无法满足条件。
数组参数在PHP中的独特特性
使用数组形式传递参数(如?pangoulin[]=value
)时,PHP会将$_GET['pangoulin']
自动解析为数组类型。这种特性在表单处理或API参数传递中较为常见。
数组参数的强制转换问题
调用intval()
对数组参数进行强制转换时,结果会固定返回1
。这是PHP的类型转换机制决定的,数组转换为整数时总是返回1
(非空数组)或0
(空数组)。
// 示例:intval对数组的转换
$val = intval(['a', 'b']); // 结果为1
$emptyVal = intval([]); // 结果为0
preg_match对数组参数的响应
当preg_match()
函数接收到数组参数时,PHP会生成Warning
级别错误,但脚本会继续执行。这与函数预期接收字符串参数的行为不符,但不会像Fatal Error
那样终止程序。
// 示例:preg_match对数组的响应
preg_match('/\d+/', ['a', 'b']);
// 输出:Warning: preg_match() expects parameter 2 to be string, array given
安全建议
处理用户输入时应显式检查变量类型,避免因自动类型转换导致逻辑漏洞。使用is_array()
或filter_input()
函数验证参数类型:
// 类型检查示例
if (is_array($_GET['pangoulin'])) {
// 处理数组逻辑
}
// 使用过滤器验证
$value = filter_input(INPUT_GET, 'pangoulin', FILTER_DEFAULT, FILTER_REQUIRE_SCALAR);
if ($value === null) {
// 非标量参数处理
}
实战利用方法 构造请求URL为:
?pangoulin[]=
- 参数变为空数组
- 绕过数字检测
- intval返回1触发flag输出
题目流程图
技术原理总结
- PHP数组传参需在参数名后加[]
- 类型转换特性:intval(array)→1
- preg_match对非字符串参数的容错处理
// 关键代码逻辑示例
if(isset($_GET['pangoulin'])){
$param = $_GET['pangoulin'];
if(preg_match("/[0-9]/", $param)) die("Blocked");
if(intval($param)) echo $flag;
}
典型应用场景 该技巧适用于需要同时满足:
- 参数值不能包含特定字符
- 需要参数经类型转换后为真值 的CTF题目突破场景。