php反序列化总结&刷题&pop链&原生类

思维导图

img

原理

未对用户输入的序列化字符串进行检测,导致攻击者可以控制反序列化过程,一个反序列化漏洞造成要有魔术方法,恰好魔术方法里面有危险函数,比如危险函数文件读取,命令执行,反序列化在数据传递,可能触发危险函数

知识点

1、什么是反序列化操作?-格式转换
2、为什么会出现安全漏洞?-魔术方法
3、反序列化漏洞如何发现? -对象逻辑
4、反序列化漏洞如何利用?-POP链构造
补充:反序列化利用大概分类三类
魔术方法的调用逻辑-如触发条件
语言原生类的调用逻辑-如SoapClient
语言自身的安全缺陷-如CVE-2016-7124

序列化:对象转换为数组或字符串等格式
反序列化:将数组或字符串等格式转换成对象
serialize()//将一个对象转换成一个字符串
unserialize()//将字符串还原成一个对象

方便记忆以后记忆 反序列化就是加un的

反序列化一般是在白盒里面,就是代码给到你的情况下分析,在黑盒里面发现几乎不可能的

class info{
   
  	public $name='qian';
  	public $age=18;
}
O:4:"info":2:(s:4:"name";s:4:"qian";s:3:"age";i:2:18;}
object 长度 info 2个变量 string类型 长度 name 



class info{
   
  	public $name;
  	public 19;
}

基础

img

img

触发:unserialize函数的变量可控,文件中存在可利用的类,类中有魔术方法:
__construct(): //构造函数,当对象new的时候会自动调用
__destruct()//析构函数当对象被销毁时会被自动调用
__wakeup(): //unserialize()时会被自动调用
__invoke(): //当尝试以调用函数的方法调用一个对象时,会被自动调用
__call(): //在对象上下文中调用不可访问的方法时触发
__callStatci(): //在静态上下文中调用不可访问的方法时触发
__get(): //用于从不可访问的属性读取数据
__set(): //用于将数据写入不可访问的属性
__isset(): //在不可访问的属性上调用isset()或empty()触发
__unset(): //在不可访问的属性上使用unset()时触发
__toString(): //把类当作字符串使用时触发
__sleep(): //serialize()函数会检查类中是否存在一个魔术方法__sleep() 如果存在,该方法会被优先调用

对象变量属性:

public(公共的):在本类内部、外部类、子类都可以访问

protect(受保护的):只有本类或子类或父类中可以访问

private(私人的):只有本类内部可以使用

序列化数据显示:

private属性序列化的时候格式是 *%00类名%00成员名* 在原本上加2

protect属性序列化的时候格式是 *%00*%00成员名* 在原本上加3

为了区分公有私有保护 ,让人很容易看出来是什么类型的

<?php
header("Content-type: text/html; charset=utf-8");
//public private protected说明
class test{
   
    public $name="xiaodi";
    private $age="29"; //两个%00,在原本上加2 就是9个  
    protected $sex="man"; //两个%00一个*, 在原本上加3 就是6个
}
$a=new test();
$a=serialize($a);
print_r($a);

?> 

img

1.安全问题
<?php
class A{
   
  public $var='echo test';
  public function test(){
   
      echo $this->var;
  }
  public function __destruct(){
    //对象被销毁会被调用,  疑问?没有看见销毁代码啊.其实程序执行结束都会自动销毁
      echo '__destruct'.'<br>';
  }
  public function __construct(){
    //当对象new的时候会调用
  	echo '__construct'.'<br>';
  }
  public function __toString(){
   
  	return '__toString'.'<br>';
  }
}
$a=new A();
?>
//无需函数,创建对象触发魔术方法

访问结果

img

2.安全问题
<?php
class A{
   
  public $var='echo test';
  public function test(){
   
      echo $this->var;
  }
  public function __destruct(){
    //对象被销毁会被调用
      echo '__destruct'.'<br>';
  }
  public function __construct(){
    //当对象new的时候会调用
  	echo '__construct'.'<br>';
  }
  public function __toString(){
   
  	return '__toString'.'<br>';
  }
}
$a=new A();
echo serialize($a).'</br>'; //输入反序列化结果
?>

img

3.安全问题
<?php
class A{
   
  public $var='echo test';
  public function test(){
   
      echo $this->var;
  }
  public function __destruct(){
    //对象被销毁会被调用
      echo '__destruct'.'<br>';
  }
  public function __construct(){
    //当对象new的时候会调用
  	echo '__construct'.'<br>';
  }
  public function __toString(){
   
  	return '__toString'.'<br>';
  }
}
$t=unserialize($_GET['x']);
?> 
//触发__destruct
http://127.0.0.1/demo.php?x=O:1:“A”:1:{
   s:3:“var”;s:9:“echo test”;} 
相当于传递public $var=‘echo test’;

虽然没有new对象,但是传递了数据,只要传递数据,程序就会执行,执行就有销毁,触发__destruct()函数

img

4.安全问题
<?php
class A{
   
  public $var='echo test';
  public function test(){
   
      echo $this->var;
      echo '</br>';
  }
  public function __destruct(){
   
      echo '__destruct'.'<br>';
  }
  public function __construct(){
   
  	echo '__construct'.'<br>';
  }
  public function __toString(){
   
  	return '__toString'.'<br>';
  }
}
$a=new A();
$a->test();  //触发test 前提是new了一个对象,才可以指向test方法
?>

img

5.安全问题toString
<?php
class A{
   
  public $var='echo test';
  public function test(){
   
      echo $this->var;
      echo '</br>';
  }
  public function __destruct(){
   
      echo '__destruct'.'<br>';
  }
  public function __construct(){
   
  	echo '__construct'.'<br>';
  }
  public function __toString(){
   
  	return '__toString'.'<br>';
  }
}
$a=new A();
echo $a;//触发__toString    __toString触发条件:把类当作字符串使用时触发    echo输出的都是字符串
?>

img

6.安全问题
<?php
class B{
   
  public function __destruct(){
   
  	system('ipconfig');
  }
  public function __construct(){
   
  	echo 'qian'.'<br>';
  }
}
$b=new b(); //执行__destruct和__construct
echo serialize($b); //输出O:1:"B":0:{} 
?>

img

7.安全问题
<?php
class B{
   
  public function __destruct(){
   
  	system('ipconfig');
  }
  public function __construct(){
   
  	echo 'qian'.'<br>';
  }
}
//$b=new b(); //执行__destruct和__construct
//echo serialize($b); //输出O:1:"B":0:{} 

unserialize($_GET[x]);  //传递O:1:"B":0:{}  执行ipconfig
?>

img

8.安全问题 关键点
<?php
class C{
   
  public $cmd='ipconfig';
  public function __destruct(){
   
  	system($this->cmd);
  }
  public function __construct(){
   
  	echo 'qian'.'<br>';
  }
}

//函数引用,无对象创建触发魔术方法自定义变量
unserialize($_GET[c]); //?c=O:1:"C":1:{s:3:"cmd";s:3:"ver";}  修改$cmd的参数,让其执行其它命令,这也是反序列化的核心点
?>

img


12种魔术方法案例

<?php
header("Content-type: text/html; charset=utf-8");
//__construct __destruct 魔术方法 创建调用__construct 2种销毁调用__destruct
class Test{
   
    public $name;
    public $age;
    public $string;
    // __construct:实例化对象时被调用.其作用是拿来初始化一些值。
    public function __construct($name, $age, $string){
   
        echo "__construct 初始化"."<br>"
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值