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:\wamp\www\dedecms5.5 1) D:\wamp\www\dedecms5.5\plus\mytag_js.php: 路径命中、内容正则匹配成功 2) D:\wamp\www\dedecms5.5\plus\ad_js.php: 未命中 2. D:\wamp\www\dedecms5.7 1) D:\wamp\www\dedecms5.7\plus\mytag_js.php: 路径命中、内容正则匹配成功 2) D:\wamp\www\dedecms5.7\plus\ad_js.php: 路径命中、内容正则匹配成功 则最后的结果为: D:\wamp\www\dedecms5.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>\plus\mytag_js.php</PATH> <PATTERN>\$pv->SetTemplet</PATTERN> </RULE> <RULE> <PATH>\plus\ad_js.php</PATH> <PATTERN>\$dsql->GetOne</PATTERN> </RULE> </SEARCHPATHRULE> <VERSIONINFO> <PATH>\data\admin\ver.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>\api\uc.php</PATH> <PATTERN>API_RETURN_SUCCEED;</PATTERN> </RULE> <RULE> <PATH>\source\module\member\member_activate.php</PATH> <PATTERN>getuserbyuid</PATTERN> </RULE> </SEARCHPATHRULE> <VERSIONINFO> <PATH>\source\discuz_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>\api\uc.php</PATH> <PATTERN>API_RETURN_SUCCEED;</PATTERN> </RULE> <RULE> <PATH>\manyou\userapp.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>\libraries\core.lib.php</PATH> <PATTERN>PMA_ifSetOr</PATTERN> </RULE> <RULE> <PATH>\libraries\common.inc.php</PATH> <PATTERN>PHPMYADMIN</PATTERN> </RULE> </SEARCHPATHRULE> <VERSIONINFO> <PATH>\libraries\Config.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>\inc\AspCms_CommonFun.asp</PATH> <PATTERN>createStreamFile</PATTERN> </RULE> <RULE> <PATH>\inc\AspCms_SettingClass.asp</PATH> <PATTERN>setcharset</PATTERN> </RULE> </SEARCHPATHRULE> <VERSIONINFO> <PATH>\inc\AspCms_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-admin\credits.php</PATH> <PATTERN>wp_credits</PATTERN> </RULE> <RULE> <PATH>\wp-admin\canonical.php</PATH> <PATTERN>redirect_canonical</PATTERN> </RULE> </SEARCHPATHRULE> <VERSIONINFO> <PATH>\wp-includes\version.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>\api\uc.php</PATH> <PATTERN>API_RETURN_SUCCEED;</PATTERN> </RULE> <RULE> <PATH>\includes\cls_template.php</PATH> <PATTERN>make_compiled</PATTERN> </RULE> </SEARCHPATHRULE> <VERSIONINFO> <PATH>\includes\cls_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>\phpcms\base.php</PATH> <PATTERN>load_sys_class;</PATTERN> </RULE> <RULE> <PATH>\phpsso_server\api.php</PATH> <PATTERN>pc_base::load_sys_class</PATTERN> </RULE> </SEARCHPATHRULE> <VERSIONINFO> <PATH>\caches\configs\version.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>\libraries\cms\application\cms.php</PATH> <PATTERN>afterSessionStart</PATTERN> </RULE> <RULE> <PATH>\libraries\cms\class\loader.php</PATH> <PATTERN>loadClass</PATTERN> </RULE> </SEARCHPATHRULE> <VERSIONINFO> <PATH>\libraries\cms\version\version.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>\e\web\atom.php</PATH> <PATTERN>RepSpeRssStr</PATTERN> </RULE> <RULE> <PATH>\e\DoInfo\ecms.php</PATH> <PATTERN>eCheckAccessDoIp</PATTERN> </RULE> </SEARCHPATHRULE> <VERSIONINFO> <PATH>\e\class\EmpireCMS_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>\member\includes\member.inc.php</PATH> <PATTERN>membertypelist</PATTERN> </RULE> <RULE> <PATH>\includes\codeimg.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>\module\brand\brand.class.php</PATH> <PATTERN>get_list</PATTERN> </RULE> <RULE> <PATH>\module\brand\admin\setting.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>\core\admin\controller\ctl.cent_save.php</PATH> <PATTERN>make_shopex_ac</PATTERN> </RULE> <RULE> <PATH>\core\admin\controller\member\ctl.member.php</PATH> <PATTERN>show_detail</PATTERN> </RULE> </SEARCHPATHRULE> <VERSIONINFO> <PATH>\core\version.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>\includes\models\partner.model.php</PATH> <PATTERN>reset_error_handler</PATTERN> </RULE> <RULE> <PATH>\admin\includes\priv.inc.php</PATH> <PATTERN>\$menu_data</PATTERN> </RULE> </SEARCHPATHRULE> <VERSIONINFO> <PATH>\eccore\ecmall.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