Automated CMS category, version identification (CMS vulnerability detection)

catalog

1. 引言
2. 不同CMS版本标的文件路径调研
3. Code Example

1. 引言

微软解决大量CVE补丁更新的检测时候,采取的思路不是根据MD5对单个漏洞文件(.dll、.sys)进行漏洞检测,而是采取基线检测的思路,对目标的.dll、.sys文件进行版本检测,如果当前版本不是最新的,则报告对应的可能存在的疑似漏洞

0x1: 技术方案

1. 识别WEB路径
    1) 进程启动参数
    2) 解析WEB容器配置文件

2. 定位CMS类型
    1) 从WEB根目录进行递归查找
    2) 根据相对路径、文本正则特征进行CMS类型定位
    3) 所有的规则(SEARCHPATHRULE)是逻辑与的关系,必须同时成立后,才能100%定位到该CMS类型
/*
需要注意的是:
有可能出现同一个WEB目录下同时存在同一类、但不同版本的CMS,在搜索的时候需要根据这些CMS的相对根目录分别进行正则匹配,最后统一统计结果,例如
1. D:wampwwwdedecms5.5
    1) D:wampwwwdedecms5.5plusmytag_js.php: 路径命中、内容正则匹配成功
    2) D:wampwwwdedecms5.5plusad_js.php: 未命中
2. D:wampwwwdedecms5.7
    1) D:wampwwwdedecms5.7plusmytag_js.php: 路径命中、内容正则匹配成功
    2) D:wampwwwdedecms5.7plusad_js.php: 路径命中、内容正则匹配成功

则最后的结果为: D:wampwwwdedecms5.7
*/

4. 识别CMS版本
将上一步得到的CMS目录根目录,和规则库中的版本标的文件的相对路径进行拼接,利用正则匹配从标的文件中获取版本信息数据
/*
对于CMS版本的识别,通用的思路如下
1. 寻找每个版本100%一定都会变化的"标的文件",计算它的MD5值,和事先计算好的最新版的"标的文件"的MD5进行对比
2. 根据相对路径寻找一个"版本信息文件",此文件中明文保存着当前的版本信息
*/

5. 计算当前获取的版本信息是否"小于"规则库中的版本信息(这里的小于需要在格式转换的基础上进行比较)
6. 特征的匹配、版本信息的提取采取正则规则进行,在正则规则中使用了一些非捕获分组、前后环视控制符,在提取结果的时候需要提取"第一个捕获子组匹配到的文本"

权衡之下,在判断版本的方案中,如果采用方案1的话如果规则库不及时更新的话,可能会造成大规模误报(用户本机的CMS版本高于规则中的版本,但是因为MD5不同也被报出来了),所以采用方案2是相对较合理的方案,这种方案要求规则制定的时候需要case by case地调研不同CMS标识版本信息的路径文件

Relevant Link:

http://www.cnblogs.com/LittleHann/p/4497977.html

2. 不同CMS版本标的文件路径调研

0x1: DEDECMS

<CMSVERSIONINFO>
    <ITEM>
        <NAME>DEDECMS</NAME>
        <SEARCHPATHRULE> 
            <RULE>
                <PATH>plusmytag_js.php</PATH>
                <PATTERN>$pv->SetTemplet</PATTERN>
            </RULE>
            <RULE>
                <PATH>plusad_js.php</PATH>
                <PATTERN>$dsql->GetOne</PATTERN>
            </RULE> 
        </SEARCHPATHRULE>
        <VERSIONINFO> 
            <PATH>dataadminver.txt</PATH>
            <PATTERN>[0-9]{8}</PATTERN>
        </VERSIONINFO> 
        <NEWESTVERSION>20150618</NEWESTVERSION>
    </ITEM> 
</CMSVERSIONINFO>

0X2: DISCUZ-X

<CMSVERSIONINFO>
    <ITEM>
        <NAME>DISCUZ-X</NAME>
        <SEARCHPATHRULE> 
            <RULE>
                <PATH>apiuc.php</PATH>
                <PATTERN>API_RETURN_SUCCEED;</PATTERN>
            </RULE>
            <RULE>
                <PATH>sourcemodulemembermember_activate.php</PATH>
                <PATTERN>getuserbyuid</PATTERN>
            </RULE> 
        </SEARCHPATHRULE>
        <VERSIONINFO> 
            <PATH>sourcediscuz_version.php</PATH>
            <PATTERN>(?<=DISCUZ_RELEASE)(?:.*?)([0-9]{8})</PATTERN>
        </VERSIONINFO> 
        <NEWESTVERSION>20150609</NEWESTVERSION>
    </ITEM> 
</CMSVERSIONINFO>

0x3: DISCUZ

Discuz的版本存在2个分支,Discuz(number)是老的分支现在已经不维护了,Discuz-X是新的分支,所以原则上如果检测到当前CMS为数字系列的,都一律报告存在低版本风险

Discuz!版本
版本维护级别
一般性使用问题
严重性使用问题
一般性安全问题
高危安全问题
Discuz!X3.2
Discuz!X3.1
x
Discuz!X3.0
×
x
Discuz!X2.5
×
×
x
Discuz!X2
×
×
×
Discuz!X1.5.1
×
×
×
Discuz!X1.5
×
×
×
≤ Discuz! 7.x
x
x
x
x
         
放弃维护版本
Discuz!X1.0、 Discuz!1.0~Discuz!7.2
<CMSVERSIONINFO>
    <ITEM>
        <NAME>DISCUZ</NAME>
        <SEARCHPATHRULE> 
            <RULE>
                <PATH>apiuc.php</PATH>
                <PATTERN>API_RETURN_SUCCEED;</PATTERN>
            </RULE>
            <RULE>
                <PATH>manyouuserapp.php</PATH>
                <PATTERN>userapp.php?script=user</PATTERN>
            </RULE> 
        </SEARCHPATHRULE>
        <VERSIONINFO> 
            <PATH>discuz_version.php</PATH>
            <PATTERN>(?<=DISCUZ_RELEASE)(?:.*?)([0-9]{8})</PATTERN>
        </VERSIONINFO> 
        <NEWESTVERSION>20101225</NEWESTVERSION>
    </ITEM> 
</CMSVERSIONINFO>

0x4: PHPMYADMIN

<CMSVERSIONINFO>
    <ITEM>
        <NAME>PHPMYADMIN</NAME>
        <SEARCHPATHRULE> 
            <RULE>
                <PATH>librariescore.lib.php</PATH>
                <PATTERN>PMA_ifSetOr</PATTERN>
            </RULE>
            <RULE>
                <PATH>librariescommon.inc.php</PATH>
                <PATTERN>PHPMYADMIN</PATTERN>
            </RULE> 
        </SEARCHPATHRULE>
        <VERSIONINFO> 
            <PATH>librariesConfig.class.php</PATH>
            <PATTERN>(?<=PMA_VERSION)(?:.*?)([0-9]{1,2}.[0-9]{1,2}.[0-9]{1,2})</PATTERN>
        </VERSIONINFO> 
        <NEWESTVERSION>4.5.1</NEWESTVERSION>
    </ITEM> 
</CMSVERSIONINFO>

0x5: ASPCMS

<CMSVERSIONINFO>
    <ITEM>
        <NAME>ASPCMS</NAME>
        <SEARCHPATHRULE> 
            <RULE>
                <PATH>incAspCms_CommonFun.asp</PATH>
                <PATTERN>createStreamFile</PATTERN>
            </RULE>
            <RULE>
                <PATH>incAspCms_SettingClass.asp</PATH>
                <PATTERN>setcharset</PATTERN>
            </RULE> 
        </SEARCHPATHRULE>
        <VERSIONINFO> 
            <PATH>incAspCms_Version.asp</PATH>
            <PATTERN>(?<="AspCms)(?:.*?)([0-9]{8})</PATTERN>
        </VERSIONINFO> 
        <NEWESTVERSION>20150901</NEWESTVERSION>
    </ITEM> 
</CMSVERSIONINFO>

0x6: WORDPRESS

<CMSVERSIONINFO>
    <ITEM>
        <NAME>WORDPRESS</NAME>
        <SEARCHPATHRULE> 
            <RULE>
                <PATH>wp-admincredits.php</PATH>
                <PATTERN>wp_credits</PATTERN>
            </RULE>
            <RULE>
                <PATH>wp-admincanonical.php</PATH>
                <PATTERN>redirect_canonical</PATTERN>
            </RULE> 
        </SEARCHPATHRULE>
        <VERSIONINFO> 
            <PATH>wp-includesversion.php</PATH>
            <PATTERN>(?<=wp_version)(?:.*?)([0-9]{1,2}.[0-9]{1,2}.[0-9]{1,2})</PATTERN>
        </VERSIONINFO> 
        <NEWESTVERSION>4.3.1</NEWESTVERSION>
    </ITEM> 
</CMSVERSIONINFO>

0x7: ECSHOP

<CMSVERSIONINFO>
    <ITEM>
        <NAME>ECSHOP</NAME>
        <SEARCHPATHRULE> 
            <RULE>
                <PATH>apiuc.php</PATH>
                <PATTERN>API_RETURN_SUCCEED;</PATTERN>
            </RULE>
            <RULE>
                <PATH>includescls_template.php</PATH>
                <PATTERN>make_compiled</PATTERN>
            </RULE> 
        </SEARCHPATHRULE>
        <VERSIONINFO> 
            <PATH>includescls_ecshop.php</PATH>
            <PATTERN>(?<=RELEASE)(?:.*?)([0-9]{8})</PATTERN>
        </VERSIONINFO> 
        <NEWESTVERSION>20121106</NEWESTVERSION>
    </ITEM> 
</CMSVERSIONINFO>

0x8: phpcmsv9

<CMSVERSIONINFO>
    <ITEM>
        <NAME>PHPCMSV9</NAME>
        <SEARCHPATHRULE> 
            <RULE>
                <PATH>phpcmsbase.php</PATH>
                <PATTERN>load_sys_class;</PATTERN>
            </RULE>
            <RULE>
                <PATH>phpsso_serverapi.php</PATH>
                <PATTERN>pc_base::load_sys_class</PATTERN>
            </RULE> 
        </SEARCHPATHRULE>
        <VERSIONINFO> 
            <PATH>cachesconfigsversion.php</PATH>
            <PATTERN>(?<=pc_release)(?:.*?)([0-9]{8})</PATTERN>
        </VERSIONINFO> 
        <NEWESTVERSION>20150812</NEWESTVERSION>
    </ITEM> 
</CMSVERSIONINFO>

0x9: JOOMLA

<CMSVERSIONINFO>
    <ITEM>
        <NAME>JOOMLA</NAME>
        <SEARCHPATHRULE> 
            <RULE>
                <PATH>librariescmsapplicationcms.php</PATH>
                <PATTERN>afterSessionStart</PATTERN>
            </RULE>
            <RULE>
                <PATH>librariescmsclassloader.php</PATH>
                <PATTERN>loadClass</PATTERN>
            </RULE> 
        </SEARCHPATHRULE>
        <VERSIONINFO> 
            <PATH>librariescmsversionversion.php</PATH>
            <PATTERN>(?<=RELEASE)(?:.*?)([0-9]{0,1}.[0-9]{0,1})</PATTERN>
        </VERSIONINFO> 
        <NEWESTVERSION>3.4</NEWESTVERSION>
    </ITEM> 
</CMSVERSIONINFO>

0X10: EMPIRECMS

<CMSVERSIONINFO>
    <ITEM>
        <NAME>EMPIRECMS</NAME>
        <SEARCHPATHRULE> 
            <RULE>
                <PATH>ewebatom.php</PATH>
                <PATTERN>RepSpeRssStr</PATTERN>
            </RULE>
            <RULE>
                <PATH>eDoInfoecms.php</PATH>
                <PATTERN>eCheckAccessDoIp</PATTERN>
            </RULE> 
        </SEARCHPATHRULE>
        <VERSIONINFO> 
            <PATH>eclassEmpireCMS_version.php</PATH>
            <PATTERN>(?<=EmpireCMS_LASTTIME)(?:.*?)([0-9]{12})</PATTERN>
        </VERSIONINFO> 
        <NEWESTVERSION>201502071030</NEWESTVERSION>
    </ITEM> 
</CMSVERSIONINFO>

0x11: PHPWEB

<CMSVERSIONINFO>
    <ITEM>
        <NAME>PHPWEB</NAME>
        <SEARCHPATHRULE> 
            <RULE>
                <PATH>memberincludesmember.inc.php</PATH>
                <PATTERN>membertypelist</PATTERN>
            </RULE>
            <RULE>
                <PATH>includescodeimg.inc.php</PATH>
                <PATTERN>SetDraw</PATTERN>
            </RULE> 
        </SEARCHPATHRULE>
        <VERSIONINFO> 
            <PATH>version.php</PATH>
            <PATTERN>(?<=PHPWEB_RELEASE)(?:.*?)([0-9]{8})</PATTERN>
        </VERSIONINFO> 
        <NEWESTVERSION>20100925</NEWESTVERSION>
    </ITEM> 
</CMSVERSIONINFO>

0x12: METINFO: 无法找到版本文件
0x13: drupal: 无法找到版本文件
0x14: coldfusion: 无法找到版本文件
0x15: z-blog: 无法找到版本文件

0x16: DESTOON

<CMSVERSIONINFO>
    <ITEM>
        <NAME>DESTOON</NAME>
        <SEARCHPATHRULE> 
            <RULE>
                <PATH>modulerandrand.class.php</PATH>
                <PATTERN>get_list</PATTERN>
            </RULE>
            <RULE>
                <PATH>modulerandadminsetting.inc.php</PATH>
                <PATTERN>update_setting</PATTERN>
            </RULE> 
        </SEARCHPATHRULE>
        <VERSIONINFO> 
            <PATH>version.inc.php</PATH>
            <PATTERN>(?<=DT_RELEASE)(?:.*?)([0-9]{8})</PATTERN>
        </VERSIONINFO> 
        <NEWESTVERSION>20151028</NEWESTVERSION>
    </ITEM> 
</CMSVERSIONINFO>

0x17: qibosoft: 无法找到版本文件

0x18: SHOPEX

<CMSVERSIONINFO>
    <ITEM>
        <NAME>SHOPEX</NAME>
        <SEARCHPATHRULE> 
            <RULE>
                <PATH>coreadmincontrollerctl.cent_save.php</PATH>
                <PATTERN>make_shopex_ac</PATTERN>
            </RULE>
            <RULE>
                <PATH>coreadmincontrollermemberctl.member.php</PATH>
                <PATTERN>show_detail</PATTERN>
            </RULE> 
        </SEARCHPATHRULE>
        <VERSIONINFO> 
            <PATH>coreversion.txt</PATH>
            <PATTERN>(?<=app)(?:.*?)([0-9]{0,1}.[0-9]{0,1}.[0-9]{0,1})</PATTERN>
        </VERSIONINFO> 
        <NEWESTVERSION>4.8.5</NEWESTVERSION>
    </ITEM> 
</CMSVERSIONINFO>

0x19: ECMALL

<CMSVERSIONINFO>
    <ITEM>
        <NAME>ECMALL</NAME>
        <SEARCHPATHRULE> 
            <RULE>
                <PATH>includesmodelspartner.model.php</PATH>
                <PATTERN>reset_error_handler</PATTERN>
            </RULE>
            <RULE>
                <PATH>adminincludespriv.inc.php</PATH>
                <PATTERN>$menu_data</PATTERN>
            </RULE> 
        </SEARCHPATHRULE>
        <VERSIONINFO> 
            <PATH>eccoreecmall.php</PATH>
            <PATTERN>(?<='VERSION)(?:.*?)([0-9]{0,1}.[0-9]{0,1}.[0-9]{0,1})</PATTERN>
        </VERSIONINFO> 
        <NEWESTVERSION>2.3.0</NEWESTVERSION>
    </ITEM> 
</CMSVERSIONINFO>

Relevant Link:

http://blog.sina.com.cn/s/blog_67c986fc0100w77z.html

3. Code Example

index.php

<?php
    header("Content-type: text/html; charset=utf-8"); 
    set_time_limit(0);
    error_reporting(E_ALL);

    include "common.lib.php";

    if (!empty($_POST)) 
    {
        if( !empty($_POST['submit']) && !empty($_POST['filepath']) )
        { 
            $_filepath = $_POST['filepath'];
            $fileList = getFileList($_filepath);

            $ruleValues = parseXMLRule("rule.xml"); 
            foreach ($ruleValues as $ruleValuesItem) 
            {
                $name = $ruleValuesItem["NAME"];
                $versionino = $ruleValuesItem["VERSIONINFO"][0];
                $newestversion = $ruleValuesItem["NEWESTVERSION"];
                //获取相对路径、正则内容全匹配成功的CMS根目录(prefix)
                $hintPath = isSomeCMSTypeHint($fileList, $ruleValuesItem["SEARCHPATHRULE"]);

                //遍历所有CMS根目录,获取对应的版本信息
                foreach ($hintPath as $hintPathValue) 
                {
                    $pattern = "/" . $versionino["PATTERN"] . "/sim";
                    if (preg_match($pattern, file_get_contents($hintPathValue . $versionino["PATH"]), $matchs)) 
                    { 
                        $currentVersion = end($matchs);
                        //版本比较
                        if ( CompareVersion($currentVersion, $newestversion) == -1 ) 
                        {
                            echo "$name: $hintPathValue is not newest version(current: $currentVersion. newest: $newestversion)" . "<br />";
                        }
                        else
                        {
                            echo "$name: $hintPathValue is newest version($newestversion)" . "<br />";
                        }
                    }
                    else
                    {
                        die("get version info faild!");
                    }
                }
                
            } 
        }
    }
?>

<html>
<body>

<h1>主机层WEB漏洞扫描测试平台</h1> 

<form action="" method="POST">
    <label for="filepath">FilePath:</label>
    <input type="text" name="filepath" id="filepath" value="D:/wamp/www"/> 
    <br />
    <input type="submit" name="submit" value="Submit" />
</form>

common.lib.php

<?php
    
    /**
    * 
    */
    class ruleObjecy  
    {
        
        function __construct()
        {
            # code...
        }
    }

    function get_extension($file) 
    { 
        return pathinfo($file, PATHINFO_EXTENSION); 
    } 

    $files = array(); 
    //递归获取指定目录下所有文件
    function getFileList($directory) 
    {        
        global $files;
        //需要过滤的白名单文件名
        $whitelist = array(
                0 => ".",
                1 => ".." 
            );     
        //需要枚举的目标文件后缀
        $extlist = array(
                0 => "php"
                //1 => "txt" 
            );

        if(is_dir($directory)) 
        {        
            if($dh = opendir($directory)) 
            {        
                while(($file = readdir($dh)) !== false) 
                {     
                    $white_hint = false;
                    foreach ($whitelist as $key => $value) 
                    {
                        if ($value !== $file) 
                        {
                            $white_hint = false;
                        }
                        else
                        {
                            //命中一次即退出
                            $white_hint = true;
                            break;
                        }    
                    }
                    //判断是否命中白名单
                    if ($white_hint === false) 
                    {
                        //递归遍历
                        $curDir = $directory . "/" . $file;
                        if(is_dir($curDir)) 
                        { 
                            getFileList($curDir);
                        }

                        //判断是否是目标后缀
                        foreach ($extlist as $extValue) 
                        {
                            $fileExt = get_extension($file);
                            if ($fileExt == $extValue) 
                            {
                                 $files[] = $directory . "/" . $file;  
                                 break;
                            }  
                        } 
                    } 
                }    
                //关闭文件夹句柄
                closedir($dh);        
            }        
        }        
        return $files;        
    }   


    $CMSVERSIONINFO = array(
        0 => array(
            "NAME" => "DEDECMS",
            "SEARCHPATHRULE" => array(
                0 => array("PATH" => "/plus/mytag_js.php", "PATTERN" => "\$pv->SetTemplet"),
                1 => array("PATH" => "/plus/ad_js.php", "PATTERN" => "\$dsql->GetOne")
            ),
            "VERSIONINFO" => array(
                0 => array("PATH" => "/data/admin/ver.txt", "PATTERN" => "[0-9]{8}")
            ),
            "NEWESTVERSION" => "20150618"
        ),
        1 => array(
            "NAME" => "DISCUZ",
            "SEARCHPATHRULE" => array(
                0 => array("PATH" => "/api/uc.php", "PATTERN" => "API_RETURN_SUCCEED;"),
                1 => array("PATH" => "/manyou/userapp.php", "PATTERN" => "userapp.php\?script=user")
            ),
            "VERSIONINFO" => array(
                0 => array("PATH" => "/discuz_version.php", "PATTERN" => "(?<=DISCUZ_RELEASE)(?:.*?)([0-9]{8})")
            ),
            "NEWESTVERSION" => "20101225"
        ),
        2 => array(
            "NAME" => "DISCUZ-X",
            "SEARCHPATHRULE" => array(
                0 => array("PATH" => "/api/uc.php", "PATTERN" => "API_RETURN_SUCCEED;"),
                1 => array("PATH" => "/source/module/member/member_activate.php", "PATTERN" => "getuserbyuid")
            ),
            "VERSIONINFO" => array(
                0 => array("PATH" => "/source/discuz_version.php", "PATTERN" => "(?<=DISCUZ_RELEASE)(?:.*?)([0-9]{8})")
            ),
            "NEWESTVERSION" => "20150609"
        ),
        3 => array(
            "NAME" => "PHPMYADMIN",
            "SEARCHPATHRULE" => array(
                0 => array("PATH" => "/libraries/core.lib.php", "PATTERN" => "PMA_ifSetOr"),
                1 => array("PATH" => "/libraries/common.inc.php", "PATTERN" => "PHPMYADMIN")
            ),
            "VERSIONINFO" => array(
                0 => array("PATH" => "/libraries/Config.class.php", "PATTERN" => "(?<=PMA_VERSION)(?:.*?)([0-9]{1,2}.[0-9]{1,2}.[0-9]{1,2})")
            ),
            "NEWESTVERSION" => "4.5.1"
        ),
        4 => array(
            "NAME" => "ASPCMS",
            "SEARCHPATHRULE" => array(
                0 => array("PATH" => "/inc/AspCms_CommonFun.asp", "PATTERN" => "createStreamFile"),
                1 => array("PATH" => "/inc/AspCms_SettingClass.asp", "PATTERN" => "setcharset")
            ),
            "VERSIONINFO" => array(
                0 => array("PATH" => "/inc/AspCms_Version.asp", "PATTERN" => "(?<="AspCms)(?:.*?)([0-9]{8})")
            ),
            "NEWESTVERSION" => "20150901"
        ),
        5 => array(
            "NAME" => "WORDPRESS",
            "SEARCHPATHRULE" => array(
                0 => array("PATH" => "/wp-admin/credits.php", "PATTERN" => "credits"),
                1 => array("PATH" => "/wp-admin/canonical.php", "PATTERN" => "redirect_canonical")
            ),
            "VERSIONINFO" => array(
                0 => array("PATH" => "/wp-includes/version.php", "PATTERN" => "(?<=wp_version)(?:.*?)([0-9]{1,2}\.[0-9]{1,2}\.[0-9]{1,2})")
            ),
            "NEWESTVERSION" => "4.3.1"
        ),
        6 => array(
            "NAME" => "ECSHOP",
            "SEARCHPATHRULE" => array(
                0 => array("PATH" => "/api/uc.php", "PATTERN" => "API_RETURN_SUCCEED;"),
                1 => array("PATH" => "/includes/cls_template.php", "PATTERN" => "make_compiled")
            ),
            "VERSIONINFO" => array(
                0 => array("PATH" => "/includes/cls_ecshop.php", "PATTERN" => "(?<=RELEASE)(?:.*?)([0-9]{8})")
            ),
            "NEWESTVERSION" => "20121106"
        ),
        7 => array(
            "NAME" => "PHPCMSV9",
            "SEARCHPATHRULE" => array(
                0 => array("PATH" => "/phpcms/base.php", "PATTERN" => "load_sys_class;"),
                1 => array("PATH" => "/phpsso_server/api.php", "PATTERN" => "pc_base::load_sys_class")
            ),
            "VERSIONINFO" => array(
                0 => array("PATH" => "/caches/configs/version.php", "PATTERN" => "(?<=pc_release)(?:.*?)([0-9]{8})")
            ),
            "NEWESTVERSION" => "20150812"
        ),
        8 => array(
            "NAME" => "JOOMLA",
            "SEARCHPATHRULE" => array(
                0 => array("PATH" => "/libraries/cms/application/cms.php", "PATTERN" => "afterSessionStart;"),
                1 => array("PATH" => "/libraries/cms/class/loader.php", "PATTERN" => "loadClass")
            ),
            "VERSIONINFO" => array(
                0 => array("PATH" => "/libraries/cms/version/version.php", "PATTERN" => "(?<=RELEASE)(?:.*?)([0-9]{0,1}.[0-9]{0,1})")
            ),
            "NEWESTVERSION" => "3.4"
        ),    
        9 => array(
            "NAME" => "EMPIRECMS",
            "SEARCHPATHRULE" => array(
                0 => array("PATH" => "/e/web/atom.php", "PATTERN" => "RepSpeRssStr"),
                1 => array("PATH" => "/e/DoInfo/ecms.php", "PATTERN" => "eCheckAccessDoIp")
            ),
            "VERSIONINFO" => array(
                0 => array("PATH" => "/e/class/EmpireCMS_version.php", "PATTERN" => "(?<=EmpireCMS_LASTTIME)(?:.*?)([0-9]{12})")
            ),
            "NEWESTVERSION" => "201502071030"
        ),    
        10 => array(
            "NAME" => "PHPWEB",
            "SEARCHPATHRULE" => array(
                0 => array("PATH" => "/member/includes/member.inc.php", "PATTERN" => "membertypelist"),
                1 => array("PATH" => "/includes/codeimg.inc.php", "PATTERN" => "SetDraw")
            ),
            "VERSIONINFO" => array(
                0 => array("PATH" => "/version.php", "PATTERN" => "(?<=PHPWEB_RELEASE)(?:.*?)([0-9]{8})")
            ),
            "NEWESTVERSION" => "20100925"
        ),    
        11 => array(
            "NAME" => "DESTOON",
            "SEARCHPATHRULE" => array(
                0 => array("PATH" => "/module/brand/brand.class.php", "PATTERN" => "get_list"),
                1 => array("PATH" => "/module/brand/admin/setting.inc.php", "PATTERN" => "update_setting")
            ),
            "VERSIONINFO" => array(
                0 => array("PATH" => "/version.inc.php", "PATTERN" => "(?<=DT_RELEASE)(?:.*?)([0-9]{8})")
            ),
            "NEWESTVERSION" => "20151028"
        ),    
        12 => array(
            "NAME" => "SHOPEX",
            "SEARCHPATHRULE" => array(
                0 => array("PATH" => "/core/admin/controller/ctl.cent_save.php", "PATTERN" => "make_shopex_ac"),
                1 => array("PATH" => "/core/admin/controller/member/ctl.member.php", "PATTERN" => "show_detail")
            ),
            "VERSIONINFO" => array(
                0 => array("PATH" => "/core/version.txt", "PATTERN" => "(?<=app)(?:.*?)([0-9]{0,1}.[0-9]{0,1}.[0-9]{0,1})")
            ),
            "NEWESTVERSION" => "4.8.5"
        ),    
        13 => array(
            "NAME" => "ECMALL",
            "SEARCHPATHRULE" => array(
                0 => array("PATH" => "/includes/models/partner.model.php", "PATTERN" => "reset_error_handler"),
                1 => array("PATH" => "/admin/includes/priv.inc.php", "PATTERN" => "\$menu_data")
            ),
            "VERSIONINFO" => array(
                0 => array("PATH" => "/eccore/ecmall.php", "PATTERN" => "(?<='VERSION)(?:.*?)([0-9]{0,1}\.[0-9]{0,1}\.[0-9]{0,1})")
            ),
            "NEWESTVERSION" => "2.3.0"
        )        
    ); 

    //解析XML格式的规则文件,返回多维数组
    function parseXMLRule($filePath)
    {  
        global $CMSVERSIONINFO;
        return $CMSVERSIONINFO;
    }


    function isSomeCMSTypeHint($fileList, $ruleValues)
    {  
        //有可能出现同一个WEB目录下同时存在同一类、但不同版本的CMS,在搜索的时候需要根据这些CMS的相对根目录(prefix)建立索引,分别进行正则匹配,最后统一统计结果
        $ruleSearchLogger = array();
        $result = array();

        //rule
        foreach ($ruleValues as $seatchruleItem) 
        { 
            $searchpath = $seatchruleItem["PATH"];
            $pattern = $seatchruleItem["PATTERN"];
            $pattern = "/" . $pattern . "/sim";

            //file list
            foreach ($fileList as $fileListItem) 
            { 
                //1. find relevant filepath 
                //防止出现/plus/mytag_js.php.txt这种情况也被误匹配到
                if (stripos($fileListItem, $searchpath) !== false && substr($fileListItem, stripos($fileListItem, $searchpath)) == $searchpath) 
                {  
                    //2. regex content match
                    if(preg_match($pattern, file_get_contents($fileListItem), $matches))
                    {
                        $prefix = substr($fileListItem, 0, strpos($fileListItem, $searchpath));
                        $ruleSearchLogger[$prefix][$searchpath] = 0;  
                    }
                }
            }
        }
 
        //判断同时满足所有路径规则的CMS根目录前缀
        foreach ($ruleValues as $seatchruleItem) 
        {
            $searchpath = $seatchruleItem["PATH"];
            foreach ($ruleSearchLogger as $prefix => $ruleSearchLoggerValue) 
            { 
                if ( array_key_exists($searchpath, $ruleSearchLoggerValue) ) 
                {
                    $ruleSearchLogger[$prefix][$searchpath] = 1;
                }
                else
                { 
                    $ruleSearchLogger[$prefix][$searchpath] = 0;
                }
            }
        } 
        
        //过滤出完整命中的路径前缀
        foreach ($ruleSearchLogger as $prefix => $ruleSearchLoggerValue) 
        {
            $isFound = 0;

            foreach ($ruleSearchLoggerValue as  $value) 
            {
                if ($value == 1) 
                {
                    $isFound = 1;
                    continue;
                }
                else
                {
                    $isFound = 0;
                    break;
                }
            }

            if ($isFound == 1) 
            {
                $result[] = $prefix;
            }
        } 

        return $result;
    }


    /*
    1. 纯数字型版本、2. 点分计数型版本
    return: 
    -1: <
    0: =
    1: >
    */
    function CompareVersion($currentVersion, $newestversion)
    { 
        if($currentVersion == $newestversion) return 0;

        //4.5.6: 点分型
        if (preg_match("/[0-9]{1,2}\./sim", $currentVersion) && preg_match("/[0-9]{1,2}\./sim", $newestversion)) 
        {

            $verArray1 =  explode($currentVersion, ".");
            $verArray2 =  explode($newestversion, ".");

            $count = count($verArray1) < count($verArray2) ? count($verArray1) : count($verArray2);

            for ($i = 0; $i < $count; $i++)
            { 
                if ( intval($verArray1[$i]) < intval($verArray2[$i]) ) return -1;        //从主版本开始逐段检测,只要出现一次小于的,就说明 $currentVersion < $newestversion
                else if ( intval($verArray1[$i]) > intval($verArray2[$i]) ) return 1;    //从主版本开始逐段检测,只要出现一次小于的,就说明 $currentVersion < $newestversion
            }

            //在全等的情况下,判断$currentVersion、$newestversion长度
            return count($verArray1) >= count($verArray2) ? 1 : -1;
        }
        //20141025: 纯数字型
        else if (preg_match("/[0-9]{6,}/sim", $currentVersion) && preg_match("/[0-9]{6,}/sim", $newestversion)) 
        {
            if ($currentVersion < $newestversion) 
            {
                return -1;
            }
            else 
            {
                return $currentVersion == $newestversion ? 0 : 1;
            }
        }
        

        
    }


?>

0x1: 版本比较

版本比较需要考虑到多种情况

1. 获取当前版本失败、获取的当前版本和配置里的基线配置参数格式不一致,遵循"宁可漏报不能误报"的原则,选择忽略
2. 格式相同、且长度不相同
    1) 点分格式: 逐段判断
    2) 纯数字形式: 解析为年-月-日后逐段判断
3. 格式相同,长度不同
将长度段的版本号补全,例如: 3.5.7 compare 3.5 => 3.5.7 compare 3.5.0

Copyright (c) 2015 LittleHann All rights reserved

原文地址:https://www.cnblogs.com/LittleHann/p/4916633.html