首页 > 解决方案 > PHP反序列化和重复的变量名

问题描述

最近,我偶然发现了旧版本 CMS Contao 中 PHP 对象注入漏洞的描述(它是用德语编写的,但我将翻译关键部分)。

作者在那里说,他没有设法让 Null-Bytes 进入反序列化函数(它们被过滤掉了),因此他无法直接写入类的受保护或私有成员。

然后他说这不是问题,因为unserialize() 函数不会关心类的序列化版本是否具有在真实类中实际受保护的公共成员,因此他可以删除前导的 Null-Bytes 和星号并更正变量名称字符串的长度(只是在序列化版本中公开变量)以使攻击起作用(因此写入易受攻击类的受保护成员)。

然后我尝试编写自己的这种行为的 PoC,但失败了。首先,我创建了一个名为“Test”的小测试类,它具有受保护的成员“value”和一个打印该值的析构函数:

class Test {
   protected $value = "Default";

   public function __destruct() {
      echo $this->value . "<br>";
   }
}

现在我正在尝试更改受保护的“值”成员的值。使用 Null-Bytes 和 Star,一切正常:

$obj = unserialize("O:4:\"Test\":1:{s:8:\"\0*\0value\";s:8:\"Injected\";}");
echo serialize($obj);

给我:
O:4:"Test":1:{s:8:"*value";s:8:"Injected";}
注入

现在我尝试省略 Null-Bytes 和星号,所以我假装“值”将是一个公共变量:

$obj2 = unserialize("O:4:\"Test\":1:{s:5:\"value\";s:8:\"Injected\";}"); // I pretended that 'value' would be a public variable
echo serialize($obj2);

这给了我:
O:4:"Test":2:{s:8:"*value";s:7:"Default";s:5:"value";s:8:"Injected";}
默认

如果您查看该类的序列化版本,似乎 PHP-Object 有两个名称相同但可见性不同的成员。析构函数打印出受保护的成员,因此注入不起作用

现在我想知道在这种情况下我是否遗漏了一些东西,或者为什么这似乎对文章的作者有用。我将非常感谢您的帮助!

标签: phpsecurityserialization

解决方案


推荐阅读