php isset 「安全攻防」序列化与反序列,你了解多少?

php isset 「安全攻防」序列化与反序列php isset 「安全攻防」序列化与反序列,你了解多少?,你了解多少?

1.序列化与反序列化

首先要了解序列化与反序列化的定义,以及序列化反序列化所用到的基本函数。

序列化:把对象转换为字节序列的过程称为对象的序列化,相当于游戏中的存档。

PHP中的序列化函数()

**()**函数用于序列化对象或数组,并返回一个字符串。()函数序列化对象后,可以很方便的将它传递给其他需要它的地方,且其类型和结构不会改变。

示例:

<?php
highlight_file(__FILE__);
$sites=array('I', 'Like', 'PHP');
echo'
'; var_dump(serialize($sites)); //把这个对象进行序列化 echo'
'; classman{ public$name="xiaocui"; public$sex="man"; private$age=26; } $M=newman();//创建一个对象 var_dump(serialize($M)); //把这个对象进行序列化 ​ ?>

输出结果为:

string(47) "a:3:{i:0;s:1:"I";i:1;s:4:"Like";i:2;s:3:"PHP";}"
string(79) "O:3:"man":3:{s:4:"name";s:7:"xiaocui";s:3:"sex";s:3:"man";s:8:"manage";i:26;}"

参数说明:

数组的序列化:
a 代表一数组  
3 代表数组中有3个元素
i 代表数组的下标
0 代表I元素的下标值
s 代表元素I的数据类型为字符型
1 代表元素I的长度为1
对象的序列化:
O 代表是一个对象
3 代表类名man的长度
3 代表类中的字段数
s 代表属性name的类型为字符型
4 代表属性name的长度
//后面的以此类推,序列化字符串中字段内容以{开始,;}结束

反序列化:把字节序列恢复为对象的过程称为对象的反序列化,相当于游戏中的读档。

【一一帮助安全学习php isset,所有资源免费获取关注我,私信回复“资料”即可一一】

①网络安全学习路线

②20份渗透测试电子书

③安全攻防357页笔记

④50份安全攻防面试指南

⑤安全红队渗透工具包

⑥信息收集80条搜索语法

⑦100个漏洞实战案例

⑧安全大厂内部视频资源

⑨历年CTF夺旗赛题解析

PHP中的反序列化函数()

**()**函数用于将序列化后的字符串在还原为原来的数组或对象的过程。**()**函数可以快速将序列化的字符串还原出来,用来完成它本来的功能。

语法

mixed ( $str )

参数说明

$str: 序列化后的字符串。

返回值

返回的是转换之后的值,可为 、float、、array 或 。不可反序列化时返回FALSE,并抛出提醒。

示例代码:

<?php
highlight_file(__FILE__);
$sites=array('I', 'Like', 'PHP');
echo'
'; echo$ser=serialize($sites).'
'; //把这个对象进行序列化 var_dump(unserialize($ser)); //把序列化的字符串进行反序列化 echo'
'; classman{ public$name="xiaocui"; public$sex="man"; private$age=26; } $M=newman();//创建一个对象 echo$ser=serialize($M).'
'; //把这个对象进行序列化 var_dump(unserialize($ser)); //把序列化的字符串进行反序列化 ​ ?>

输出结果为:

a:3:{i:0;s:1:"I";i:1;s:4:"Like";i:2;s:3:"PHP";}
array(3) { [0]=>string(1) "I"[1]=>string(4) "Like"[2]=>string(3) "PHP"}
​
O:3:"man":3:{s:4:"name";s:7:"xiaocui";s:3:"sex";s:3:"man";s:8:"manage";i:26;}
object(man)#2 (3) { ["name"]=> string(7) "xiaocui" ["sex"]=> string(3) "man" ["age":"man":private]=> int(26) } 

可以看出上述反序列化后的数组或对象,与原数据没有任何变化。

序列化与反序列化在系统中的作用

①把对象的字节序列永久放在磁盘中,需要时可以随时调用,大大节省磁盘占用空间。

②在传输过程中可以直接传输字节序列,而不是对象,这可以大大提高传输速率。

在业务系统中,需要对一些对象进行序列化存储,让他们离开内存空间,存放在一个文件中php isset 「安全攻防」序列化与反序列,你了解多少?,以便持久化保存。例如:在用户注册并登录系统时,会将用户信息如用户名,密码,等信息先通过序列化存储起来,当用户再次登录时将序列化后的字节序列通过反序列化成原对象到内存进行使用,可以大大节省内存开销。

2.魔术方法

PHP将所有以__(两个下划线)开头的类方法保留为魔术方法。所以在定义类方法时,除了上述魔术方法,建议不要以__为前缀。

PHP中常见魔术方法()

具有 函数的类会在每次创建新对象时先调用此方法,适合在使用对象之前做一些初始化工作。

代码示例:

<?php
highlight_file(__FILE__);
classdemo{
public$name="xiaocui";
public$sex="man";
private$age=26;
publicfunction__construct()
{
echo"
"."类被实例化时调用我!"; } } $D=newdemo(); //实例化对象 ​ ?>

输出结果:

类被实例化时调用我!

()

该函数会在到某个对象的所有引用都被删除或者当对象被销毁时执行

代码示例:

<?php
highlight_file(__FILE__);
class demo{
public $name="xiaocui";
public $sex="man";
private $age=26;
public function __construct()
{
echo "
"."类被实例化时调用我!"."
"; } public function num($a,$b){ echo $c = $a + $b.'
'; return $c; } public function __destruct(){ echo "当类中的所有方法都被销毁时调用我!"; } public function person($per){ echo "We are $per !!!".'
'; } } $D=new demo(); //实例化对象 $D->num(5,6); //调用num()方法 $D->person(man); //调用person()方法 ?>

输出结果:

类被实例化时调用我!
11
Weareman!!!
当类中的所有方法都被销毁时调用我!

上述输出结果可以很直观的看到代码的执行顺序:()=>num(5,6)=>()=>()

实例化对象时首先要执行构造方法(),然后接着执行类中的实例num()、(),当所有方法都执行完成销毁时,最后调用析构方法()。

()

在使用()时,会检查是否存在一个()魔术方法。如果存在,则该方法会先被调用,预先准备对象需要的资源。

代码示例:

<?php
highlight_file(__FILE__);
classdemo{
public$name="xiaocui";
protected$sex="man";
private$age=26;
publicfunction__construct()
{
echo"
"."类被实例化时调用我!"."
"; } publicfunction__destruct(){ echo"
"."当类中的所有方法都被销毁时调用我!"."
"; } publicfunction__wakeup() { echo"
"."当反序列时首先调用我 !".'
'; } } $D=newdemo(); //实例化对象 echo$ser=serialize($D); //序列化对象$D var_dump(unserialize($ser)); //反序列化字符串$ser ​ ?>

输出结果:

由于$age为私有属性,在序列化时会在前后加空白字符,原本的字符长度为7,而在两侧加入空白字符则字符长度就会变为9

类被实例化时调用我!
O:4:"demo":3:{s:4:"name";s:7:"xiaocui";s:6:"*sex";s:3:"man";s:9:"demoage";i:26;}
当反序列时调用我 !
object(demo)#2
 (3) { ["name"]=> string(7) "xiaocui" ["sex":protected]=> 
string(3) "man" ["age":"demo":private]=> int(26) }
当类中的所有方法都被销毁时调用我!
​
当类中的所有方法都被销毁时调用我!

上述输出结果可以很直观的看到代码的执行顺序:()=>($D)=>()=>($ser)=>()=>()

实例化对象时首先要执行构造方法(),然后执行序列化($D),然后再反序列化之前要执行()方法,然后执行反序列化($ser),当所有方法都执行完成销毁时最后执行()析构方法,由于反序列化后将原来的序列化字符串还原又执行一次()。

()

()方法用于定义一个类被当成字符串时该如何处理。

示例代码:

<?php
highlight_file(__FILE__);
class demo{
    public $name="xiaocui";
    protected $sex="man";
    private $age=26;
    public function __construct()
    {
        echo "
"."类被实例化时调用我!"."
"; } public function __destruct(){ echo "
"."当类中的所有方法都被销毁时调用我!"."
"; } public function __wakeup() { echo "
"."当反序列时调用我 !".'
'; } public function __toString(){ return "
"."类被当成字符串处理时调用我!"."
"; } } $D=new demo(); //实例化对象 echo $D; //类被当成字符串输出 ?>

输出结果:

类被实例化时调用我!
​
类被当成字符串处理时调用我!
​
当类中的所有方法都被销毁时调用我!

上述输出结果可以看到,当类被当成字符串echo时,()方法被调用并执行。

如果该类中没有()方法,进行echo输出时,PHP会抛出致命性错误,错误如下:

Catchablefatalerror: ObjectofclassdemocouldnotbeconvertedtostringinD:XXXXphpstudy_proWWWtwodemo.phponline30

()

在使用()函数时,程序会检查类中是否存在一个()魔术方法。如果存在,则该方法会先被调用,然后再执行序列化操作。

()方法常用于提交未提交的数据,或类似的清理操作。同时,如果有一些很大的对象,但不需要全部保存,该函数就起到了很好的清理作用。

示例代码:

<?php
highlight_file(__FILE__);
class demo{
    public $name="xiaocui";
    protected $sex="man";
    private $age=26;
    public function __construct()
    {
        echo "
"."类被实例化时调用我!"."
"; } public function __destruct(){ echo "
"."当类中的所有方法都被销毁时调用我!"."
"; } public function __wakeup() { echo "
"."当反序列时调用我 !".'
'; } public function __sleep(){ echo "
"."当序列时调用我 !".'
'; return array("name","sex","age"); //这里必须返回一个数值,里边的元素表示返回的属性名称 } } $D=new demo(); //实例化对象 echo $ser = serialize($D); //序列化对象 ?>

输出结果:

类被实例化时调用我!
当序列时调用我!
O:4:"demo":3:{s:4:"name";s:7:"xiaocui";s:6:"*sex";s:3:"man";s:9:"demoage";i:26;}
当类中的所有方法都被销毁时调用我!

上述输出结果可以看到,当类被序列化时首先调用了()方法,该函数必须返回一个数值。如果该函数没有返回属性的话,序列化时会将属性清空。

()

当尝试以调用函数的方式调用一个对象时,方法会被自动调用。(本特性只在 PHP 5.3.0 及以上版本有效。)

代码示例:

<?php
highlight_file(__FILE__);
class demo{
    public $name="xiaocui";
    protected $sex="man";
    private $age=26;
    public function __construct()
    {
        echo "
"."类被实例化时调用我!"."
"; } public function __destruct(){ echo "
"."当类中的所有方法都被销毁时调用我!"."
"; } public function __wakeup() { echo "
"."当反序列化时调用我 !".'
'; } public function __sleep(){ echo "
"."当序列化时调用我 !".'
'; return array("name","sex","age"); } public function __invoke() { echo "
"."当以函数的方式调用对象时会调用我!".'
'; } } $D=new demo(); //实例化对象 $D(); //以函数的方式调用对象 ?>

结果输出:

类被实例化时调用我!
​
当以函数的方式调用对象时会调用我!
​
当类中的所有方法都被销毁时调用我!

上述结果可以看到当使用函数的方法调用对象时,就会调用()方法.

如果没有类中没有该方法,那么PHP会报出致命性错误,如下:

Fatalerror:
 UncaughtError: 
FunctionnamemustbeastringinD:xxxxxphpstudy_proWWWtwodemo.php:42Stacktrace:
 #0 {main} thrown in D:xxxxxphpstudy_proWWWtwodemo.php on line 42

()

在对象中调用一个不存在或者不可访问方法时,会被调用。

代码示例:

<?php
highlight_file(__FILE__);
class demo{
    public $name="xiaocui";
    protected $sex="man";
    private $age=26;
    public function __construct()
    {
        echo "
"."类被实例化时调用我!"."
"; } public function num($a,$b){ echo "
".$c = $a + $b.'
'; return $c; } public function __destruct(){ echo "
"."当类中的所有方法都被销毁时调用我!"."
"; } public function person($per){ echo "
"."We are $per !!!".'
'; } public function __wakeup() { echo "
"."当反序列化时调用我 !".'
'; } public function __sleep(){ echo "
"."当序列时调用我 !".'
'; return array("name","sex","age"); } public function __call($arg1,$arg2){ echo "
"."当对象调用一个不存在或者不可访问的方法时调用我!".'
'; } } $D=new demo(); //实例化对象 $D->num1(1,2); //调用一个不存在的方法 ?>

结果输出:

类被实例化时调用我!
​
当对象调用一个不存在或者不可访问的方法时调用我!
​
当类中的所有方法都被销毁时调用我!

__set()

给不可访问属性赋值时,__set会被调用。

代码示例:

<?php
highlight_file(__FILE__);
class demo extends demo1{
    public $name="xiaocui";
    protected $sex="man";
    private $age=26;
    public function __construct()
    {
        echo "
"."类被实例化时调用我!"."
"; } public function __destruct(){ echo "
"."当类中的所有方法都被销毁时调用我!"."
"; } public function person($per){ echo "
"."We are $per !!!".'
'; } public function __set($arg1,$arg2){ echo "
"."当给不存在或者不可访问的属性赋值时调用我!"."
"; } } class demo1{ private $weight; public $height; public function people(){ echo $this->weight; echo $this->height; } } $D=new demo(); //实例化对象 $D->weight=74; //给不可访问的属性赋值 ?>

输出结果:

类被实例化时调用我!
当给不存在或者不可访问的属性赋值时调用我!
当类中的所有方法都被销毁时调用我!

()

对不可访问属性调用isset()或empty()时,()会被调用。

()

对不可访问属性调用unset()时,()会被调用。

__get()

读取不可访问属性的值时,__get会被调用。

代码示例:

<?php
highlight_file(__FILE__);
class demo extends demo1{
    public $name="xiaocui";
    protected $sex="man";
    private $age=26;
    public function __construct()
    {
        echo "
"."类被实例化时调用我!"."
"; } public function __destruct(){ echo "
"."当类中的所有方法都被销毁时调用我!"."
"; } public function __get($arg1){ echo "
"."读取不存在或不可访问的属性时调用我!"; } } class demo1{ private $weight = 0; public $height; public function people(){ echo $this->weight; echo $this->height; } } $D=new demo(); //实例化对象 $D->weight; //读取父类中不可访问的属性 ?>

输出结果:

类被实例化时调用我!
读取不存在或不可访问的属性时调用我!
当类中的所有方法都被销毁时调用我!

3.反序列化漏洞3.1 反序列化漏洞利用条件

① unserialize()函数中参数可控
② 存在可利用的类,且类中有魔术方法

代码示例1:

arg1;  //输出用户传递的arg1值
    }
}
$a=$_GET['arg'];     //接收前端传递的arg1变量
$unser = unserialize($a);    //反序列化传递的arg1
?>

上述的代码满足反序列化漏洞的两个条件,arg参数可控,也就是()函数的参数可控;存在可利用的类demo,且demo类中有可利用的魔术方法(),然而()魔术方法中使用echo输出变量了arg。

通过arg参数,构造序列化字符串,通过()函数进行反序列化php issetphp isset,最后通过()魔术方法输出变量,造成XSS。

示例代码2

arg1);  //eval()去执行用户传递的arg1值
    }
}
$a=$_GET['arg'];     //接收前端传递的arg1变量
$unser = unserialize($a);    //反序列化传递的arg1
var_dump($unser);
?>

如果魔术方法中存在eval(),且参数可控,那么通过构造序列化字符串,通过反序列化漏洞造成RCE。

3.2 ()函数绕过

在序列化时传递对象的属性大于实际对象的属性时,()魔术方法将不会被执行,从而导致绕过。

PHP版本

公告:
1. 本站所有资源来源于用户上传和网络,如有侵权请联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系站长处理!
6. 本站不售卖代码,资源标价只是站长收集整理的辛苦费!如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。
7. 站长QQ号码 2205675299

资源库 - 资源分享下载网 » php isset 「安全攻防」序列化与反序列,你了解多少?

常见问题FAQ

关于资源售价和售后服务的说明?
本站所有资源的标价均为本站收集资源的辛苦费,不代表资源本身的价值。软件是高智慧高价值的商品,不可能是白菜价。本站资源标价只是赞助费用,收取的赞助费仅用来维持本站的日常运营!毕竟收集整理资料需要投入云计算资源和站长大量的精力。
代码有没有售后服务和技术支持?
由于代码的运行具有不可预见性,本站不保证代码完整可运行,不提供技术支持和售后服务。 本站原创代码都是站长自己开发的,可以有偿提供技术支持服务。 网站里标明【亲测】的代码都是站长亲测过的,其他的代码由于精力有限,没有一一测试,不能保证代码就一定能够使用,更没有技术支持服务,下载前请自行斟酌。
有没有搭建服务?
由于搭建服务比较费时费力,所以本站除了原创代码外均不提供搭建服务。本站分享代码纯属兴趣爱好,不以盈利为目的,请勿咨询有没有搭建服务,谢谢理解。
链接地址失效了怎么办?
请带上资源链接地址联系客服,工作时间内我们看到后将第一时间回复。
关于解压密码
本站资源一般都没有加密,如果发现需要解压密码的,那么就输入 hao.35dc.com 试试。

发表评论

资源库,由老程序员细心甄别、精心筛选,只为提供优质的源码资源

关于我们 联系我们