【PHP】反序列化漏洞(又名“PHP对象注入”)

9 篇文章 0 订阅
7 篇文章 0 订阅

相关函数

在利用这个漏洞之前我们要先了解相关的函数都有什么,弱点在哪里

看不懂下面的不要紧

后面我会慢慢解释
在这里插入图片描述
在这里插入图片描述
unserialize() 对单一的已序列化的变量进行操作,将其转换回 PHP 的值。返回的是转换之后的值,可为 integer、float、string、array 或 object。如果传递的字符串不可解序列化,则返回 FALSE。与之相对的函数serialize()序列化函数。

掌握语言的最好方法就是自己动手敲
我们举个例子

<?php
//序列化一个数组
$sites = array('Google', 'Runoob', 'Facebook');
$serialized_data = serialize($sites);
echo  $serialized_data;
//a:3:{i:0;s:6:"Google";i:1;s:6:"Runoob";i:2;s:8:"Facebook";}

//序列化一个字符串
$str='hello world';
echo serialize($str);
//s:11:"hello world";

//序列化一个类
class xctf{
    public $flag = '111';
    public function __wakeup(){
    exit('bad requests');
    }
}
$a=new xctf;
echo serialize(($a));
//O:4:"xctf":1:{s:4:"flag";s:3:"111";}
?>

s:16代表这个是字符串,字符串长度为16,a:3代表这个是数组,有三个数值。O代表对象,xctf是类名,flag是类实例化后的对象名

下面详细说一下序列化对象的内容

序列化一个对象将会保存对象的所有变量,但是不会保存对象的方法,只会保存类的名字。所以对象A和对象B序列化后并没有什么区别。

O:<length>:"<class name>":<n>:{<field name 1><field value 1>...<field name n><field value n>} 

O:表示序列化的事对象
< length>:表示序列化的类名称长度
< class name>:表示序列化的类的名称
< n >:表示被序列化的对象的属性个数
< field name 1>:属性名
< field value 1>:属性值

unserialize()函数能够重新把字符串变回php原来的值。

漏洞成因

PHP__wakeup()函数漏洞

在程序执行前,serialize() 函数会首先检查是否存在一个魔术方法 __sleep.如果存在,__sleep()方法会先被调用, 然后才执行串行化(序列化)操作。这个功能可以用于清理对象,并返回一个包含对象中所有变量名称的数组。如果该方法不返回任何内容,则NULL被序列化,导致 一个E_NOTICE错误。

与之相反,unserialize()会检查是否存在一个__wakeup方法。如果存在,则会先调用 __wakeup方法,预先准备对象数据。但是这个wakeup()是可以被绕过的

漏洞的根源在于unserialize()函数的参数可控。如果反序列化对象中存在魔术方法,而且魔术方法中的代码有能够被我们控制,漏洞就这样产生了,根据不同的代码可以导致各种攻击,如代码注入、SQL注入、目录遍历等等。

__wakeup 触发于 unserilize() 调用之前, 当反序列化时的字符串所对应的对象的数目被修改,__wake 的函数就不会被调用. 并且不会重建为对象, 但是会触发其他的魔术方法比如__destruct

贴一个我觉得最详细的链接:
https://www.anquanke.com/post/id/84705

漏洞利用

利用__wakeup()函数漏洞原理:

当序列化字符串表示对象属性个数的值大于真实个数的属性时就会跳过__wakeup的执行。
链接:xctf unserialize3
wp:xctf unserialize3

进阶版之变量权限为私有或者保护

protected
声明的字段为保护字段,在所声明的类和该类的子类中可见,但在该类的对象实例中不可见。因此保护字段的字段名在序列化时,字段名前面会加上\0*\0的前缀。这里的
\0 表示 ASCII 码为 0 的字符(不可见字符),而不是 \0 组合。

这也许解释了,为什么如果直接在网址上,传递\0*\0username会报错,因为实际上并不是\0,只是用它来代替ASCII值为0的字符。
必须用python传值才可以。

比如:

O:4:"Name":2:{s:11:"\0*\0username";s:5:"admin";s:11:"\0*\0password";i:100;}

private 声明的字段为私有字段,只在所声明的类中可见,在该类的子类和该类的对象实例中均不可见。因此私有字段的字段名在序列化时,类名和字段名前面都会加上\0的前缀。字符串长度也包括所加前缀的长度。其中 \0 字符也是计算长度的。

对于private变量,我们需要在类名和字段名前面都会加上\0的前缀
比如

O:4:"Name":3{s:14:"\0Name\0username";s:5:"admin";s:14:"\0Name\0password";i:100;}

注意:
这里使用python提交,因为他是私有类,
类名和字段名前面都会加上\0的前缀

进行利用的(传入该变量)
py代码:

import  requests

url ="http://7bc3f84d-1e2f-4a49-897a-15eb4d1d5255.node3.buuoj.cn"
html = requests.get(url+'?select=O:4:"Name":3:{s:14:"\0Name\0username";s:5:"admin";s:14:"\0Name\0password";i:100;}')
print(html.text)

如果想放在浏览器中直接提交,我们可以将\0换成%00

O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";i:100;}

相关题目链接:https://blog.csdn.net/weixin_45844670/article/details/108934194

总结

其实漏洞的核心思想还是在于unserialize函数,漏洞利用的核心思路在于控制魔术方法中的代码从而产生代码注入,SQL注入,目录遍历等一系列的漏洞利用。防御本漏洞就要严格控制unserialize函数的参数,对unserialize后的变量内容进行检查,确保绿色输入。

  • 10
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
关于PHP反序列化漏洞的习题,可以使用GlobIterator类和ArrayObject类来进行练习。其中,GlobIterator类的题目是被遗忘的反序列化,ArrayObject类的题目是easy_phpPHP反序列化漏洞是一种安全漏洞,其中一个具体的例子是CVE-2016-7124,该漏洞存在于php5<5.6.25和php7<7.0.10的版本中。漏洞的产生原因是由于反序列化时对输入的不当处理所导致的。 了解PHP反序列化漏洞的习题,需要掌握类与对象反序列化基础知识以及一些与魔术方法相关的内容,如构造和折构方法(__construct()、__destruct())、序列化和反序列化方法(__sleep()、__wakeup())、错误调用魔术方法(__callStatic()、__get()、__set()、__isset()、__unset()、__clone())等。反序列化漏洞的成因较复杂,例如POP链构造、POC链反推法等。 此外,还可以学习字符串逃逸和__wakeup魔术方法绕过漏洞的相关知识。其中,__wakeup魔术方法绕过漏洞的产生原因是__wakeup方法可以在反序列化时被绕过,从而可能导致安全漏洞PHP反序列化漏洞还可以通过引用的利用方法来进行学习。另外,还可以学习SESSION反序列化漏洞和phar反序列化漏洞的习题。其中,SESSION反序列化漏洞涉及到不同处理器的不同储存格式,而phar反序列化漏洞需要了解phar的构造和使用条件。 通过这些习题的学习,可以更好地理解PHP反序列化漏洞以及如何进行防范和修复。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [PHP反序列化漏洞(最全面最详细有例题)](https://blog.csdn.net/m0_73728268/article/details/129893800)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值