Blog post

What is Phar Deserialization

Johannes Dahse photo

Johannes Dahse

Head of R&D

Date

  • Security
Last week a new exploitation technique for PHP applications was announced at the BlackHat USA conference. Find out everything you need to know in this blog post.

Summary

The security researcher Sam Thomas from Secarma found a new exploitation technique that can lead to critical PHP object injection vulnerabilities - without using the PHP function unserialize(). The new technique was announced at the BlackHat USA conference in his talk It’s a PHP Unserialization Vulnerability Jim, but Not as We Know It. It can enable attackers to escalate the severity of file related vulnerabilities to remote code execution.

Stream Wrappers

Most PHP file operations allow to use various URL-style wrappers such as data://zlib://, or php:// when accessing a file path. Some of these wrappers are often used to exploit remote file inclusion vulnerabilities where an attacker can control the full file path of a file inclusion. For example, the wrappers are injected to leak source code that otherwise would be executed, or to inject own PHP code for execution:


Remote File Inclusion Exploitation

1    include($_GET['file'])
2    include('php://filter/convert.base64-encode/resource=index.php');
3    include('data://text/plain;base64,cGhwaW5mbygpCg==');

Phar Meta Data

But so far, nobody paid attention to the phar:// wrapper. What is interesting about Phar (PHP Archive) files is that these contain meta data in serialized format. Let’s create a Phar file and add an object with some data as meta data:


Creating a Phar File

 1    // create new Phar
 2    $phar = new Phar('test.phar');
 3    $phar->startBuffering();
 4    $phar->addFromString('test.txt', 'text');
 5    $phar->setStub('<?php __HALT_COMPILER(); ? >');
 6
 7    // add object of any class as meta data
 8    class AnyClass {}
 9    $object = new AnyClass;
10    $object->data = 'rips';
11    $phar->setMetadata($object);
12    $phar->stopBuffering();

Our newly created test.phar file now has the following content. We can see that our object was stored as a serialized string.

Figure 1: Hex view of the created Phar file.

PHP Object Injection

If a file operation is now performed on our existing Phar file via the phar:// wrapper, then its serialized meta data is unserialized. This means that our injected object in the meta data is loaded into the application’s scope. If this application has a class named AnyClass and it has the magic method __destruct() or __wakeup() defined, then those methods are automatically invoked. This means we can trigger any destructor or wakeup method in the code base. Even worse, if these methods operate on our injected data then this can lead to further vulnerabilities.


PHP Object Injection via Phar file

1    classAnyClass{
2        function__destruct(){
3            echo $this->data;
4        }
5    }
6    // output: rips 
7    include('phar://test.phar');

Exploitation

First, an attacker must be able to plant a crafted Phar file on the targeted web server. But Sam Thomas found some nice tricks on how to sneak a Phar file into a fake JPG, so a common image upload feature is already sufficient1.

So far, this still doesn’t seem that critical because if an attacker can control the full file path in operations such as ìnclude()fopen()file_get_contents()file() etc., then this already poses a severe security vulnerability itself. Therefore, user input used in these functions is usually validated.

However, the unserialize is triggered for the phar:// wrapper in any file operation. Thus, other file operations, such as file_exists() which simply checks the existence of a file, were until now considered as less sensitive to security risks and are less well protected. But now an attacker can inject the phar:// wrapper and gain code execution.


Examples of so far harmless looking code:

1    file_exists($_GET['file']);
2    md5_file($_GET['file']);
3    filemtime($_GET['file']);
4    filesize($_GET['file


Related Posts