PHP反序列化字符串逃逸

本文介绍了PHP中的字符串逃逸技术,包括减少和增多字符串的方法。通过preg_replace函数,改变序列化字符串内容,实现反序列化时对对象属性的操控。示例中展示了如何利用字符串增多来修改类实例的属性值,以及如何通过字符串减少来实现同样的效果。文章详细阐述了构造序列化字符串的原理和步骤,对于理解PHP字符串操作和安全有重要参考价值。
部署运行你感兴趣的模型镜像

例题可看:https://www.cnblogs.com/v2ish1yan/articles/16118319.html

今天才学的,做个记录。

字符串逃逸分为两种,减少和增多。

主要是通过一个preg_replace()函数来进行字符串的减少和增多。

首先要知道逃逸的原理,就是反序列化时,是以}来进行结尾的,同时在字符串内,是以关键字后面的数字来规定所读取的内容的长度。

1.字符串增多

demo:

<?php
class A{
    public $a='q';
    public $b='21';

}
$a=new A;
var_dump($a);

得到结果为:

string(45) "O:1:"A":2:{s:1:"a";s:1:"q";s:1:"b";s:2:"21";}"

要将反序列后$b的值变为我们想要的值。

我们还要有一个关键的函数。

function filter($a){
    $filter='/q/i';
    return preg_replace($filter,'ww',$a);
}

这个就是将序列化后的值,将所有的'q'变为'ww'。

例子:

<?php
class A{
    public $a='qqqqqqq';
    public $b='21';

}function filter($a){
    $filter='/q/i';
    return preg_replace($filter,'ww',$a);
}
$a=new A;
var_dump(serialize($a));
echo'<pre>';
$r=filter(serialize($a));
var_dump($r);

得到:

假设我们想要$b=104,构造的$b的值的序列化后为:

";s:1:"b";s:3:"104";}
这里的";是用来闭合前面的,往下看就知道了

如何进行逃逸

我们先看看把上面的字符串加到$a后是什么样的。

 然后仔细看,如果我们把s:28后面的内容以字符串按要求填满了28个,那么s:1:"b";s:3:"104";}就会被包含在序列化字符串内。而}”后面的内容,即;s:1:"b";s:2:"21";}"就不会被认为是序列化字符串的内容,从而执行了我们构造的";s:1:"b";s:3:"104";},即让一个成员b的值为104。

然后进行构造:

在上面,只要让'w'字符的数量按要求达到s:后面所要求的的数量(28)即可。

但是我们要根据实际情况来选择构造多少个w。

因为在filter函数中,一个q被换成了两个w,所以让q的数量等于";s:1:"b";s:3:"104";}的字符串长度就行了。因为";s:1:"b";s:3:"104";} 的字符串长度为21,让q的数量为21,反序列化后a的值的长度为就是q的数量加上";s:1:"b";s:3:"104";}  的长度(42),在filter()之后,w的数量就是刚好42,而我们添加上去的字符串就会被逃逸出来,会在反序列化的时候成功执行。【文笔不好】

<?php
class A{
    public $a='qqqqqqqqqqqqqqqqqqqqq";s:1:"b";s:3:"104";}';
    public $b='21';

}function filter($a){
    $filter='/q/i';
    return preg_replace($filter,'ww',$a);
}
$a=new A;
var_dump(serialize($a));
echo'<pre>';
$r=filter(serialize($a));
var_dump($r);

得到

string(87) "O:1:"A":2:{s:1:"a";s:42:"qqqqqqqqqqqqqqqqqqqqq";s:1:"b";s:3:"104";}";s:1:"b";s:2:"21";}"

string(108) "O:1:"A":2:{s:1:"a";s:42:"wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww";s:1:"b";s:3:"104";}";s:1:"b";s:2:"21";}"

然后再进行反序列化就可以发现,$b的值变成了104。

接上面代码:

print_r(unserialize($r));

 总的就是说,让字符'w'占用了原本属于";s:1:"b";s:3:"104"}的位置,从而让";s:1:"b";s:3:"104"}逃逸出去而成功执行。

2.字符串减少

demo:

<?php
class A{
    public $a='qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq';
    public $b='20';

}
function filter($a){
    $filter='/qq/i';
    return preg_replace($filter,'w',$a);
}
$a=new A;
var_dump(serialize($a));
echo '<pre>';
$r=filter(serialize($a));
var_dump($r);

 由名字可知,这个就是让字符串变少。

那么要如何让字符串逃逸呢?

同上面字符串增加:如果要让$b=104,那么他的序列化后就是:";s:1:"b";s:3:"104";}

但是前面要加个东西,如:A";s:1:"b";s:3:"104";},那个A是用来闭合的。

我们先把$b=A";s:1:"b";s:3:"104";}

得到:

 这里可以看到,在序列化字符串里,有两个 s:1:"b",第一个是序列化得到的,第二个是我们自己构造的。

那么要如果让我们构造的104生效呢?

就要让s:1:"a":s:32:"读取到s:22:"A",这样s:22:"A就会变成$a的值了,后面的内容就可以执行,所以这个时候就要想如何使这些字符串在一个合理的数量了。

有filter可以知道,两个q会变成一个w,所以只要让w的个数等于黄色字符串的长度

"O:1:"A":2:{s:1:"a";s:44:"wwwwwwwwwwwwwwwwwwwwww";s:1:"b";s:22:"A";s:1:"b";s:3:"104";}";}"

这个黄色字符串长度为17,所以qq的数量就为17,就有34个q。

所以这样:

<?php
class A{
    public $a='qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq';
    public $b='A";s:1:"b";s:3:"104";}';

}
function filter($a){
    $filter='/qq/i';
    return preg_replace($filter,'w',$a);
}
$a=new A;
var_dump(serialize($a));
echo '<pre>';
$r=filter(serialize($a));
var_dump($r);
print_r(unserialize($r));

就可以得到

 看$b变成了104。

与字符串增加的区别:

1.字符串增加:构造的序列化加在qqqq(就是值有很多qqqq的)那个变量里。字符串减少:构造的序列化加在另一个变量里。

2.字符串增加:字符串'qqqqxxx'的数量依照构造的那个序列化字符串的长度。字符串减少:字符串'qqqqxxx'的数量依照"O:1:"A":2:{s:1:"a";s:44:"wwwwwwwwwwwwwwwwwwwwww";s:1:"b";s:22:"A";s:1:"b";s:3:"104";}";}"中黄色字符串的长度。(只能意会)(doge)

您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

反序列化字符串逃逸是一种在PHP等编程语言中利用序列化和反序列化机制的漏洞。 ### 原理 在序列化过程中,对象或数据结构被转换为字符串形式,该字符串包含了对象的类名、属性名和属性值等信息,并且对属性值的长度有明确的标记。而在反序列化时,程序会根据这些标记来解析字符串,还原对象或数据结构。当开发者使用一些过滤函数(如`str_replace`)对序列化后的字符串进行处理时,可能会改变字符串的实际内容,但不会改变序列化时标记的长度,这就导致了字符串逃逸问题。 例如,序列化之后,属性的长度在序列化后是固定的,即使使用替换函数也不会改变,这是能够逃逸的一个关键,因为是先进行了序列化才进行的替换。如在某些情况下,将序列化字符串中的某些字符替换为空,会使字符串长度减少,但原序列化标记的长度不变,后面的内容就会被“吞”进来解析,从而实现逃逸;反之,若替换后字符串长度增加,也会造成解析的偏移,实现另一种形式的逃逸 [^4]。 ### 应用 反序列化字符串逃逸可用于构造恶意的反序列化数据,绕过安全检查,执行任意代码或修改程序的正常逻辑。例如在某些代码中,开发者通过过滤函数对用户输入进行安全性检查,但由于反序列化字符串逃逸问题,攻击者可以构造特殊的输入,绕过这种检查。 在给出的示例代码中,定义了一个过滤函数`filter`,将`"flag"`和`"php"`替换为`"hack"`,然后对用户输入进行序列化、过滤和反序列化操作。攻击者可以构造特殊的输入,利用字符串逃逸,使反序列化后的对象满足特定条件,如使`$profile->pass == 'escaping'`,从而实现攻击目标 [^5]。 以下是一个简单的示例代码,演示字符串逃逸减少的情况: ```php <?php class a{ public $name = "abcp"; public $number = "1234"; } $data = serialize(new a()); echo '序列化:'.$data."\n"; $data = str_replace("p","",$data); // 注意这个str_replace,它把p都替换为空 echo '替换后序列化:'.$data."\n"; var_dump(unserialize($data)); ``` 在这个例子中,将序列化字符串中的`p`替换为空,由于原序列化标记的长度不变,会导致反序列化时解析出现偏差,从而实现字符串逃逸 [^3]。
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

v2ish1yan

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

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

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

打赏作者

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

抵扣说明:

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

余额充值