← CodeClarityLab Home
Browse by Category
+ added · updated 7d
← Back to glossary

PHAR Deserialization Attack

security CWE-502 OWASP A8:2021 CVSS 9.8 PHP 5.0+ Advanced

Also Known As

PHAR deserialization PHP archive injection phar:// attack

TL;DR

PHP's phar:// stream wrapper triggers deserialization of PHAR metadata on any file operation, enabling PHP object injection without unserialize().

Explanation

PHAR (PHP Archive) files embed serialized PHP metadata in their stub. Any PHP file function (file_exists(), fopen(), copy(), rename(), include()) that operates on a phar:// URI will deserialize this metadata — triggering magic methods and enabling PHP Object Injection without a call to unserialize(). An attacker who can upload a file (even one with a safe extension like .jpg) and control a path passed to a file function can exploit this. Mitigations: disable the phar stream wrapper (Phar::unlinkArchive, stream_wrapper_unregister('phar')), validate file paths strictly, and use realpath() before file operations.

How It's Exploited

An attacker uploads a JPEG image crafted with a PHAR payload in its metadata. Later, a call to file_exists('phar://uploads/evil.jpg') triggers deserialization and executes a POP gadget chain.

Common Misconception

PHAR injection requires the attacker to upload a .phar file. Any file operation using a user-controlled path — file_exists(), fopen(), copy() — can trigger PHAR deserialization if the path starts with phar://, even on an uploaded image.

Why It Matters

PHP archive files are deserialized when accessed via any stream wrapper that triggers PHP's file functions — an attacker who can upload a PHAR file and trigger a file function on it gets deserialization RCE.

Common Mistakes

  • Allowing user file uploads to be passed to file_exists(), file_get_contents(), or similar — a phar:// URL triggers deserialization.
  • Not disabling PHAR-based stream wrappers when user input is used in file paths.
  • Mime-type checking uploads but not considering that .jpg files can be valid PHAR archives.
  • Not restricting allowed PHP stream wrappers via allow_url_fopen and htaccess rules.

Code Examples

✗ Vulnerable
// User-controlled path triggers PHAR deserialization:
$file = $_GET['file'];
if (file_exists($file)) { // Attacker: ?file=phar://uploads/evil.jpg
    echo file_get_contents($file);
}
✓ Fixed
// Validate file paths — never pass user input to file functions:
function safeRead(string $userPath): string {
    // Realpath resolves .. and symlinks:
    $base = realpath('/var/www/uploads/');
    $full = realpath($base . '/' . basename($userPath));

    // Ensure resolved path is inside the allowed directory:
    if (!$full || !str_starts_with($full, $base . '/')) {
        throw new SecurityException('Path traversal attempt');
    }

    return file_get_contents($full);
}

// Disable phar stream wrapper if not needed:
stream_wrapper_unregister('phar');

// Validate file magic bytes, not extension:
$finfo = new \finfo(FILEINFO_MIME_TYPE);
$type  = $finfo->file($path); // Check actual content type

Added 15 Mar 2026
Edited 22 Mar 2026
Views 154
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 1 ping T 4 pings F 1 ping S 2 pings S 0 pings M 0 pings T 0 pings W 1 ping T 2 pings F 1 ping S 1 ping S 0 pings M 0 pings T 0 pings W 0 pings T
No pings yet today
No pings yesterday
ChatGPT 103 Perplexity 16 Amazonbot 16 Google 6 Unknown AI 5 Ahrefs 1 Qwen 1
crawler 146 crawler_json 1 pre-tracking 1
DEV INTEL Tools & Severity
🔴 Critical ⚙ Fix effort: Medium
⚡ Quick Fix
Never pass user-controlled paths to file functions (file_exists, include, fopen) — validate and canonicalise all paths with realpath() first
📦 Applies To
PHP 5.0+ web cli
🔗 Prerequisites
🔍 Detection Hints
file_exists($_GET['file']) or include($_GET['path']) allowing phar:// wrapper without blocking
Auto-detectable: ✓ Yes semgrep psalm
⚠ Related Problems
🤖 AI Agent
Confidence: High False Positives: Medium ✗ Manual fix Fix: High Context: Function Tests: Update
CWE-502 CWE-694

✓ schema.org compliant