最近正在开发一款基于PHP实现的Web安全检测平台,写到了CMS识别这一功能,便写一篇文章总结一下。
首先需要梳理的是CMS识别的几种方法:
1.网页源代码特征:例如源代码中包含CMS的名称或是某种特定关键词。
2.路径/文件特征:例如DeDe织梦系统存在/dede/路径与advancedsearch.php文件。
3.版权信息特征:在网页底部的版权信息中往往会包含CMS信息,这种特征在我们接下来的编程中可以包含在"网页源代码特征"中。
4.robots.txt特征:部分CMS的robots.txt文件中会包含CMS信息,例如Discuz论坛系统。
除了这四种特征以外,还有其他的一些特征这里就不多阐述了,我们接下来就要围绕这4种特征来实现基于PHP的CMS识别功能。
在开始编程前,我们先根据4种特征来设计一下各自识别CMS的编程思路:
在开始编程前,我们先根据4种特征来设计一下各自识别CMS的编程思路:
1.网页源代码特征:发送请求获取网页源码 -> 利用正则匹配关键词
2.路径/文件特征:发送请求获取HTTP状态码 -> 根据HTTP状态码判断路径/文件是否存在
3.版权信息特征:发送请求获取网页源码 -> 利用正则匹配关键词(与网页源代码特征编程思路相同)
4.robots.txt特征: 发送请求获取HTTP状态码 -> 根据HTTP状态码判断robots.txt文件是否存在 -> 若存在则使用正则匹配关键词
以上便是4种特征的编程实现思路,同时,为了保证识别的准确性,我们需要对一个CMS添加多种识别方式,防止漏报或误报:
例如判断DeDe织梦系统时,我们除了可以依据robots.txt文件存在"Disallow: /plus/"这一关键词判断外,还可以检测源代码中是否存在"dedeajax"的关键词,只要满足以上任一条件即可判定为DeDe织梦系统。
下面开始编写我们的主要几个功能:
//获取HTTP状态码函数: function requests_code($url){ $curl = curl_init(); $header = array("Connection: Keep-Alive","Accept: text/html, application/xhtml+xml, */*", "Pragma: no-cache", "Accept-Language: zh-Hans-CN,zh-Hans;q=0.8,en-US;q=0.5,en;q=0.3","User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)"); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_HEADER, 1); curl_setopt($curl, CURLOPT_HTTPHEADER, $header); curl_setopt($curl,CURLOPT_NOBODY,true); curl_setopt($curl,CURLOPT_SSL_VERIFYPEER, false); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); curl_exec($curl); $code = curl_getinfo($curl,CURLINFO_HTTP_CODE); curl_close($curl); return $code; } //获取网页源代码正则匹配函数: function contents_match($url, $regex){ $curl = curl_init(); $header = array("Connection: Keep-Alive","Accept: text/html, application/xhtml+xml, */*", "Pragma: no-cache", "Accept-Language: zh-Hans-CN,zh-Hans;q=0.8,en-US;q=0.5,en;q=0.3","User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)"); curl_setopt($curl, CURLOPT_URL,$url); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curl, CURLOPT_HTTPHEADER, $header); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); $data = curl_exec($curl); curl_close ($curl); if(preg_match($regex, $data)){ return True; }else{ return False; } }
以上两个功能我们使用自定义函数实现能使代码更加简介易懂,接下来我们开始编写不同CMS的识别策略:
//Discuz论坛系统网站特征 function dz($url){ $regex = "/Discuz/i"; if(contents_match($url, $regex)){ //网页源代码特征 return True; }elseif(contents_match($url.'/robots.txt', $regex)){ //robots.txt文件特征 return True; }else{ return False; } } //ECshop网店商城系统网站特征 function ecshop($url){ $contents_regex = "/process_request/"; $path = "/themes/default/images/logo.gif"; if(contents_match($url, $contents_regex)){ //网页源代码特征 return True; }else if(requests_code($url.$path) == 200){ //robots.txt文件特征 return True; }else{ return False; } }
这里就展示两种CMS的识别方式,如果对更多CMS识别有兴趣可以联系笔者一起交流。这样我们就实现了PHP识别CMS的核心程序,接下来只需要调用各个函数使用if语句判断即可,加上百万前端工程师的美化,文末展示一下最终的效果: