python安全编程之指纹识别
什么是cms
CMS是Content Management System的缩写,意为"内容管理系统",这是百度百科的解释,意思是相当于⽹站的建站模板,整个⽹站架构已经集成好了,只需要你部署和安装,便可以搭起⼀个⽹站,这样虽然⽅便了开发⼈员建设⽹站,但也带来新的安全问题,如果cms本⾝有安全问题如⼀些⾼危漏洞,那么使⽤这个cms的所有⽹站都会存在这种安全漏洞,所以我们在进⾏渗透测试的时候,如果可以探测出⽹站使⽤的框架,那么我们便可以寻这个框架的漏洞,从⽽成功拿下这个⽹站,所以在渗透过程中,探测⽹站的cms是⼀件很重要的事,⽹上有开源的常见的cms的字典库,我们可以⼿写⼀个cms识别程序来对cms进⾏识别,⽅便我们进⾏渗透。
常见的指纹识别⽅式
1、特定⽂件的MD5
⼀些⽹站的特定图⽚⽂件、js⽂件、CSS等静态⽂件,如favicon.ico、css、logo.ico、js等⽂件⼀般不会修改,通过爬⾍对这些⽂件进⾏抓取并⽐对md5值,如果和规则库中的Md5⼀致则说明是同⼀CMS。这种⽅式速度⽐较快,误报率相对低⼀些,但也不排除有些⼆次开发的CMS会修改这些⽂件。
2、正常页⾯或错误⽹页中包含的关键字
先访问⾸页或特定页⾯如等,通过正则的⽅式去匹配某些关键字,如Powered by Discuz、dedecms等。
或者可以构造错误页⾯,根据报错信息来判断使⽤的CMS或者中间件信息,⽐较常见的如tomcat的报错页⾯。
3、请求头信息的关键字匹配
根据⽹站response返回头信息进⾏关键字匹配,whatweb和Wappalyzer就是通过banner信息来快速识别指纹,之前fofa的web指纹库很多都是使⽤的这种⽅法,效率⾮常⾼,基本请求⼀次就可以,但搜集这些规则可能会耗时很长。⽽且这些banner信息有些很容易被改掉。
根据response header⼀般有以下⼏种识别⽅式:
查看http响应报头的X-Powered-By字段来识别;
根据Cookies来进⾏判断,⽐如⼀些waf会在返回头中包含⼀些信息,如360wzws、Safedog、yunsuo等;
根据header中的Server信息来判断,如DVRDVS-Webs、yunjiasu-nginx、Mod_Security、nginx-wallarm等;
根据WWW-Authenticate进⾏判断,⼀些路由交换设备可能存在这个字段,如NETCORE、huawei、h3c等设备。
4、部分URL中包含的关键字,⽐如wp-includes、dede等URL关键特征
通过规则库去探测是否有相应⽬录,或者根据爬⾍结果对链接url进⾏分析,或者对⽂件中⽬录进⾏检测等等⽅式,通过url地址来判别是否使⽤了某CMS,⽐如wordpress默认存在wp-includes和wp-admin⽬录,织梦默认管理后台为dede⽬录,solr平台可能使⽤/solr⽬录,weblogic可能使⽤wls-wsat⽬录等。
5、开发语⾔的识别
web开发语⾔⼀般常见的有PHP、jsp、aspx、asp等,常见的识别⽅式有:
通过爬⾍获取动态链接进⾏直接判断是⽐较简便的⽅法。
asp判别规则如下<a[^>]*?href=(‘|”)[^http][^>]*?\.asp(\?|\#|\1),其他语⾔可替换相应asp即可。
通过X-Powered-By进⾏识别
⽐较常见的有X-Powered-By: ASP.NET或者X-Powered-By: PHP/7.1.8
通过Set-Cookie进⾏识别
这种⽅法⽐较常见也很快捷,⽐如Set-Cookie中包含PHPSSIONID说明是php、包含JSESSIONID说明是java、包含ASP.NET_SessionId说明是aspx等。
下⾯是我在github上到的⼀个⼤佬写的cms脚本识别⼯具(⾃⼰写的就不放了,惨不忍睹),⼤佬写的很好,可以当做⽣产⼒⼯具来使⽤了。
import json#字典为json⽂件格式
织梦新闻博客网站模板import threading
import requests
import hashlib#⽤于md5加密
from concurrent.futures import ThreadPoolExecutor, as_completed, FIRST_EXCEPTION, wait, ALL_
COMPLETED
from optparse import OptionParser
#查cms静态⽂件,并计算哈希值,获取静态⽂件的url相对路径,根据此⽣成cms特征集
threadingLock = threading.Lock()
show_count = 0
SCAN_COMPLATED = False
def md5encode(text):#将关键字md5加密
m = hashlib.md5()
m.de("utf-8"))
return m.hexdigest()
def check_file_is_ok(url, path):
"""
head 请求⽅式去判断⽂件是否存在, 减少正⽂响应时间
:param url:
:param path:
:return:
"""
target = url + path#拼接url和路径
r = requests.head(target)
if r.status_code == 200:#判断页⾯状态码
return True
return False
def get_request_md5(url, path, pattern):
"""
通过请求路径获取内容的md5
:param url:
:param url:
:param path:
:param pattern:
:return:
"""
target = url + path
r = (target)
r_md5 = )
if pattern == r_md5:
return True
return False
def load_cms_fingers(fingers):
"""
加载CMS指纹
:return:
"""
with open(fingers) as f:
data = json.load(f)
print("Update Time: {}".("update_time")))
print("CMS Fingers Count: {}".format(len(data['data'])))
return data['data']
def read_url_file_to_list(filename):
"""
读 URL ⽂件为列表
:param filename:
:return:
"""
with open(filename) as f:
return [x.strip() for x adlines()]
def check_thread(item):
global show_count#在函数中调⽤全局变量
global SCAN_COMPLATED
url, finger = item
path = ("path")
path = path if path[0] == "/"else"/" + path
threadingLock.acquire()
show_count += 1
if not SCAN_COMPLATED:
print('\r', "扫描进度 {}/{}".format(show_count, fingers_count), end='', flush=True)    lease()
if check_file_is_ok(url, path):
match_pattern = ("match_pattern")
result = get_request_md5(url, path, match_pattern)
if result:
threadingLock.acquire()
if not SCAN_COMPLATED:
print("\nHint CMS名称: {}".("cms")))
print("Hint 指纹⽂件: {}".("path")))
print("Hint Md5: {}\n".("match_pattern")))
SCAN_COMPLATED = True
raise Exception("任务结束")
if__name__ == '__main__':
if__name__ == '__main__':
usage = "%prog -u \"xxxx\" -t threads_number"
parser = OptionParser(usage=usage)
print("指纹识别------2.0")
parser.add_option("-u", "--url", dest="url", help="⽬标URL")
parser.add_option("-f", "--file", dest="file", help="url⽂件", default=None)
parser.add_option("-s", "--fingers", dest="fingers", help="指定指纹⽂件", default="fingers_simple.json")
parser.add_option("-t", "--threads", dest="threads", type="int", default=10, help="线程⼤⼩, 默认为 10")
options, args = parser.parse_args()
if not options.url and not options.file:
parser.print_help()
exit(0)
fingers = load_cms_fingers(options.fingers)
if options.file:
urls = read_url_file_to_list(options.file)
else:
urls = [options.url]
for url in urls:
SCAN_COMPLATED = False
show_count = 0
print(" 扫描⽬标: {}".format(url))
fingers_count = len(fingers)
executor = ThreadPoolExecutor(max_workers=options.threads)
tasks = [executor.submit(check_thread, ((url, finger))) for finger in fingers]
wait(tasks, return_when=FIRST_EXCEPTION)
for task in reversed(tasks):
task.cancel()
wait(tasks, return_when=ALL_COMPLETED)
⼤佬的脚本是将cms的md5特征值以json格式存储为⼀个字典,调⽤字典对⽹站进⾏检测,同时还加⼊了验证机制,验证⽂件是否存在,减少响应时间等。⼤家可以学习下。
很多时候我们习惯⽤云悉等在线⼯具对cms进⾏识别,⼿写的这种脚本可能因为识别速度和精度问题⽐不上在线的⼯具强⼤,但是我们还是需要尝试⼿写⼀些⼯具,对于⼯具,我们不仅要会⽤,还要深挖其原理,尝试⾃⼰写,不能停留在脚本⼩⼦,等到技术积累到⼀定程度,我们⼿写的⼯具也可以成为⽣产⼒。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。