PHP unserialize() 是否可以在没有任何魔术方法的情况下被利用?

信息安全 Web应用程序 php 对象注入
2021-09-03 00:03:27

假设有一个可公开访问的网页,其中包含以下 PHP 代码:

<?php
class NotInteresting
{
    public function noExploits() {
        echo "Whatever.";
    }
}
$unsafe = unserialize($_GET['data']);
$unsafe->noExploits();
?>

代码期望dataURL 参数包含 的序列化实例NotInteresting但当然data可以操纵该参数。unserialize()用于用户提供的数据时,它通常会导致PHP 对象注入

但是,到目前为止,我看到的所有 PHP 对象注入示例(123)都是危险的,原因有两个:

  1. 有一些带有危险方法的可利用类(这些方法只能在内部调用)被用来执行任意代码,通常是 CMS 的情况。
  2. PHP 版本过旧或过时,PHP 代码中的漏洞被利用。

鉴于 PHP 版本是最新的 - 也就是说,unserialize()函数中不存在已知漏洞 - 并且没有定义自定义类(只是默认类 -ExceptionstdClass),是否可以利用上述代码进行成功的攻击在默认的 PHP 安装上?

额外信息:

据我所知,从调用构造任意类时只有四种可利用魔术方法、、unserialize()__call()__wakeup()__destruct()__toString()

  • __wakeup()在对象未序列化时调用。
  • __call()在调用不可访问的方法(或不存在的方法)时被调用。
  • __destruct()总是在不再存在对该对象的引用后调用。
  • __toString()在对象被视为字符串时被调用。

因此,我编写了一个 PHP 脚本来快速生成包含这些魔术方法的类列表:请参阅此处以获取 pastebin其中一些看起来非常“有趣”:

  • XML 类(可能导致XXE
  • Phar课程_

但是,到目前为止,我无法仅凭这些来构建攻击:我需要更有经验的人来权衡。

2个回答

PHP 对象反序列化的可利用性仅取决于可用的类(标准类和自定义类)、它们的方法和行为,以及是否有可能触发这些可利用的方法之一。

请注意,可利用的方法可能不是那么简单。您可能需要使用多个嵌套对象创建复杂的对象结构来触发特定行为。可利用方法的数量或其行为也可能在此期间发生变化。因此,即使您今天可能无法利用它,有时也可能有人能够利用它。

好的,为了对特定设置安全,您必须绝对确定没有具有可利用行为的类。鉴于这可能包括各种模块(数据库访问等),并且它们的行为可能包括诸如 getter 或 之类的“魔术方法” __wakeup(),因此很难完全了解这一点。

您还应该考虑您的开发人员/维护人员(包括未来的您)。首先,他们可能不记得他们应该在编写每个类时都考虑到这个安全约束(这似乎很容易忘记)。其次,代码看起来不安全,不断让人们跑过来让你仔细解释你如何清理系统的所有其他部分以使这个特定的东西工作是没有意义的。

一个更好的计划是对 JSON 之类的东西进行序列化 - 这不仅更安全,而且还使您的 API 与其他语言兼容。