- 发布时间:2016-08-29
- 公开时间:N/A
- 漏洞类型:变量覆盖
- 危害等级:高
- 漏洞编号:xianzhi-2016-08-42442070
- 测试版本:N/A
漏洞详情
include/remote.class.php
function construct($file, $savepath, $savename = '') {
global $DT, $_userid;
$this->file = strip_sql($file, 0);
$this->userid = $_userid;
$this->ext = file_ext($file);
in_array($this->ext, array('jpg', 'jpeg', 'gif', 'png', 'bmp')) or $this->ext = 'jpg';
$this->maxsize = $DT['uploadsize'] ? $DT['uploadsize']1024 : 20481024;
$this->savepath = $savepath;
$this->savename = $savename;
}
function remote($file, $savepath, $savename = '') {
$this->construct($file, $savepath, $savename);
}
function save() {
include load('include.lang');
if(!$this->isallow()) return $this->($L['uploadnot_allow']);
$this->set_savepath($this->savepath);
$this->set_savename($this->savename);
if(file_copy($this->file, DT_ROOT.'/'.$this->saveto)) {
if(!@getimagesize(DT_ROOT.'/'.$this->saveto)) {
file_del(DT_ROOT.'/'.$this->saveto);
return $this->($L['uploadbad']);
}
if($this->maxsize > 0 && filesize(DT_ROOT.'/'.$this->saveto) > $this->maxsize) {
file_del(DT_ROOT.'/'.$this->saveto);
return $this->($L['uploadsize_limit'].' ('.intval($this->maxsize/1024).'Kb)');
}
$this->image = 1;
return true;
} else {
return $this->($L['uploadfailed']);
}
}
upload.php 行69
if($remote && strlen($remote) > 17 && strpos($remote, '://') !== false) {
require DT_ROOT.'/include/remote.class.php';
$do = new remote($remote, $uploaddir);
$remote可以随意提交 只要长度大于17且包含:// 就进入远程下载
虽然远程下载逻辑中判断了文件的格式,非法格式一律当作jpg来保存,防止了getshell 但是并没有对来源做限制 通过file://协议 就能任意读取本地文件
文件保存后有一个是否为图像文件的检查 如果不是就直接删除,这里可以用条件竞争来赶在文件删除前读取数据,当然 前提是要知道文件名 再来看看保存的文件名是如何定义的
remote.class.php 行68
function set_savename($savename) {
global $DT_TIME;
if($savename) {
$this->savename = $this->adduserid ? str_replace('.'.$this->ext, $this->userid.'.'.$this->ext, $savename) : $savename;
} else {
$this->uptime = $DT_TIME;
$name = date('His', $this->uptime).rand(10, 99);
$this->savename = $this->adduserid ? $name.$this->userid.'.'.$this->ext : $name.'.'.$this->ext;
}
$this->saveto = $this->savepath.$this->savename;
if(!$this->overwrite && is_file(DT_ROOT.'/'.$this->saveto)) {
$i = 1;
while($i) {
$saveto = str_replace('.'.$this->ext, '('.$i.').'.$this->ext, $this->saveto);
if(is_file(DT_ROOT.'/'.$saveto)) {
$i++;
continue;
} else {
$this->saveto = $saveto;
break;
}
}
}
}
在remote过程中 并没有初始化$savename 所以进入else逻辑 文件名就是
时间+两位数字+uid 还是比较弱的
网友评论