反序列化漏洞学习

序列化:

将对象转换成字符串(包括属性名、属性值、属性类型和该对象对应的类名)---->有利于对象的保存和传输,也可让多个文件共享对象。

反序列化:

将字符串重新恢复成对象的成员变量。

php序列化

<?php
class test{
public $flag = 'flag{RedSpeed}';
public $name = 'cxk';
public $age ='10';
}
$tester = new test;
$tester->flag = 'flag{helloworld}';
$tester->name = 'whiteH';
$tester->age = '25';
echo serialize($tester);
?>
    
 #输出:
 O:4:"test":3:{s:4:"flag";s:16:"flag{RedSpeed}";s:4:"name";s:3:"cxk";s:3:"age";s:2:"25";}

_sleep()

调用serialize()函数时,函数会先检查类中是否存在魔术方法_sleep()。如果存在,_sleep()会先被调用,【若存在,会按照sleep()函数的属性序列化设置】然后才执行序列化操作。此功能可以用于清理对象,并返回一个包含对象中所有应被序列化的变量名称的数组。

<?php
class Person
{
    public $sex;
    public $name;
    public $age;
    public function _construct($name="",$age=25,$sex='男')
    {
        $this->name = $name;
        $this->age = $age;
        $this->sex = $sex;
    }
    public function _sleep(){
        $this->name = base64_encode($this->name);
        return array('name','age');//必须返回一个数组,里边的元素表示返回的属性名称
    }
}
$person = new Person('小明');//赋初值
echo serialize($person);
echo '<br/>';
?>
    
#输出:
O:6:"Person":2:{s:4:"name";s:8:"5bCP5piO";s:3:"age";i:25}

PHP反序列化

<?php

class Test{

public $flag = 'flag{****}';

public $name = 'wty';

public $age = '10';

}


$tester = new Test(); //实例化一个对象

$tester->flag = 'flag{ashjfkdhdg}';

$tester->name = 'WhiteH';

$tester->age = '18';

$str = serialize($tester);

echo $str;

echo '<pre>';

var_dump(unserialize($str));//调用反序列化函数,将str字符串转换成对象

?>
    
#输出:
object(Test) #2 (3){
  ["flag"]=>
      string(16) "flag{ashjfkdhdg}"
  ["name"]=>
      string(6)  "WhiteH"
  ["age"]=>
      string(2)  "18"
}

_wakeup()

与序列化类似。如果存在_wakeup,先调用_wakeup,(预先准备对象资源,返回void),对属性进行初始化,赋值或改变。

<?php

class Test{

public $flag = 'flag{****}';

public $name = 'wty';

public $age = '10';

public function __wakeup(){

//调用wakeup方法的时候将flag属性的值改变

$this ->flag = "This is not a flag";

}

}

$tester = new Test(); //实例化一个对象

$tester->flag = 'flag{ashjfkdhdg}';

$tester->name = 'WhiteH';

$tester->age = '18';

$str = serialize($tester);

echo $str;

echo '<pre>';

var_dump(unserialize($str));//调用反序列化函数,将str字符串转换成对象

?>
    

常见魔术方法:

_construct()------对象new时自动调用
_destruct()--------对象销毁时自动调用
_wakeup()---------使用unserialize()函数时自动调用
_toString()----------当对象被当作字符串输出时自动调用
    

绕过

反序列化绕过

php7.1+反序列化对类属性不敏感

如果变量前是protected,可换为public

绕过__wakeup(CVE-2016-7124)

版本:PHP5 < 5.6.25 && PHP7 < 7.0.10

利用:序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过__wakeup的执行,并且不会报错,可以被正常反序列化

绕过部分正则

preg_match('/^O:\d+/')匹配序列化字符串是否是对象字符串开头

**:利用+绕过 或 serialize(array(a)); //a为要反序列化的对象(序列化结果开头是a,不影响作为数组元素的$a的析构)

补充:

正则表达式中^的用法

**限定开头:匹配输入的开始,如果多行标示被设置成了true,同时会匹配后面紧跟的字符。 比如 /^A/会匹配"An e"中的A,但是不会匹配"ab A"中的A

**(否)取反:/[^a-z\s]/会匹配"my 3 sisters"中的"3" 这里的”^”的意思是字符类的否定,上面的正则表达式的意思是匹配不是(a到z和空白字符)的字符。

**只要是”^”这个字符是在中括号”[]”中被使用的话就是表示字符类的否定,如果不是的话就是表示限定开头。其实也就是说”[]”代表的是一个字符集,”^”只有在字符集中才是反向字符集的意思。

PHP反序列化字符串逃逸--改变序列化字符串的长度,导致反序列化漏洞

***共同点:

  1. php序列化后的字符串经过了替换或者修改,导致字符串长度发生变化。
  2. 总是先进行序列化,再进行替换修改操作。

过滤后导致序列化字符串变长

<?php
  function filter($str){
  return str_replace('bb','ccc',$str);
}
class A{
  public $name = 'aaabb';
  public $pass = '123456';
}
$AA = new A();
echo serialize($AA);//序列化后的字符串s为5,内容为aaabb,结果为O:1:"A":2:{s:4:"name";s:5:"aaabb";s:4:"pass";s:6:"123456";}
$res = filter(serialize($AA));
//过滤后,s仍为6,当内容变为aaaccc.但此时name只能读取到aaacc,无法读到末尾的c,所以就形成了一个字符串的逃逸。每添加一个bb就可逃逸一个字符
$c = unserialize($res);
echo $c->pass;
?>
//以上代码可以在不直接修改$pass值得情况下简介修改$pass的值
//先序列化代码,将里面不希望出现的字符bb替换成ccc,然后反序列化,最后输出pass变量

所以可将逃逸字符传的长度填充为我们要反序列化的代码长度,即可控制反序列化的结果以及类里的变量值

在name处改为

O:1:"A":2:{s:4:"name";s:5:"aaabb";s:4:"pass";s:6:"123456";}

";s:4:"pass";s:6:"hacker";}

被反序列化后的$name仍为";s:4:"pass";s:6:"hacker";}。所以主要是看filter()函数检测并替换非法字符串。

";s:4:"pass";s:6:"hacker";}长度为27,所以如果给name再赋值27个bb,就会增加27个长度,就可以逃逸";s:4:"pass";s:6:"hacker";}了

public $name = 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";s:4:"pass";s:6:"hacker";}';

序列化后字符串如下

O:1:"A":2:{s:4:"name";s:54:"bbbbbbbbbbbbbbbbbbbbbbbbbbb";s:4:"pass";s:6:"hacker";}";s:4:"pass";s:6:"123456";}

此时,原先的s:4:"pass";s:6:"123456";}由于前面的字符串已经构造了闭合会被舍弃,逃逸出来的s:4:"pass";s:6:"hacker";}就会被当做当前类的属性被继续执行。然后密码就改完啦~

过滤后导致序列化字符串变短

<?php
function str_rep($string){
	return preg_replace( '/php|test/','', $string);//在string中匹配到php或test就替换为空
}

$test['name'] = $_GET['name'];
$test['sign'] = $_GET['sign']; 
$test['number'] = '2020';
$temp = str_rep(serialize($test));
printf($temp);
$fake = unserialize($temp);
echo '<br>';
print("name:".$fake['name'].'<br>');
print("sign:".$fake['sign'].'<br>');
print("number:".$fake['number'].'<br>');
?>

执行结果如下

可通过输入name和sign来间接修改number的值

?name=phpphpphpphpphpphpphpphp&&sign=hello";s:4:"sign";s:4:"eval";s:6:"number";s:4:"2000";}

str_rep()中检测到php,会替换为空,实现字符串逃逸,输入8个php就腾出了24个空间,正好包含进了";s:4:"sign";s:54:"hello,然后就达到目的啦

老感觉这个绕过有点SQL注入的意思

举例就是[安洵杯 2019]easy_serialize_php,可以看buuctf的wp

pop链

我现在的感觉就是逆向分析,不断找跳板,进行触发

php-session反序列化

魔术方法:

__get

使用场景:

当希望访问某个对象的未定义的或者不可访问的属性不报错,我们可以在类里定义__get方法,这样系统在此刻会自动调用该方法

定义格式:

public function __get(参数1) ,这里注意必须是2个__,名称必须是__get,而且必须是要带1个参数,多一个少一个都不行

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
关于PHP反序列化漏洞的习题,可以使用GlobIterator类和ArrayObject类来进行练习。其中,GlobIterator类的题目是被遗忘的反序列化,ArrayObject类的题目是easy_phpPHP反序列化漏洞是一种安全漏洞,其中一个具体的例子是CVE-2016-7124,该漏洞存在于php5<5.6.25和php7<7.0.10的版本中。漏洞的产生原因是由于反序列化时对输入的不当处理所导致的。 了解PHP反序列化漏洞的习题,需要掌握类与对象、反序列化基础知识以及一些与魔术方法相关的内容,如构造和折构方法(__construct()、__destruct())、序列化和反序列化方法(__sleep()、__wakeup())、错误调用魔术方法(__callStatic()、__get()、__set()、__isset()、__unset()、__clone())等。反序列化漏洞的成因较复杂,例如POP链构造、POC链反推法等。 此外,还可以学习字符串逃逸和__wakeup魔术方法绕过漏洞的相关知识。其中,__wakeup魔术方法绕过漏洞的产生原因是__wakeup方法可以在反序列化时被绕过,从而可能导致安全漏洞PHP反序列化漏洞还可以通过引用的利用方法来进行学习。另外,还可以学习SESSION反序列化漏洞和phar反序列化漏洞的习题。其中,SESSION反序列化漏洞涉及到不同处理器的不同储存格式,而phar反序列化漏洞需要了解phar的构造和使用条件。 通过这些习题的学习,可以更好地理解PHP反序列化漏洞以及如何进行防范和修复。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [PHP反序列化漏洞(最全面最详细有例题)](https://blog.csdn.net/m0_73728268/article/details/129893800)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值