1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
|
<?php
// stolen from PEAR2_Pyrus_Developer_Creator_Tar by Greg Beaver, the original author, for use in unit tests
// this tarmaker makes a malicious tar with a header designed to overflow the buffer
class danger_tarmaker
{
/**
* Path to archive file
*
* @var string
*/
protected $archive;
/**
* Temporary stream used for creating the archive
*
* @var stream
*/
protected $tmp;
protected $path;
protected $compress;
function __construct($path, $compress = 'zlib')
{
$this->compress = $compress;
if ($compress === 'bz2' && !function_exists('bzopen')) {
throw new PEAR2_Pyrus_Developer_Creator_Exception(
'bzip2 extension not available');
}
if ($compress === 'zlib' && !function_exists('gzopen')) {
throw new PEAR2_Pyrus_Developer_Creator_Exception(
'zlib extension not available');
}
$this->path = $path;
}
/**
* save a file inside this package
*
* This code is modified from Vincent Lascaux's File_Archive
* package, which is licensed under the LGPL license.
* @param string relative path within the package
* @param string|resource file contents or open file handle
*/
function addFile($path, $fileOrStream, $stat = null)
{
clearstatcache();
if ($stat === null) {
if (is_resource($fileOrStream)) {
$stat = fstat($fileOrStream);
} else {
$stat = array(
'mode' => 0x8000 + 0644,
'uid' => 0,
'gid' => 0,
'size' => strlen($fileOrStream),
'mtime' => time(),
);
}
}
$link = null;
if ($stat['mode'] & 0x4000) {
$type = 5; // Directory
} else if ($stat['mode'] & 0x8000) {
$type = 0; // Regular
} else if ($stat['mode'] & 0xA000) {
$type = 1; // Link
$link = @readlink($current);
} else {
$type = 9; // Unknown
}
$filePrefix = '';
if (strlen($path) > 255) {
throw new Exception(
"$path is too long, must be 255 characters or less"
);
} else if (strlen($path) > 100) {
$filePrefix = substr($path, 0, strlen($path)-100);
$path = substr($path, -100);
}
$block = pack('a100a8a8a8a12A12',
$path,
'12345678', // have a mode that allows the name to overflow
sprintf('%6s ',decoct($stat['uid'])),
sprintf('%6s ',decoct($stat['gid'])),
sprintf('%11s ',decoct($stat['size'])),
sprintf('%11s ',decoct($stat['mtime']))
);
$blockend = pack('a1a100a6a2a32a32a8a8a155a12',
$type,
$link,
'ustar',
'00',
'Pyrus',
'Pyrus',
'',
'',
$filePrefix,
'123456789abc'); // malicious block
$checkheader = array_merge(str_split($block), str_split($blockend));
if (!function_exists('_pear2tarchecksum')) {
function _pear2tarchecksum($a, $b) {return $a + ord($b);}
}
$checksum = 256; // 8 * ord(' ');
$checksum += array_reduce($checkheader, '_pear2tarchecksum');
$checksum = pack('a8', sprintf('%6s ', decoct($checksum)));
fwrite($this->tmp, (binary)$block . $checksum . $blockend, 512);
if (is_resource($fileOrStream)) {
stream_copy_to_stream($fileOrStream, $this->tmp);
if ($stat['size'] % 512) {
fwrite($this->tmp, (binary)str_repeat("\0", 512 - $stat['size'] % 512));
}
} else {
fwrite($this->tmp, (binary)$fileOrStream);
if (strlen($fileOrStream) % 512) {
fwrite($this->tmp, (binary)str_repeat("\0", 512 - strlen($fileOrStream) % 512));
}
}
}
/**
* Initialize the package creator
*/
function init()
{
switch ($this->compress) {
case 'zlib' :
$this->tmp = gzopen($this->path, 'wb');
break;
case 'bz2' :
$this->tmp = bzopen($this->path, 'w');
break;
case 'none' :
$this->tmp = fopen($this->path, 'wb');
break;
default :
throw new Exception(
'unknown compression type ' . $this->compress);
}
}
/**
* Create an internal directory, creating parent directories as needed
*
* @param string $dir
*/
function mkdir($dir)
{
$this->addFile($dir, "", array(
'mode' => 0x4000 + 0644,
'uid' => 0,
'gid' => 0,
'size' => 0,
'mtime' => time(),
));
}
/**
* Finish saving the package
*/
function close()
{
fwrite($this->tmp, pack('a1024', ''));
fclose($this->tmp);
}
}
|