序列化和反序列化及绕过

  • 前言
  • 序列化和反序列化
    • 序列化
    • 反序列化
    • 反序列化绕过
    • 序列化利用
      • ctf题目实例
        • 攻防世界 unserialize3
        • 攻防世界 Web_php_unserialize
        • ctfshow 月饼杯第一题次夜圆
  • 尾言

前言

本菜鸡本着菜死人不偿命的觉悟,接着迈向了ctf的世界。
废话不多说,今天来谈一下PHP的序列化和反序列化还有一些绕过姿势

序列化和反序列化

序列化

在PHP里面存在一个serialize方法来实现序列化功能。

Serializable {/* 方法 */
abstract public serialize ( ) : string
abstract public unserialize ( string $serialized ) : mixed
}

在官方说明中提供了这个接口的摘要。
接下来用本地实验的例子来说明一下序列化结果的大致格式

<?php
$init=12;
echo serialize($init).'<br />';//序列化整形数据,得到格式为i:12;
$string='test';
echo serialize($string).'<br />';//序列化字符串型数据,得到格式为s:4:"test";
$boolean=false;
echo serialize($boolean).'<br />';//序列化布尔类型数据,得到格式为b:0;
$array = array('0' =>'array');
echo serialize($array).'<br />';//序列化数组类型数据,得到格式为a:1:{i:0;s:5:"array";}
?>


所以,经过试验可以得出:
iinteger代表的是整型的数据,其数据的范围-2147483648~2147483647,而其后面跟的12就是这个变量的值;
sstring代表的是字符串类型的数据,后面跟的4为变量的字符个数,之后跟的是变量的值;
bbool代表的是布尔类型的数据,而布尔类型的数据只有falsetrue两种,返回时只会返回01
aarray代表的是数组类型的数据,可以看到有一个花括号,前面半部分是索引值,代表的是数组索引是从0开始,后面是当前索引位置的数据的类型和值。
关于其他的,就不在这里进行总结,总结几个比较常见的。
当然还有就是PHP语言特性,可以把整个方法或者整个类给序列化,这时的格式就是O开头了。

<?php
/*$init=12;
echo serialize($init).'<br />';
$string='test';
echo serialize($string).'<br />';
$boolean=false;
echo serialize($boolean).'<br />';
$array = array('0' =>'array');
echo serialize($array).'<br />';*/
/*** */
class test
{public $username;public $password;public function __construct($username,$password){# code...$this->username=$username;$this->password=$password;}public function __wakeup(){if ($this->username==='zhangsan'&&this->$password==='123456') {# code...echo "flag{nice!}";}else{echo "stop hacker!";}}
}
$username='zhangsan';
$password='123456';
$a=new test($username,$password);
echo serialize($a);
?>

得到结果

反序列化

既然有了序列化函数serialize,那反序列化函数就能猜出来是unserialize
在这里需要注意的是若被反序列化的变量是一个对象,在成功重新构造对象之后,PHP会自动地试图去调用__wakeup()成员函数(如果存在的话)
也就是说比如在上面的例子中,若加入

$b=serialize($a);
$test=unserialize($b);

那么就会得到

即在检测到这个反序列化对象是个类之后,发现有__wakeup()函数,会执行这个函数。而在源码中是执行了让一个if判断,满足输出指定内容。在这里也可以进行一个修改序列化的值,从而达到相关的目的。

反序列化绕过

序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过__wakeup的执行,并且不会报错,可以被正常反序列化

也就是说,在实际题目中,可以通过修改指定的值使其大于原值,从而达到绕过的目的。
也就是说假如现在有一串这个代码。

<?php
class test
{public $a='flag{nice!}';public function __wakeup(){echo $this->a='go out,hacker!';}public function __destruct(){echo $this->a;}
}
$a='O:4:"test":1:{s:1:"a";s:11:"flag{nice!}";}';
$b=unserialize($a);
?>

大致的题目意思就是有一个类,里面的变量a为flag字符串,然后需要输出,但是在上面说的会调用wakeup函数,导致无法输出flag字符串。即

但是现在需要输出它,所以就可以用上面说的方法来绕过wakeup函数,即构造payload为a=O:4:"test":2:{s:1:"a";s:11:"flag{nice!}";}
此时输出为

从而达到了绕过的想法。

序列化利用

反序列化可以绕过,同样序列化也可以进行利用。
假如现在的代码为

<?php
class a
{public $username;public $password;public function __construct($username,$password){$this->username=$username;$this->password=$password;}public function __wakeup(){if($this->username==='zhangsan'){include('flag.php');echo $flag;  }else{echo 'wrong password';}}}function filter($string){return str_replace('hahaha','heyheyhey',$string);
}
$username='lisi';
$password=$_GET[1];
$ser=filter(serialize(new a($username,$password)));
$test=unserialize($ser);
?>

通过源码知需要绕过wakeup函数里的if判断,然后执行语句,但是username变量值被写死,因此这时候就可以利用序列化进行操作。
首先对类进行序列化查看一下

发现本应该是hahaha的变成了heyheyhey
然后构造一下payload的一部分:";s:8:"username";s:8:"zhangsan";}共30个字符,然后字符替换是有3个字符,所以应该构造最终payload为:hahahahahahahahahahahahahahahahahahahahahahahahahahahahahahaha";s:8:"username";s:8:"zhangsan";}
运行结果

发现username值被成功改为zhangsan。说明成功。
所以效果最终为:

注意:如果在本地实验中发现修改之后页面提示错误的,可以在源码里加一个函数
function mb_unserialize($serial_str) {$out = preg_replace('!s:(\d+):"(.*?)";!se', "'s:'.strlen('$2').':\"$2\";'", $serial_str );
return unserialize($out);
}

是在报 unserialize(): Error at offset 124 of 181 bytes in错误时可以尝试这个自建函数来进行实验。

ctf题目实例

攻防世界 unserialize3

打开题目,发现源码

class xctf{public $flag = '111';
public function __wakeup(){exit('bad requests');
}
?code=

所以,根据上面讲的,可以直接将flag字符串那一列进行序列化,然后修改值得到flag。
先序列化得到O:4:"xctf":1:{s:4:"flag";s:3:"111";},修改得O:4:"xctf":2:{s:4:"flag";s:3:"111";}

攻防世界 Web_php_unserialize

打开题目

同样,修改一下,进行序列化,然后O:4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";},然后修改得到O:+4:"Demo":2:{s:10:"Demofile";s:8:"fl4g.php";},这里注意还需要一次base64编码才能得到。

ctfshow 月饼杯第一题次夜圆

具体源码和上面那个序列化利用是一样的,也可以说上面的序列化利用中举的例子就是这个题目,按照上面得方法,构造最终payload为:?1=FirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebasky";s:8:"password";s:5:"yu22x";},提交得到flag。

尾言

还是经常说的那句话,自己总结的只是一些入门的东西,更加深刻得方面需要慢慢学习下去,努力下去,一切都有可能,加油。

PHP序列化及反序列化绕过相关推荐

  1. python序列化和反序列化_python反序列化免杀

    在日常的渗透行动当中,当我们对目标进行内网横向渗透时很不幸的是内网一般往往都会部署防火墙.流量监控等设备,杀软更是成为了服务器的标配,所以如何进行免杀绕过杀毒软件的限制让主机上线成了我们首要解决的问题 ...

  2. php反序列化绕过,【技术分享】PHP反序列化漏洞

    前言 序列化给我们传递对象提供了一种简单的方法serialize()将一个对象转换成一个字符串unserialize()将字符串还原为一个对象.此类函数的使用本身没有危害,但是传入反序列化函数的字符串 ...

  3. PHP序列化与反序列化(__sleep与__wakeup)

    前言 总结一下序列化和反序列化的入门知识主要介绍__sleep与__wakeup 简单介绍 1.序列化 将一个对象转换为字符串 2.反序列化 将一个字符串恢复成对象 3.常见魔术方法 __constr ...

  4. php反序列化绕过,浅谈php反序列化漏洞

    关于php的反序列化漏洞要先说到序列化和反序列化的两个函数,即: serialize() 和unserialize(). 简单的理解: 序列化就是将一个对象变成字符串 反序列化是将字符串恢复成对象 这 ...

  5. ctf中的php序列化与反序列化

    ctf中的php序列化与反序列化 刚开始学的php序列化与反序列化,有点雨里雾里的,于是做个笔记~~ 首先我们来了解一下概念知道他是怎么样的一个东西: 序列化(串行化):是将变量转换为可保存或传输的字 ...

  6. 【CTF】buuctf web(三)——PHP序列化与反序列化

    知识点 后台目录扫描工具:dirsearch 魔术方法wakeup()绕过:当成员属性数目大于实际数目时可绕过wakeup方法(CVE-2016-7124) 常见的备份文件后缀名:.git .svn ...

  7. PHP之序列化与反序列化(基础篇)

    可利用的序列化与反序列化是在php中常见的一种漏洞,那为什么会出现序列化与反序列化漏洞呢?这就和php魔术方法有关系了,如果有还对魔术方法不太明白的可以看我上一篇文章PHP之魔术方法_errorr0的 ...

  8. 序列化和反序列化刷题记录

    BUU CODE REVIEW\ *反序列化 md5 <?php /*** Created by PhpStorm.* User: jinzhao* Date: 2019/10/6* Time: ...

  9. [Java]LeetCode297. 二叉树的序列化与反序列化 | Serialize and Deserialize Binary Tree

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★ ➤微信公众号:山青咏芝(shanqingyongzhi) ➤博客园地址:山青咏芝(https://www.cnblog ...

最新文章

  1. 【运营】盘点2014,有哪些O2O名牌被撕。
  2. php 安装pdo odbc,关于PHP安装扩展pdo_odbc
  3. 从AndroidStudio同步上传项目代码到GitHub
  4. python tkinter图片为什么要设置全局变量_为什么这里一定要设置全局变量
  5. C++头文件和源文件,编译过程
  6. html怎么用小小的图片铺满作为背景,多种背景图片随机切换的应用
  7. Maven项目出现web.xml is missing and 《failOnMissingWebXml》is set to true,已解决
  8. vCenter6.0配置一:配置分布式交换机
  9. android http 图片上传,Android okHttp上传图片
  10. python 合并不同文件夹下名称相同的文件
  11. 详解 ManualResetEvent(转)
  12. Windows优化远程连接速度
  13. |- 微信 -| 网页授权登录
  14. redis之复制之谜(二)
  15. css样式表诞生,[css]简明教程 CSS样式表概述
  16. Google 出的 Guava 是个什么鬼?
  17. VUE 创建组件并且引用
  18. java.sql.SQLException: ORA-00911: 无效字符(编译器大坑)
  19. 杭州seo优化月底工作总结
  20. 安装ao 服务器为空,如何在64位Windows操作系统中安装现场审计实施系统AO2011

热门文章

  1. mysql最大公约数_什么是最大公约数和最小公倍数?
  2. 欧姆龙PLC ST语言6轴伺服RS232C通讯板CP1W-C IF0 真实项目程序,ST语言写的FB块
  3. Word2Vec 算法详解
  4. python猴子吃桃问题_「每日一练」巧用python计算猴子吃桃问题
  5. Targeted Supervised Contrastive Learning for Long-Tailed Recognition(2022.5.14)
  6. UVa145 Gondwanaland Telecom
  7. 2016年上海面试记
  8. 上海人才大数据 | 上下班1小时,年薪30万(附图表)
  9. 刚毕业年薪40w......程序员薪资天花板?
  10. 制作实体图、流程图、er图的工具ProcessOn的简单使用说明附截图