什么是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、正常页面或错误网页中包含的关键字

先访问首页或特定页面如robots.txt等,通过正则的方式去匹配某些关键字,如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进行分析,或者对robots.txt文件中目录进行检测等等方式,通过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.update(text.encode("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 path:
:param pattern:
:return:
"""
target = url + path
r = requests.get(target) r_md5 = md5encode(r.text) 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: {}".format(data.get("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 in f.readlines()]
def check_thread(item):
global show_count#在函数中调用全局变量
global SCAN_COMPLATED
url, finger = item
path = finger.get("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)
threadingLock.release() if check_file_is_ok(url, path):
match_pattern = finger.get("match_pattern") result = get_request_md5(url, path, match_pattern) if result:
threadingLock.acquire()
if not SCAN_COMPLATED:
print("\nHint CMS名称: {}".format(finger.get("cms")))
print("Hint 指纹文件: {}".format(finger.get("path")))
print("Hint Md5: {}\n".format(finger.get("match_pattern")))
SCAN_COMPLATED = True
threadingLock.release()
raise Exception("任务结束")
threadingLock.release()
if __name__ == '__main__':
usage = "%prog -u \"http://xxxx.com\" -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进行识别,手写的这种脚本可能因为识别速度和精度问题比不上在线的工具强大,但是我们还是需要尝试手写一些工具,对于工具,我们不仅要会用,还要深挖其原理,尝试自己写,不能停留在脚本小子,等到技术积累到一定程度,我们手写的工具也可以成为生产力。

python安全编程之指纹识别的更多相关文章

  1. 使用C#winform编写渗透测试工具--Web指纹识别

    使用C#winform编写渗透测试工具--web指纹识别 本篇文章主要介绍使用C#winform编写渗透测试工具--Web指纹识别.在渗透测试中,web指纹识别是信息收集关键的一步,通常是使用各种工具 ...

  2. WAF指纹识别和XSS过滤器绕过技巧

    [译文] -- “Modern Web Application Firewalls Fingerprinting and Bypassing XSS Filters” 0x1 前言 之前在乌云drop ...

  3. Python高级编程–正则表达式(习题)

    原文:http://start2join.me/python-regex-answer-20141030/ ############################################## ...

  4. 设备指纹识别之User Agent 解析

    设备指纹识别之User Agent 解析User Agent 解析 zoerywzhou@163.com http://www.cnblogs.com/swje/ 作者:Zhouwan 2017-4- ...

  5. 基于STM32单片机光学指纹识别模块(FPM10A)全教程(基于C语言)

    本文转载,其来源在参考中:1,稍加修改,因为近期使用到这个模块,故而加以整理! 1.平台 首先我使用的是 奋斗 STM32 开发板 MINI板 基于STM32单片机光学指纹识别模块(FPM10A)全教 ...

  6. python网络编程基础(线程与进程、并行与并发、同步与异步、阻塞与非阻塞、CPU密集型与IO密集型)

    python网络编程基础(线程与进程.并行与并发.同步与异步.阻塞与非阻塞.CPU密集型与IO密集型) 目录 线程与进程 并行与并发 同步与异步 阻塞与非阻塞 CPU密集型与IO密集型 线程与进程 进 ...

  7. Python并发编程二(多线程、协程、IO模型)

    1.python并发编程之多线程(理论) 1.1线程概念 在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程 线程顾名思义,就是一条流水线工作的过程(流水线的工作需要电源,电源就相当于 ...

  8. Kali Linux渗透测试实战 2.2 操作系统指纹识别

    目录 2.2 操作系统指纹识别 2.2.1 Banner抓取 2.2.2 TCP 和 ICMP 常规指纹识别技术 TCP数据报格式 ICMP首部格式 TTL与TCP窗口大小 FIN探测 BOGUS f ...

  9. 《Python计算机视觉编程》

    <Python计算机视觉编程> 基本信息 作者: (美)Jan Erik Solem 译者: 朱文涛 袁勇 丛书名: 图灵程序设计丛书 出版社:人民邮电出版社 ISBN:978711535 ...

随机推荐

  1. Oracle对大表进行delete注意事项

    如果对大表进行大量的delete和update,那么可以注意一下如下说明: (1) 查看执行计划,如果说删除的记录很多,走索引的成本会比全表扫描更大,因为更新数据时还需要做一些约束校验和创建index ...

  2. 65.QT-UDP组播实现多人共享桌面(同时支持收发显示)

    这里我们只是简单学习下通过udp组播如何共享桌面demo.帧率上面比较低,毕竟没有用推流,只是简单的将图片发送到组播地址,而加入组播地址的客户端去取数据显示而已. 主要是为了学习UDP知识而写的,真的 ...

  3. 看完互联网大佬的「LeetCode 刷题手册」, 手撕了 400 道 Leetcode 算法题

    大家好,我是 程序员小熊 ,来自 大厂 的程序猿.相信绝大部分程序猿都有一个进大厂的梦想,但相较于以前,目前大厂的面试,只要是研发相关岗位,算法题基本少不了,所以现在很多人都会去刷 Leetcode ...

  4. 13、linux中用户和用户组

    linux是多用户多进程的系统: 每个文件和进程都需要应对一个用户和用户组: linux系统通过uid和gid来识别用户和组的: 一个用户必须要有唯一的uid和一个主组来识别身份,不同的用户可以使用同 ...

  5. 一、.Net Core 依赖注入详解及Autofac使用

    .NET中的依赖注入实际上帮助我们解耦了我们的代码,是控制反转和依赖反转原则的具体实现. .Net Core的依赖注入的好处: 1. application 更稳定,容易维护和演化: 2. 实现细节的 ...

  6. 利用C语言判别输入数的位数并正逆序输出

    利用C语言判别用户输入数的位数并正逆序输出 #include <stdio.h> void main() {        int i, scanfNum, printfNum, temp ...

  7. Linux基础 -03

    2.2.3 head-tail 命令 #------head #head pass #查看头部内容,默认前10行 #head -n5 pass #查看头部前5行,使用-n指定 #-------tail ...

  8. Kafka:Springboot整合Kafka消息队列

    本文主要分享下Spring Boot和Spring Kafka如何配置整合,实现发送和接收来自Spring Kafka的消息. 项目结构 pom依赖包 <?xml version="1 ...

  9. java基础---java8 新特性

    1. 函数式接口 函数式接口主要指只包含一个抽象方法的接口,如:java.lang.Runnable(java1.0).java.util.Comparator接口(java1.4)等. Java8提 ...

  10. 题解 guP4552 IncDec Sequence

    这道题是一道差分的题目 差分数组p即p[i]=a[i]-a[i-1] 如果我们把一个区间[l,r]里的数+1,那么我们不难发现p[l]'=a[l]+1-a[l-1]=p[l]+1,p[r+1]'=a[ ...