PHP 对象注入真的需要 PHP 魔术方法吗?

信息安全 php 注射
2021-08-31 00:05:33

我试图了解 vBulletin 5.1.x (CVE 2015-7808) 中的 PHP 对象注入缺陷,我偶然发现了 OWASP 所述的对象注入要求:

应用程序必须有一个实现 PHP 魔术方法(如 __wakeup 或 __destruct)的类,可用于执行恶意攻击或启动“POP 链”。
来源:https ://www.owasp.org/index.php/PHP_Object_Injection

然而,在这篇关于 vbulletin 漏洞的文章中,我没有看到被利用的魔法方法,而是rewind()调用了类的函数,vB_dB_Result因为foreach()

public function decodeArguments($arguments){
        if ($args = @unserialize($arguments)){
            $result = '';
            foreach ($args AS $varname => $value){
                $result .= $varname;
...
class vB_dB_Result implements Iterator{
...
    public function rewind(){
        //no need to rerun the query if we are at the beginning of the recordset.
        if ($this->bof){
            return;
        }
        if ($this->recordset){
            $this->db->free_result($this->recordset);
        }
...
abstract class vB_Database{
... 
    function free_result($queryresult){
        $this->sql = '';
        return @$this->functions['free_result']($queryresult);
    }

在这种情况下,我是否遗漏了什么或者 OWASP 声明只是错误的?

1个回答

这种形式的陈述是错误的。您可以使用任何方法进行 PHP 对象注入。重要的一点是必须实际调用该方法

魔术方法的优点是它们都命名相同,__wakeup并且__destruct都被自动调用

在这种特定情况下,rewind它被称为 foreach 循环中迭代器的一部分。

但它也适用于其他更简单的示例。例如,假设您有两个类,它们都有一个同名的方法:

class Foo {
    public function bar() {
        echo "everything is safe here";
    }
    [other methods...]
}

class BadFoo {
    public $command = "something";
    public function bar() {
        echo exec($this->command);
    }
}

现在你想反序列化一个安全Foo类的对象,并在它上面调用 bar 函数:

$foo = unserialize($_GET['foo']);
$foo->bar();

显然,攻击者可以简单地发送BadFoo类的对象,从而导致代码执行:

O:6:"BadFoo":1:{s:7:"command";s:2:"id";}

这表明它适用于任何方法,而不仅仅是魔术方法,只要该方法被调用并执行攻击者感兴趣的事情。