├── Frog-Fp.py ├── README.md ├── check.png ├── check.py ├── config.py ├── core ├── banner.py ├── ffuf.py ├── hb.py ├── parse.py └── rad.py ├── ffuf ├── dict.txt ├── ffuf_linux └── ffuf_win.exe ├── fingerprint ├── fp-74cms-get.yml ├── fp-ActiveMQ-get.yml ├── fp-Cacti-get.yml ├── fp-Canal-Admin-get.yml ├── fp-Coremail-get.yml ├── fp-Druid-get.yml ├── fp-Drupal-get.yml ├── fp-E-Bridge-get.yml ├── fp-E-mobile-get.yml ├── fp-EAS-get.yml ├── fp-Exchange-get.yml ├── fp-FineReport-get.yml ├── fp-FusionAuth-get.yml ├── fp-GRP-U8-get.yml ├── fp-GitLab-get.yml ├── fp-H3C_switch-get.yml ├── fp-Harbor-get.yml ├── fp-JBoss-Console-get.yml ├── fp-JumpServer-get.yml ├── fp-Kibana-get.yml ├── fp-KubeSphere-get.yml ├── fp-Liferay-get.yml ├── fp-Login-get.yml ├── fp-NC-get.yml ├── fp-Nexus-get.yml ├── fp-Pulse-VPN-get.yml ├── fp-Sangfor-VPN-get.yml ├── fp-SpringBoot-get.yml ├── fp-Struts2-get.yml ├── fp-Upload-get.yml ├── fp-WebSphere-get.yml ├── fp-Weblogic-console-get.yml ├── fp-adminer-get.yml ├── fp-apereo-cas-get.yml ├── fp-axis2-get.yml ├── fp-confluence-get.yml ├── fp-consul-get.yml ├── fp-dubbo-get.yml ├── fp-ecologyOA-get.yml ├── fp-emessage-get.yml ├── fp-fastadmin-get.yml ├── fp-fastjson-post.yml ├── fp-flink-get.yml ├── fp-flink-md5.yml ├── fp-git-get.yml ├── fp-jenkins-get.yml ├── fp-jira-get.yml ├── fp-joomla-get.yml ├── fp-joomla-md5.yml ├── fp-kylin-get.yml ├── fp-laravel-debug-post.yml ├── fp-laravel-env-get.yml ├── fp-laravel-get.yml ├── fp-laravel-webdir-get.yml ├── fp-nacos-get.yml ├── fp-phpmyadmin-get.yml ├── fp-seeyonOA-get.yml ├── fp-seeyonOA-md5.yml ├── fp-sharepoint-get.yml ├── fp-shiro-get.yml ├── fp-shiro-post.yml ├── fp-shiro1-get.yml ├── fp-shiro1-post.yml ├── fp-solr-get.yml ├── fp-sonicwall-vpn-get.yml ├── fp-swagger-ui-get.yml ├── fp-thinkadmin-get.yml ├── fp-thinkcmf-get.yml ├── fp-thinkphp-1-get.yml ├── fp-thinkphp-get.yml ├── fp-thinkphp-md5.yml ├── fp-tomcat-get.yml ├── fp-tongdaOA-get.yml ├── fp-ueditor-vuln-get.yml ├── fp-vBulletin-get.yml ├── fp-vmware-vcenter-get.yml ├── fp-weaverOA-md5.yml ├── fp-weblogic-error-get.yml ├── fp-wordpress-md5.yml ├── fp-zabbix-get.yml └── fp-zentao-md5.yml ├── hb ├── hb_linux └── hb_win.exe ├── rad ├── rad_config.yml ├── rad_linux └── rad_win.exe ├── requirements.txt └── tmp ├── history └── test.txt └── test.txt /Frog-Fp.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # coding: utf-8 3 | import requests 4 | from core import parse,banner,hb,rad,ffuf 5 | import config 6 | import argparse 7 | import sys 8 | import os 9 | import logging 10 | import hashlib 11 | logging.captureWarnings(True) 12 | from random import shuffle 13 | from concurrent.futures import ThreadPoolExecutor,wait, ALL_COMPLETED 14 | 15 | raw_headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36", 16 | "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"} 17 | 18 | hb_bin = 'hb_linux' 19 | rad_bin = "rad_linux" 20 | ffuf_bin = "ffuf_linux" 21 | 22 | fileL = [] 23 | 24 | sec_flag = False 25 | 26 | #设置两种系统 27 | def getsys(sys0): 28 | global hb_bin 29 | global rad_bin 30 | global ffuf_bin 31 | if sys0.lower() == 'linux': 32 | hb_bin = 'hb_linux' 33 | rad_bin = "rad_linux" 34 | ffuf_bin = "ffuf_linux" 35 | if sys0.lower() == 'win': 36 | hb_bin = 'hb_win.exe' 37 | rad_bin = "rad_win.exe" 38 | ffuf_bin = "ffuf_win.exe" 39 | 40 | 41 | #读取文件输出list 42 | def readf(fname): 43 | li = [] 44 | try: 45 | f = open(fname) 46 | for text in f.readlines(): 47 | data1 = text.strip('\n') 48 | if data1[-1] == "/": 49 | data1 = data1[:-1] 50 | if data1 != '': 51 | li.append(data1) 52 | except: 53 | return None 54 | finally: 55 | f.close() 56 | return li 57 | 58 | 59 | #写入 60 | def wFile(str): 61 | try: 62 | f = open("fp_results.txt",'a') 63 | f.write(str) 64 | f.write('\n') 65 | finally: 66 | f.close() 67 | 68 | 69 | def getmd5(body): 70 | m2 = hashlib.md5() 71 | m2.update(body) 72 | return m2.hexdigest() 73 | 74 | 75 | #指纹扫描 76 | def run(url,yaml_name,cookies,HD,fRe,paths,Method,expression,datas,md5_path,md5,type_F): 77 | global sec_flag 78 | global fileL 79 | if type_F == "second" and sec_flag == True: 80 | return 81 | flag = 0 82 | if yaml_name.split("-")[-1] != "md5": 83 | for i in paths: 84 | try: 85 | if (i == "/" or i == "") and HD == raw_headers and cookies == {} and Method == "get": 86 | pass 87 | else: 88 | url_tar = url + i 89 | if Method == "get": 90 | try: 91 | r = requests.get(url_tar, headers=HD, cookies = cookies, timeout=config.timeout, verify=False, allow_redirects=fRe, proxies = config.proxies) 92 | if eval(expression): 93 | print(" "+yaml_name + ": "+url_tar) 94 | wFile(yaml_name + ": "+url_tar) 95 | flag = 1 96 | break 97 | except: 98 | pass 99 | elif Method == "post": 100 | try: 101 | r = requests.post(url_tar, headers=HD, cookies = cookies, data = datas, timeout=config.timeout, verify=False, allow_redirects=fRe, proxies = config.proxies) 102 | if eval(expression): 103 | print(" "+yaml_name + ": "+url_tar) 104 | wFile(yaml_name + ": "+url_tar) 105 | flag = 1 106 | break 107 | except: 108 | pass 109 | except Exception as e: 110 | print(e) 111 | elif yaml_name.split("-")[-1] == "md5": 112 | for i in range(len(md5_path)): 113 | url_tar = url + md5_path[i] 114 | if Method == "get": 115 | try: 116 | r = requests.get(url_tar, headers=HD, timeout=config.timeout, verify=False, allow_redirects=fRe, proxies = config.proxies) 117 | r_md5 = getmd5(r.content) 118 | if r_md5 == md5[i] and r.status_code == 200: 119 | print(" "+yaml_name + ": "+url_tar) 120 | wFile(yaml_name + ": "+url_tar) 121 | flag = 1 122 | break 123 | except: 124 | pass 125 | if flag == 1 and type_F == "first": 126 | fileL.remove(url) 127 | if flag == 1 and type_F == "second": 128 | sec_flag = True 129 | 130 | #根目录指纹扫描 131 | def run_root(url,type_F): 132 | global sec_flag 133 | global fileL 134 | global yaml_list 135 | if type_F == "second" and sec_flag == True: 136 | return 137 | try: 138 | r = requests.get(url, headers=raw_headers, timeout=config.timeout, verify=False, allow_redirects=True, proxies = config.proxies) 139 | except: 140 | return 141 | #一次请求根目录判断多个yml 142 | for y in yaml_list: 143 | yaml_name,cookies,HD,fRe,paths,Method,expression,datas,md5_path,md5 = parse.get_yaml("fingerprint/"+y) 144 | if yaml_name.split("-")[-1] != "md5" and "/" in paths and Method == "get" and fRe == True: 145 | if eval(expression): 146 | print(" "+yaml_name + ": "+url) 147 | wFile(yaml_name + ": "+url) 148 | if type_F == "first": 149 | fileL.remove(url) 150 | if type_F == "second" and sec_flag == False: 151 | sec_flag = True 152 | return 153 | 154 | try: 155 | r = requests.get(url, headers=raw_headers, timeout=config.timeout, verify=False, allow_redirects=False, proxies = config.proxies) 156 | except: 157 | return 158 | #一次请求根目录判断多个yml 159 | for y in yaml_list: 160 | yaml_name,cookies,HD,fRe,paths,Method,expression,datas,md5_path,md5 = parse.get_yaml("fingerprint/"+y) 161 | if yaml_name.split("-")[-1] != "md5" and "/" in paths and Method == "get" and fRe == False: 162 | if eval(expression): 163 | print(" "+yaml_name + ": "+url) 164 | wFile(yaml_name + ": "+url) 165 | if type_F == "first": 166 | fileL.remove(url) 167 | if type_F == "second" and sec_flag == False: 168 | sec_flag = True 169 | return 170 | 171 | 172 | 173 | if __name__ == '__main__': 174 | os.system('') 175 | banner.banner() 176 | if len(sys.argv) != 4: 177 | print('\n') 178 | print("Usage: python3 Frog-Fp.py win/linux -tL urls.txt") 179 | print("Usage: python3 Frog-Fp.py win/linux -dL ips.txt") 180 | exit() 181 | else: 182 | parser = argparse.ArgumentParser() 183 | parser.add_argument('os', help='win/linux') 184 | parser.add_argument('-tL', help='urls', default='') 185 | parser.add_argument('-dL', help='domains', default='') 186 | args = parser.parse_args() 187 | 188 | #根据系统设置二进制文件名 189 | getsys(args.os) 190 | 191 | #读取yaml文件夹 192 | yaml_list = os.listdir('fingerprint') 193 | print("fingerprint list:\n") 194 | for y in yaml_list: 195 | print(" ",y) 196 | print("\ntotal:",len(yaml_list),"yaml files\n") 197 | shuffle(yaml_list) 198 | 199 | #输入url的情况 200 | if args.tL != "": 201 | file = args.tL 202 | #输入domain/ip/cidr的情况用hb进行端口发现 203 | elif args.dL != "": 204 | domainfile = args.dL 205 | hb.hb_scan(hb_bin,domainfile) 206 | file = "tmp/hb_output.txt" 207 | 208 | #将初始url读入list 209 | fileL = readf(file) 210 | fileL_cp = [] 211 | fileL_cp.extend(fileL) 212 | 213 | #判断是否仅进行基础扫描 214 | if config.only_basic == True: 215 | print("only_basic == True 仅进行基础扫描\n") 216 | 217 | #基础指纹扫描 218 | print("Basic scanning ",len(fileL),"urls...") 219 | 220 | type_F = "first" 221 | 222 | #针对根路径进行一次检测 223 | with ThreadPoolExecutor(max_workers=config.threads) as pool: 224 | all_task = [pool.submit(run_root,url,type_F) for url in fileL_cp] 225 | wait(all_task, return_when=ALL_COMPLETED) 226 | 227 | #解析yaml文件 228 | for y in yaml_list: 229 | shuffle(fileL_cp) 230 | #print(" ",y) 231 | yaml_name,cookies,HD,fRe,paths,Method,expression,datas,md5_path,md5 = parse.get_yaml("fingerprint/"+y) 232 | #逐个url去请求 233 | with ThreadPoolExecutor(max_workers=config.threads) as pool: 234 | all_task = [pool.submit(run,url,yaml_name,cookies,HD,fRe,paths,Method,expression,datas,md5_path,md5,type_F) for url in fileL_cp] 235 | wait(all_task, return_when=ALL_COMPLETED) 236 | #print(" Done\n") 237 | 238 | 239 | print("Basic Scan Finished\n") 240 | 241 | #判断是否需要进行深度扫描 242 | if config.only_basic == True or fileL == []: 243 | exit() 244 | 245 | print("Start Crawling&Deepscan ",len(fileL),"urls...") 246 | 247 | #爬虫,逐个url 248 | crawler_res = [] 249 | crawlerL = [] 250 | for url in fileL: 251 | #判断是否深度扫描需要进行爬虫 252 | if config.deep_crawl == True: 253 | crawlerL = rad.rad_crawler(rad_bin,url) 254 | if crawlerL != []: 255 | crawler_res.extend(crawlerL) 256 | crawlerL.clear() 257 | 258 | #dirfuzz目录发现 259 | fuzzL = ffuf.ffuf_dir(ffuf_bin,url) 260 | 261 | #补充爬虫(速度太慢,暂时抛弃) 262 | ''' 263 | if fuzzL != []: 264 | for x in fuzzL: 265 | if x not in crawler_res: 266 | crawlerL = rad.rad_crawler(rad_bin,x) 267 | if crawlerL != []: 268 | crawler_res.extend(crawlerL) 269 | crawlerL.clear() 270 | ''' 271 | if fuzzL != []: 272 | crawler_res.extend(fuzzL) 273 | fuzzL.clear() 274 | 275 | print(len(crawler_res),"crawling results in ./tmp/history/") 276 | 277 | #深度指纹扫描 278 | type_F = "second" 279 | sec_flag = False 280 | 281 | if crawler_res != []: 282 | #去重 283 | crawler_res = list(set(crawler_res)) 284 | #爬虫结果打乱 285 | shuffle(crawler_res) 286 | print("Deep scanning ",len(crawler_res),"urls...") 287 | 288 | #针对爬虫后的根路径进行一次检测 289 | with ThreadPoolExecutor(max_workers=config.threads) as pool: 290 | all_task = [pool.submit(run_root,url,type_F) for url in crawler_res] 291 | wait(all_task, return_when=ALL_COMPLETED) 292 | 293 | 294 | for y in yaml_list: 295 | #print(" ",y) 296 | yaml_name,cookies,HD,fRe,paths,Method,expression,datas,md5_path,md5 = parse.get_yaml("fingerprint/"+y) 297 | #逐个url去请求 298 | with ThreadPoolExecutor(max_workers=config.threads) as pool: 299 | all_task = [pool.submit(run,url,yaml_name,cookies,HD,fRe,paths,Method,expression,datas,md5_path,md5,type_F) for url in crawler_res] 300 | wait(all_task, return_when=ALL_COMPLETED) 301 | #print(" Done\n") 302 | 303 | #清除爬虫结果的list,进入下次循环 304 | crawler_res.clear() 305 | 306 | print("\nCrawling&Deepscan All Finished\n") 307 | try: 308 | os.remove("tmp/rad_output.json") 309 | except: 310 | pass 311 | try: 312 | os.remove("tmp/hb_output.txt") 313 | except: 314 | pass 315 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Frog-Fp](https://socialify.git.ci/timwhitez/Frog-Fp/image?description=1&font=Raleway&forks=1&issues=1&language=1&logo=https%3A%2F%2Favatars1.githubusercontent.com%2Fu%2F36320909&owner=1&pattern=Circuit%20Board&stargazers=1&theme=Light) 2 | 3 | - 🐸Frog For Automatic Scan 4 | 5 | - 🐶Doge For Defense Evasion&Offensive Security 6 | 7 | - 本系列命名为Frog可能是因为这种生物的寿命长 🐸 🤓 +1s 8 | 9 | - Frog-Fp为Frog系列第三个项目🐸,写的有点累了 10 | 11 | - 安全本逆天而行,猝死很正常,请勿用作授权之外非法用途 12 | 13 | ## 序 14 | 15 | ### 许久不更新,现在看来项目有点拉跨了 16 | 17 | ``` 18 | 1.关于自动化的设计,难点在于经验如何转化为程序的逻辑 19 | 20 | 2.大规模攻防对抗初期拼的是"以漏洞找资产的能力" 21 | 22 | 3.个人能力有限,精力有限,此项目的完成过程非常纠结 23 | ``` 24 | # 🐸Frog-Fp 25 | 26 | Frog-Fp批量深度指纹识别,采用python3实现,具体实现流程如下所示: 27 | 28 | ``` 29 | 不开启深度扫描: 30 | input: domain/ip/cidr-->web端口发现-->浅层指纹识别 31 | input: url-->浅层指纹识别 32 | 33 | 开启深度扫描: 34 | input: domain/ip/cidr-->web端口发现-->浅层指纹识别-->爬虫 && dir fuzz-->目录过滤与去重-->深度指纹识别 35 | input: url-->初次指纹识别-->爬虫 && dir fuzz-->目录过滤与去重-->深度指纹识别 36 | ``` 37 | 指纹库采用yaml格式进行解析, 需自行添加, 支持get,post,md5三种方式进行识别, 指纹库不公开, 具体格式见fingerprint内的demo文件 38 | 39 | web端口发现使用[c26root/hb](https://github.com/c26root/hb), 爬虫使用[chaitin/rad](https://github.com/chaitin/rad), 目录fuzz使用[ffuf/ffuf](https://github.com/ffuf/ffuf) 40 | 41 | 注:c26root/hb 我略微修改了输出代码,所以目前的hb二进制文件不可直接更新。 42 | 43 | 支持ip/domain/CIDR输入 44 | 45 | ## about 46 | 47 | 在大规模红蓝对抗中,不触发waf拦截的指纹识别是比较好的自动化切入点。 48 | 49 | 尤其是在手上有了一部分0day后,深度的指纹识别能提升"以漏洞找资产的能力"。 50 | 51 | 此框架的构思基于个人的一部分打点经验,有很多不足之处。 52 | 53 | ## Usage 54 | 若在linux下使用,请给 rad_linux/ffuf_linux/hb_linux三个文件可执行权限 55 | 56 | 并且执行pip install安装依赖 57 | ``` 58 | python3 -m pip install -r requirements.txt 59 | 60 | Linux下: 61 | python3 -m pip install -r requirements.txt --ignore-installed PyYAML 62 | ``` 63 | 将指纹库yaml文件放入fingerprint文件夹内,执行check.py可进行yaml格式检查。 64 | 65 | ## 常用命令 66 | ``` 67 | python3 Frog-Fp.py win/linux -tL urls.txt 68 | python3 Frog-Fp.py win/linux -dL ips.txt 69 | ``` 70 | 输入的文本按行划分,支持ip/domain/CIDR格式 71 | 72 | 若识别出结果会存到fp_results.txt 73 | 74 | tmp/history内会储存爬虫所得目录的历史记录 75 | 76 | ## yaml格式解析 77 | 78 | GET,POST: 79 | ``` 80 | #name为yaml的标题,请以fp开头,以请求方法结尾,中间以-连接 81 | name: fp-demo-get 82 | 83 | #method目前支持GET,POST 84 | method: GET 85 | 86 | #目录采用list格式,可写多个 87 | path: ["/","/login"] 88 | 89 | #Header采用dict格式,可写入""留空,即采用chrome默认header 90 | Header: {"Accept-Language":"zh-CN", "Content-Type": "text/javascript"} 91 | 92 | #Cookie采用;分隔多个key=value,中间不要有空格 93 | Cookie: key1=value1;key2=value2 94 | 95 | #follow_redirects可赋值True或False,记得第一位字母大写 96 | follow_redirects: True 97 | 98 | #expression表达式采用python语句直接执行,requests请求的返回值为r 99 | expression: | 100 | r.status_code == 200 and ('test' in str(r.headers) or 'test1' in r.content.decode()) 101 | 102 | #若请求方法为POST可加入data字段,格式为string 103 | data: '' 104 | 105 | ``` 106 | 107 | MD5: 108 | ``` 109 | #name为yaml的标题,请以fp开头,以md5结尾 110 | name: fp-demo-md5 111 | 112 | #md5_path为文件路径,list格式,与md5的list一一对应 113 | md5_path: ["/test.ico","/favicon.ico"] 114 | 115 | #md5为对于path的md5值,与md5_path一一对应 116 | md5: ["18b786ca7913a58cb8463f1a5feca293","ffaadddssa7913a58cb8463f1a5feca2"] 117 | 118 | ``` 119 | 120 | ## config.py 121 | 122 | ``` 123 | #指纹识别代理(去掉井号)(dirfuzz,爬虫代理暂不支持) 124 | proxies = { 125 | #"http":"http://127.0.0.1:8080", 126 | #"https":"http://127.0.0.1:8080", 127 | } 128 | 129 | #目录fuzz递归深度 130 | recursion = 2 131 | 132 | #目录fuzz超时(s) 133 | fuzztime = 5 134 | 135 | #指纹识别超时(s) 136 | timeout = 5 137 | 138 | #单个目标爬虫超时(s) 139 | crawler_timeout = 600 140 | 141 | #指纹识别线程数 142 | threads = 100 143 | 144 | #目录fuzz线程数 145 | fuzz_t = 20 146 | 147 | #web端口扫描超时 148 | hb_time = 5 149 | 150 | #端口扫描线程数 151 | hb_t = 200 152 | 153 | #端口扫描端口list 154 | ports = "80,443,8080,8443" 155 | 156 | #仅基础扫描,此配置为True就不会进行爬虫与目录fuzz 157 | only_basic = True 158 | 159 | #深度扫描进行爬虫 160 | deep_crawl = False 161 | ``` 162 | 目录扫描的字典位于ffuf/dict.txt,可自行修改 163 | 164 | ## todo 165 | 若有好的建议,程序的bug,欢迎提交issues 166 | 167 | ## 🚀Star Trend 168 | [![Stargazers over time](https://starchart.cc/timwhitez/Frog-Fp.svg)](https://starchart.cc/timwhitez/Frog-Fp) 169 | 170 | 171 | ## etc 172 | 1. 开源的样本大部分可能已经无法免杀,需要自行修改 173 | 174 | 2. 我认为基础核心代码的开源能够帮助想学习的人 175 | 176 | 3. 本人从github大佬项目中学到了很多 177 | 178 | 4. 若用本人项目去进行:HW演练/红蓝对抗/APT/黑产/恶意行为/违法行为/割韭菜,等行为,本人概不负责,也与本人无关 179 | 180 | 5. 本人已不参与大小HW活动的攻击方了,若溯源到timwhite id与本人无关 181 | -------------------------------------------------------------------------------- /check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timwhitez/Frog-Fp/41bbcf81b1181e46d1a0e77bf82f2968c004e982/check.png -------------------------------------------------------------------------------- /check.py: -------------------------------------------------------------------------------- 1 | import yaml 2 | import requests 3 | import os 4 | yaml.warnings({'YAMLLoadWarning':False}) 5 | 6 | 7 | def get_yaml(yaml_file): 8 | # 打开yaml文件 9 | file = open(yaml_file, 'r', encoding="utf-8") 10 | file_data = file.read() 11 | file.close() 12 | 13 | # 将字符串转化为字典或列表 14 | raw_data = yaml.load(file_data) 15 | 16 | #处理name 17 | if type(raw_data['name']) == str: 18 | if raw_data['name'].split("-")[0] == "fp": 19 | if raw_data['name'].split("-")[-1] == "get" or raw_data['name'].split("-")[-1] == "post" or raw_data['name'].split("-")[-1] == "md5": 20 | pass 21 | else: 22 | print(yaml_file,"name字段格式错误") 23 | else: 24 | print(yaml_file,"name字段格式错误") 25 | else: 26 | print(yaml_file,"name字段格式错误") 27 | 28 | 29 | if raw_data['name'].split("-")[-1] != "md5": 30 | #处理cookie 31 | if raw_data['Cookie'] != "" and raw_data['Cookie'] != {""} and raw_data['Cookie'] != {"":""}: 32 | if type(raw_data['Cookie']) != str: 33 | print(yaml_file,"Cookie字段格式错误") 34 | else: 35 | if ";" in raw_data['Cookie']: 36 | for i in raw_data['Cookie'].split(";"): 37 | if "=" not in i: 38 | print(yaml_file,"Cookie字段格式错误") 39 | elif "=" not in raw_data['Cookie']: 40 | print(yaml_file,"Cookie字段格式错误") 41 | 42 | 43 | #处理Header 44 | if raw_data['Header'] != "" and raw_data['Header'] != {""} and raw_data['Header'] != {"":""}: 45 | if type(raw_data['Header']) != dict: 46 | print(yaml_file,"Header字段格式错误") 47 | 48 | #处理redirects 49 | if type(raw_data['follow_redirects']) != bool: 50 | print(yaml_file,"follow_redirects字段格式错误") 51 | 52 | #处理path 53 | if type(raw_data['path']) != list: 54 | print(yaml_file,"path字段格式错误") 55 | for i in raw_data['path']: 56 | if "/" not in i: 57 | print(yaml_file,"path字段格式错误") 58 | 59 | #处理method 60 | if raw_data['method'].lower() != "get" and raw_data['method'].lower() != "post": 61 | print(yaml_file,"method字段格式错误") 62 | 63 | #处理expression 64 | if type(raw_data['expression']) != str: 65 | print(yaml_file,"expression字段格式错误") 66 | if "\n" in raw_data['expression']: 67 | expression = raw_data['expression'].split("\n")[0] 68 | else: 69 | expression = raw_data['expression'] 70 | 71 | if eval(expression) != True and eval(expression) != False: 72 | print(yaml_file,"expression字段格式错误") 73 | 74 | 75 | #处理data 76 | if raw_data['method'].lower() == "post": 77 | try: 78 | if type(raw_data['data']) != str: 79 | print(yaml_file,"data字段格式错误") 80 | except: 81 | pass 82 | 83 | md5 = [] 84 | md5_path = [] 85 | 86 | elif raw_data['name'].split("-")[-1] == "md5": 87 | if type(raw_data['md5_path']) != list: 88 | print(yaml_file,"md5_path字段格式错误") 89 | if type(raw_data['md5']) != list: 90 | print(yaml_file,"md5字段格式错误") 91 | for i in raw_data['md5']: 92 | if len(i)!= 32: 93 | print(yaml_file,"md5字段格式错误") 94 | if len(raw_data['md5_path']) != len(raw_data['md5']): 95 | print(yaml_file,"md5字段list对应关系错误") 96 | 97 | 98 | 99 | r = requests.get("https://www.baidu.com", timeout=10) 100 | yaml_list = os.listdir('fingerprint') 101 | print("+++++++++++++++++++++++++checking+++++++++++++++++++++++++") 102 | for y in yaml_list: 103 | print("checking -", y) 104 | get_yaml('fingerprint/'+y) 105 | print("\ntotal checked:",len(yaml_list),"yaml files\n") 106 | print("+++++++++++++++++++++++++finished+++++++++++++++++++++++++") 107 | -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | #指纹识别代理(dirfuzz,爬虫代理暂不支持) 2 | proxies = { 3 | #"http":"http://127.0.0.1:8080", 4 | #"https":"http://127.0.0.1:8080", 5 | } 6 | 7 | #目录fuzz递归深度 8 | recursion = 2 9 | 10 | #目录fuzz超时(s) 11 | fuzztime = 3 12 | 13 | #指纹识别超时(s) 14 | timeout = 5 15 | 16 | #单个目标爬虫超时(s) 17 | crawler_timeout = 1000 18 | 19 | #指纹识别线程数 20 | threads = 200 21 | 22 | #目录fuzz线程数 23 | fuzz_t = 20 24 | 25 | #web端口扫描超时 26 | hb_time = 3 27 | 28 | #端口扫描线程数 29 | hb_t = 500 30 | 31 | #端口扫描端口list 32 | ports = "80,81,82,83,84,85,86,87,88,89,90,91,92,98,99,443,800,801,808,880,888,889,1000,1010,1080,1081,1082,1158,1863,1980,2018,2019,2100,3000,3128,3505,5555,6080,6677,7000,7001,7002,7003,7005,7007,7070,7080,7200,7777,7890,8000,8001,8002,8003,8004,8005,8006,8008,8009,8010,8011,8012,8014,8016,8020,8028,8042,8053,8060,8069,8070,8080,8081,8082,8083,8084,8085,8086,8087,8088,8089,8090,8091,8092,8093,8094,8095,8096,8097,8098,8099,8100,8101,8108,8118,8123,8161,8172,8180,8181,8200,8222,8243,8251,8280,8281,8300,8333,8360,8443,8484,8500,8800,8834,8879,8880,8881,8888,8899,8983,8989,9000,9001,9002,9043,9060,9080,9081,9082,9085,9090,9091,9092,9200,9443,9800,9981,9999,10000,10001,10002,10003,12443,15672,16080,18080,18082,18091,18092,20720,28017,38501,38888" 33 | 34 | #仅基础扫描 35 | only_basic = False 36 | 37 | #深度扫描进行爬虫 38 | deep_crawl = False 39 | -------------------------------------------------------------------------------- /core/banner.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # -*- coding:utf8 -*- 3 | 4 | 5 | def banner(): 6 | ''' 7 | print(" ⣿⣿⣿⣿⣿⣿⢟⣡⣴⣶⣶⣦⣌⡛⠟⣋⣩⣬⣭⣭⡛⢿⣿⣿⣿⣿ ") 8 | print(" ⣿⣿⣿⣿⠋⢰⣿⣿⠿⣛⣛⣙⣛⠻⢆⢻⣿⠿⠿⠿⣿⡄⠻⣿⣿⣿ ") 9 | print(" ⣿⣿⣿⠃⢠⣿⣿⣶⣿⣿⡿⠿⢟⣛⣒⠐⠲⣶⡶⠿⠶⠶⠦⠄⠙⢿ ") 10 | print(" ⣿⠋⣠⠄⣿⣿⣿⠟⡛⢅⣠⡵⡐⠲⣶⣶⣥⡠⣤⣵⠆⠄⠰⣦⣤⡀ ") 11 | print(" ⠇⣰⣿⣼⣿⣿⣧⣤⡸⢿⣿⡀⠂⠁⣸⣿⣿⣿⣿⣇⠄⠈⢀⣿⣿⠿ ") 12 | print(" ⣰⣿⣿⣿⣿⣿⣿⣿⣷⣤⣈⣙⠶⢾⠭⢉⣁⣴⢯⣭⣵⣶⠾⠓⢀⣴ ") 13 | print(" ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣉⣤⣴⣾⣿⣿⣦⣄⣤⣤⣄⠄⢿⣿ ") 14 | print(" ⣿⣿⣿⣿⣿⣿⣿⣿⠿⠿⠿⠿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣇⠈⢿ ") 15 | print(" ⣿⣿⣿⣿⣿⣿⡟⣰⣞⣛⡒⢒⠤⠦⢬⣉⣉⣉⣉⣉⣉⣉⡥⠴⠂⢸ ") 16 | print(" ⠻⣿⣿⣿⣿⣏⠻⢌⣉⣉⣩⣉⡛⣛⠒⠶⠶⠶⠶⠶⠶⠶⠶⠂⣸⣿ ") 17 | print(" ⣥⣈⠙⡻⠿⠿⣷⣿⣿⣿⣿⣿⣿⣿⣿⣿⣾⣿⠿⠛⢉⣠⣶⣶⣿⣿ ") 18 | ''' 19 | 20 | print(" _ _ _ _ ") 21 | print(" /\ \ /\ \ /\ \ /\ \ ") 22 | print(" / \ \ / \ \ / \ \ / \ \ ") 23 | print(" / /\ \ \ / /\ \ \ / /\ \ \ / /\ \_\ ") 24 | print(" / / /\ \_\ / / /\ \_\ / / /\ \ \ / / /\/_/ ") 25 | print(" / /_/_ \/_// / /_/ / / / / / \ \_\ / / / ______ ") 26 | print(" / /____/\ / / /__\/ / / / / / / // / / /\_____\ ") 27 | print(" / /\____\/ / / /_____/ / / / / / // / / \/____ / ") 28 | print(" / / / / / /\ \ \ / / /___/ / // / /_____/ / / ") 29 | print("/ / / / / / \ \ \/ / /____\/ // / /______\/ / ") 30 | print("\/_/ \/_/ \_\/\/_________/ \/___________/ ") -------------------------------------------------------------------------------- /core/ffuf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # coding: utf-8 3 | import subprocess 4 | import os 5 | import sys 6 | import config 7 | 8 | def ffuf_dir(ffuf_bin,url): 9 | print("fuzzing ",url) 10 | li = [] 11 | cmd = ["./ffuf/"+ffuf_bin, "-u", url+"/FUZZ", "-timeout", str(config.fuzztime), "-ac", "-r", "-t", str(config.fuzz_t), "-s","-recursion","-recursion-depth", str(config.recursion), "-w", "ffuf/dict.txt", "-o", "tmp/fuzz_tmp.csv", "-of", "csv"] 12 | try: 13 | output = subprocess.check_output(cmd) 14 | except Exception as e: 15 | print(e) 16 | #print("fuzz目录出错") 17 | return li 18 | 19 | #读结果 20 | with open("tmp/fuzz_tmp.csv", 'r') as f: 21 | next(f) 22 | for text in f.readlines(): 23 | if text != "": 24 | li.append(text.split(",")[1]) 25 | print("fuzz_results:",len(li)) 26 | return li 27 | -------------------------------------------------------------------------------- /core/hb.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # coding: utf-8 3 | import subprocess 4 | import os 5 | import sys 6 | import config 7 | 8 | def hb_scan(hb_bin,file): 9 | try: 10 | os.remove("tmp/hb_output.txt") 11 | except: 12 | pass 13 | cmd = ["./hb/"+hb_bin, "-f", file, "-o", "tmp/hb_output.txt", "-p", config.ports, "-random", "-redirect", "-timeout", str(config.hb_time), "-t", str(config.hb_t)] 14 | try: 15 | print("Starting Port Scan") 16 | rsp=subprocess.Popen(cmd) 17 | output, error = rsp.communicate() 18 | except Exception as e: 19 | print(e) 20 | print("端口扫描出错,请检查输入文件以及hb文件夹内二进制文件") 21 | sys.exit(1) 22 | print("Port Scanning Finished\n") 23 | print(r"***************************************************************************************") 24 | -------------------------------------------------------------------------------- /core/parse.py: -------------------------------------------------------------------------------- 1 | import yaml 2 | yaml.warnings({'YAMLLoadWarning':False}) 3 | 4 | def get_yaml(yaml_file): 5 | #初始化 6 | HD = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36", 7 | "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"} 8 | cookies = {} 9 | data = "" 10 | 11 | # 打开yaml文件 12 | file = open(yaml_file, 'r', encoding="utf-8") 13 | file_data = file.read() 14 | file.close() 15 | 16 | # 将字符串转化为字典或列表 17 | raw_data = yaml.load(file_data) 18 | 19 | #处理name 20 | yaml_name = raw_data['name'] 21 | 22 | if yaml_name.split("-")[-1] != "md5": 23 | #处理cookie 24 | if raw_data['Cookie'] != "" and raw_data['Cookie'] != {""} and raw_data['Cookie'] != {"":""}: 25 | if ";" in raw_data['Cookie']: 26 | for q in raw_data['Cookie'].split(";"): 27 | c1 = q.split("=")[0] 28 | c2 = q.split("=")[1] 29 | cookies[c1] = c2 30 | else: 31 | c1 = raw_data['Cookie'].split("=")[0] 32 | c2 = raw_data['Cookie'].split("=")[1] 33 | cookies[c1] = c2 34 | 35 | 36 | #处理Header 37 | if raw_data['Header'] != "" and raw_data['Header'] != {""} and raw_data['Header'] != {"":""}: 38 | HD.update(raw_data['Header']) 39 | 40 | #处理redirects 41 | if raw_data['follow_redirects'] == True: 42 | fRe = True 43 | else: 44 | fRe = False 45 | 46 | #处理path 47 | paths = raw_data['path'] 48 | 49 | #处理method 50 | Method = raw_data['method'].lower() 51 | 52 | #处理expression 53 | if "\n" in raw_data['expression']: 54 | expression = raw_data['expression'].split("\n")[0] 55 | else: 56 | expression = raw_data['expression'] 57 | 58 | #处理data 59 | if raw_data['method'].lower() == "post": 60 | try: 61 | data = raw_data['data'] 62 | except: 63 | pass 64 | 65 | md5 = [] 66 | md5_path = [] 67 | 68 | elif yaml_name.split("-")[-1] == "md5": 69 | md5_path = raw_data['md5_path'] 70 | md5 = raw_data['md5'] 71 | fRe = False 72 | Method = "get" 73 | paths = "" 74 | expression = "" 75 | 76 | return yaml_name,cookies,HD,fRe,paths,Method,expression,data,md5_path,md5 77 | -------------------------------------------------------------------------------- /core/rad.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # coding: utf-8 3 | import subprocess 4 | import os 5 | import simplejson 6 | import time 7 | import config 8 | 9 | #获取时间戳 10 | def gettime(): 11 | t = time.strftime("%m-%d_%H-%M-%S", time.localtime()) 12 | return str(t) 13 | 14 | #写入 15 | def wFile(file,str): 16 | tn = gettime() 17 | if ":" in file: 18 | file = file.replace(":","_") 19 | try: 20 | f = open("tmp/history/"+file + "_" + tn +".txt",'a') 21 | f.write(str) 22 | f.write('\n') 23 | finally: 24 | f.close() 25 | 26 | def rad_crawler(rad_bin,target): 27 | uList = [] 28 | name = target.split("://")[1] 29 | try: 30 | name = name.split("/")[0] 31 | except: 32 | pass 33 | try: 34 | os.remove("tmp/rad_output.json") 35 | except: 36 | pass 37 | cmd = ["./rad/"+rad_bin, "-t", target, "-json", "tmp/rad_output.json", "--no-banner","-c","rad/rad_config.yml"] 38 | print('\nCrawling '+target+"...") 39 | try: 40 | output = subprocess.check_output(cmd, timeout=config.crawler_timeout) 41 | except Exception as e: 42 | #print(e) 43 | if "time out" in str(e): 44 | print("crawling timeout...") 45 | pass 46 | else: 47 | print(e) 48 | return uList 49 | 50 | #print("Finished") 51 | file_err = False 52 | with open("tmp/rad_output.json") as f: 53 | try: 54 | result_json = simplejson.load(f) 55 | except: 56 | file_err = True 57 | pass 58 | if file_err == True: 59 | with open("tmp/rad_output.json") as f: 60 | try: 61 | result_json = simplejson.loads(f.read()+"]") 62 | except: 63 | print("json解析失败") 64 | return uList 65 | 66 | for u in result_json: 67 | url_split = [] 68 | url_list = [] 69 | try: 70 | urls = u['URL'] 71 | if "?" in urls: 72 | urls = urls.split("?")[0] 73 | url_split.append(urls.split("://")[0]) 74 | for ul in range(len((urls.split("://")[1]).split("/"))): 75 | url_split.append(urls.split("://")[1].split("/")[ul]) 76 | if ul == 3: 77 | break 78 | url = url_split[0]+"://" + url_split[1] 79 | url_list.append(url) 80 | if len(url_split) > 2: 81 | for i in range(len(url_split)-2): 82 | i = i + 2 83 | if url_split[i] == "": 84 | break 85 | url = url +"/"+ url_split[i] 86 | url_list.append(url) 87 | uList.extend(url_list) 88 | except: 89 | continue 90 | uList = list(set(uList)) 91 | for url0 in uList: 92 | wFile(name,url0) 93 | return uList -------------------------------------------------------------------------------- /ffuf/dict.txt: -------------------------------------------------------------------------------- 1 | improve 2 | img11 3 | manufacturer 4 | import 5 | movie 6 | mysql 7 | monitor 8 | news 9 | network 10 | n 11 | nav 12 | models 13 | menus 14 | manage 15 | maintenance 16 | main 17 | manager 18 | hunter 19 | modules 20 | mail 21 | htdocs 22 | html 23 | jobconsume 24 | logs 25 | sort 26 | sola 27 | kindeditor 28 | soap 29 | login 30 | ch 31 | log 32 | cdn 33 | category 34 | image 35 | captcha 36 | hr 37 | jobs 38 | item 39 | bbs 40 | cake 41 | home 42 | json 43 | local 44 | interface 45 | lite 46 | install 47 | link 48 | info 49 | index 50 | includes 51 | include 52 | libs 53 | libraries 54 | history 55 | lib 56 | helpers 57 | inc 58 | helper 59 | languages 60 | base 61 | api 62 | hello 63 | alarm 64 | skin 65 | l 66 | award 67 | sms 68 | sites 69 | auth 70 | caching 71 | cache 72 | caches 73 | build 74 | cacti 75 | backup 76 | bak 77 | authority 78 | dashboard 79 | daily 80 | crud 81 | css 82 | crontab 83 | core 84 | controllers 85 | control 86 | content 87 | attachment 88 | back 89 | simple 90 | show 91 | shell 92 | service 93 | server 94 | security 95 | consumer 96 | site 97 | console 98 | confs 99 | mysite 100 | config 101 | group 102 | conf 103 | ft 104 | framework 105 | frame 106 | forum 107 | follow 108 | flashchart 109 | finance 110 | files 111 | file 112 | demo 113 | feature 114 | fe 115 | classic 116 | ext 117 | export 118 | excel 119 | examples 120 | commons 121 | components 122 | common 123 | eva 124 | es 125 | commit 126 | duty 127 | download 128 | comment 129 | doc 130 | collection 131 | dev 132 | cluster 133 | client 134 | default 135 | db 136 | database 137 | gss 138 | classes 139 | data 140 | scripts 141 | script 142 | schema 143 | schedule 144 | save 145 | s 146 | resources 147 | resource 148 | report 149 | quote 150 | bootstrap 151 | search 152 | redisclient 153 | redirect 154 | blog 155 | blacklist 156 | bin 157 | bg 158 | gift 159 | gold 160 | game 161 | gallery 162 | brand 163 | public 164 | qq 165 | ps 166 | proxy 167 | protected 168 | product 169 | post 170 | portal 171 | pm 172 | platform 173 | project 174 | address 175 | ajax 176 | pl 177 | mis 178 | picture 179 | phptest 180 | phprpc 181 | php 182 | pcheck 183 | person 184 | people 185 | pay 186 | passport 187 | pages 188 | page 189 | other 190 | act 191 | action 192 | activity 193 | question 194 | oauth 195 | account 196 | ad 197 | m 198 | mobile 199 | admin_bak 200 | admin 201 | zone 202 | wwwroot 203 | www2 204 | www 205 | ws 206 | workspace 207 | wordpress 208 | wm 209 | web 210 | weixin 211 | widgets 212 | view 213 | vendor 214 | views 215 | v2 216 | v1 217 | util 218 | user 219 | tpl 220 | url 221 | txt 222 | uploadify 223 | upload 224 | uploads 225 | top 226 | tool 227 | tools 228 | token 229 | tmp 230 | ticket 231 | sv 232 | tcpdf 233 | tag 234 | task 235 | tasks 236 | static 237 | system 238 | template 239 | templates 240 | test 241 | subways 242 | tests 243 | survey 244 | stat 245 | stats 246 | statistics 247 | submit 248 | syslog 249 | bd 250 | 11 251 | class 252 | nw 253 | 123 254 | cms 255 | 2018 256 | ar 257 | model 258 | bbs1 259 | js 260 | check 261 | 2017 262 | app 263 | sql 264 | spider 265 | city 266 | message 267 | notice 268 | abstract -------------------------------------------------------------------------------- /ffuf/ffuf_linux: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timwhitez/Frog-Fp/41bbcf81b1181e46d1a0e77bf82f2968c004e982/ffuf/ffuf_linux -------------------------------------------------------------------------------- /ffuf/ffuf_win.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timwhitez/Frog-Fp/41bbcf81b1181e46d1a0e77bf82f2968c004e982/ffuf/ffuf_win.exe -------------------------------------------------------------------------------- /fingerprint/fp-74cms-get.yml: -------------------------------------------------------------------------------- 1 | name: fp-74cms-get 2 | method: GET 3 | path: ['/'] 4 | Header: "" 5 | Cookie: "" 6 | follow_redirects: True 7 | expression: | 8 | 'content="74cms.com' in r.content.decode() or 'content="骑士CMS' in r.content.decode() or ('/templates/default/css/common.css' in r.content.decode() and 'selectjobscategory' in r.content.decode()) -------------------------------------------------------------------------------- /fingerprint/fp-ActiveMQ-get.yml: -------------------------------------------------------------------------------- 1 | name: fp-ActiveMQ-get 2 | method: GET 3 | path: ['/'] 4 | Header: "" 5 | Cookie: "" 6 | follow_redirects: True 7 | expression: | 8 | 'Apache ActiveMQ' in r.content.decode() or 'activemq_logo' in r.content.decode() or 'Manage ActiveMQ broker' in r.content.decode() -------------------------------------------------------------------------------- /fingerprint/fp-Cacti-get.yml: -------------------------------------------------------------------------------- 1 | name: fp-Cacti-get 2 | method: GET 3 | path: ["/"] 4 | Header: "" 5 | Cookie: "" 6 | follow_redirects: True 7 | expression: | 8 | '' in r.content.decode() and '' in r.content.decode() and 'Cacti' in r.content.decode() -------------------------------------------------------------------------------- /fingerprint/fp-Canal-Admin-get.yml: -------------------------------------------------------------------------------- 1 | name: fp-Canal-Admin-get 2 | method: GET 3 | path: ['/'] 4 | Header: "" 5 | Cookie: "" 6 | follow_redirects: True 7 | expression: | 8 | 'Canal Admin' in r.content.decode() or 'Canal Admin Login' in r.content.decode() -------------------------------------------------------------------------------- /fingerprint/fp-Coremail-get.yml: -------------------------------------------------------------------------------- 1 | name: fp-Coremail-get 2 | method: GET 3 | path: ["/","/coremail"] 4 | Header: "" 5 | Cookie: "" 6 | follow_redirects: True 7 | expression: | 8 | '/coremail/common' in r.content.decode() -------------------------------------------------------------------------------- /fingerprint/fp-Druid-get.yml: -------------------------------------------------------------------------------- 1 | name: fp-Druid-get 2 | method: GET 3 | path: ["/druid/index.html"] 4 | Header: "" 5 | Cookie: "" 6 | follow_redirects: True 7 | expression: | 8 | 'Druid Stat Index' in r.content.decode() and 'DruidVersion' in r.content.decode() and 'DruidDrivers' in r.content.decode() -------------------------------------------------------------------------------- /fingerprint/fp-Drupal-get.yml: -------------------------------------------------------------------------------- 1 | name: fp-Drupal-get 2 | method: GET 3 | path: ["/"] 4 | Header: "" 5 | Cookie: "" 6 | follow_redirects: True 7 | expression: | 8 | ('X-Generator'in str(r.headers) and 'Drupal' in str(r.headers)) or 'jQuery.extend(Drupal.settings' in r.content.decode() or ('/sites/default/files/' in r.content.decode() and '/sites/all/modules/' in r.content.decode() and '/sites/all/themes/' in r.content.decode()) -------------------------------------------------------------------------------- /fingerprint/fp-E-Bridge-get.yml: -------------------------------------------------------------------------------- 1 | name: fp-E-Bridge-get 2 | method: GET 3 | path: ["/","/login"] 4 | Header: "" 5 | Cookie: "" 6 | follow_redirects: True 7 | expression: | 8 | r.status_code==200 and 'http://wx.weaver.com.cn' in r.content.decode() -------------------------------------------------------------------------------- /fingerprint/fp-E-mobile-get.yml: -------------------------------------------------------------------------------- 1 | name: fp-E-mobile-get 2 | method: GET 3 | path: ["/","/login.do"] 4 | Header: "" 5 | Cookie: "" 6 | follow_redirects: True 7 | expression: | 8 | 'Weaver E-mobile' in r.content.decode() -------------------------------------------------------------------------------- /fingerprint/fp-EAS-get.yml: -------------------------------------------------------------------------------- 1 | name: fp-EAS-get 2 | method: GET 3 | path: ["/"] 4 | Header: "" 5 | Cookie: "" 6 | follow_redirects: False 7 | expression: | 8 | 'EASSESSIONID' in str(r.headers['Set-Cookie']) -------------------------------------------------------------------------------- /fingerprint/fp-Exchange-get.yml: -------------------------------------------------------------------------------- 1 | name: fp-Exchange-get 2 | method: GET 3 | path: ["/owa","/owa/auth/logon.aspx"] 4 | Header: "" 5 | Cookie: "" 6 | follow_redirects: True 7 | expression: | 8 | 'Outlook' in r.content.decode() or 'owaLgnBdy' in r.content.decode() or '<!-- OwaPage = ASP.auth_logon_aspx -->' in r.content.decode() or 'owaauth.dll' in r.content.decode() or 'owaLogoContainer' in r.content.decode() or 'OutlookSession' in str(r.headers) -------------------------------------------------------------------------------- /fingerprint/fp-FineReport-get.yml: -------------------------------------------------------------------------------- 1 | name: fp-FineReport-get 2 | method: GET 3 | path: ["/","/ReportServer","/report/ReportServer","/seeyonreport/ReportServer","/WebReport/ReportServer"] 4 | Header: "" 5 | Cookie: "" 6 | follow_redirects: True 7 | expression: | 8 | 'FineReport,Web Reporting Tool' in r.content.decode() -------------------------------------------------------------------------------- /fingerprint/fp-FusionAuth-get.yml: -------------------------------------------------------------------------------- 1 | name: fp-FusionAuth-get 2 | method: GET 3 | path: ["/","/login"] 4 | Header: "" 5 | Cookie: "" 6 | follow_redirects: True 7 | expression: | 8 | 'content="FusionAuth">' in r.content.decode() or 'fusionauth.locale' in str(r.headers) -------------------------------------------------------------------------------- /fingerprint/fp-GRP-U8-get.yml: -------------------------------------------------------------------------------- 1 | name: fp-GRP-U8-get 2 | method: GET 3 | path: ["/","/login.jsp","/index.jsp"] 4 | Header: "" 5 | Cookie: "" 6 | follow_redirects: True 7 | expression: | 8 | r.status_code==200 and 'GRP-U8' in r.content.decode() -------------------------------------------------------------------------------- /fingerprint/fp-GitLab-get.yml: -------------------------------------------------------------------------------- 1 | name: fp-GitLab-get 2 | method: GET 3 | path: ["/","/users/sign_in"] 4 | Header: "" 5 | Cookie: "" 6 | follow_redirects: True 7 | expression: | 8 | '_gitlab_session' in str(r.headers) and 'content="GitLab' in r.content.decode() -------------------------------------------------------------------------------- /fingerprint/fp-H3C_switch-get.yml: -------------------------------------------------------------------------------- 1 | name: fp-H3C_switch-get 2 | method: GET 3 | path: ["/","/web/device/login"] 4 | Header: "" 5 | Cookie: "" 6 | follow_redirects: True 7 | expression: | 8 | '<title>Web user login' in r.content.decode() and '/skin/custom/login/index.css' in r.content.decode() -------------------------------------------------------------------------------- /fingerprint/fp-Harbor-get.yml: -------------------------------------------------------------------------------- 1 | name: fp-Harbor-get 2 | method: GET 3 | path: ['/','/harbor/sign-in'] 4 | Header: "" 5 | Cookie: "" 6 | follow_redirects: True 7 | expression: | 8 | 'Harbor' in r.content.decode() or ('images/harbor-' in r.content.decode() and 'harbor-logo' in r.content.decode()) or 'class="title">Harbor' in r.content.decode() -------------------------------------------------------------------------------- /fingerprint/fp-JBoss-Console-get.yml: -------------------------------------------------------------------------------- 1 | name: fp-JBoss-Console-get 2 | method: GET 3 | path: ['/','/console','/jmx-console','/admin-console','/jbossws'] 4 | Header: "" 5 | Cookie: "" 6 | follow_redirects: True 7 | expression: | 8 | 'Welcome to JBoss' in r.content.decode() or '<title>JBoss' in r.content.decode() or 'JBoss™ Management Console' in r.content.decode() or 'JBoss AS Administration Console' in r.content.decode() -------------------------------------------------------------------------------- /fingerprint/fp-JumpServer-get.yml: -------------------------------------------------------------------------------- 1 | name: fp-JumpServer-get 2 | method: GET 3 | path: ['/','/core/auth/login/'] 4 | Header: '' 5 | Cookie: "" 6 | follow_redirects: True 7 | expression: | 8 | '<title>JumpServer' in r.content.decode() or ('/static/css/jumpserver.css' in r.content.decode() and '/static/js/jumpserver.js' in r.content.decode()) -------------------------------------------------------------------------------- /fingerprint/fp-Kibana-get.yml: -------------------------------------------------------------------------------- 1 | name: fp-Kibana-get 2 | method: GET 3 | path: ['/','/app/kibana'] 4 | Header: "" 5 | Cookie: "" 6 | follow_redirects: True 7 | expression: | 8 | 'Kibana' in r.content.decode() or ('kbn-name' in str(r.headers) and 'kbn-version' in str(r.headers)) -------------------------------------------------------------------------------- /fingerprint/fp-KubeSphere-get.yml: -------------------------------------------------------------------------------- 1 | name: fp-KubeSphere-get 2 | method: GET 3 | path: ['/','/login'] 4 | Header: "" 5 | Cookie: "" 6 | follow_redirects: True 7 | expression: | 8 | 'KubeSphere' in r.content.decode() -------------------------------------------------------------------------------- /fingerprint/fp-Liferay-get.yml: -------------------------------------------------------------------------------- 1 | name: fp-Liferay-get 2 | method: GET 3 | path: ['/'] 4 | Header: "" 5 | Cookie: "" 6 | follow_redirects: True 7 | expression: | 8 | 'Liferay-Portal' in str(r.headers) or 'Liferay Portal' in str(r.headers) -------------------------------------------------------------------------------- /fingerprint/fp-Login-get.yml: -------------------------------------------------------------------------------- 1 | name: fp-Login-get 2 | method: GET 3 | path: ["/","/login","/admin","/logon","/Login"] 4 | Header: "" 5 | Cookie: "" 6 | follow_redirects: True 7 | expression: | 8 | ('type="password"' in r.content.decode() or 'name="password"' in r.content.decode()) and ('name="user' in r.content.decode() or 'id="user' in r.content.decode() or 'name="userId' in r.content.decode()) -------------------------------------------------------------------------------- /fingerprint/fp-NC-get.yml: -------------------------------------------------------------------------------- 1 | name: fp-NC-get 2 | method: GET 3 | path: ["/","/login.jsp","/index.jsp"] 4 | Header: "" 5 | Cookie: "" 6 | follow_redirects: True 7 | expression: | 8 | r.status_code==200 and 'YONYOU NC' in r.content.decode() -------------------------------------------------------------------------------- /fingerprint/fp-Nexus-get.yml: -------------------------------------------------------------------------------- 1 | name: fp-Nexus-get 2 | method: GET 3 | path: ["/","/nexus"] 4 | Header: "" 5 | Cookie: "" 6 | follow_redirects: True 7 | expression: | 8 | 'Nexus Repository Manager' in r.content.decode() or 'Sonatype Nexus Repository Manager' in r.content.decode() or 'content="Nexus Repository Manager">' in r.content.decode() -------------------------------------------------------------------------------- /fingerprint/fp-Pulse-VPN-get.yml: -------------------------------------------------------------------------------- 1 | name: fp-Pulse-VPN-get 2 | method: GET 3 | path: ["/","/dana-na/auth/url_default/welcome.cgi"] 4 | Header: "" 5 | Cookie: "" 6 | follow_redirects: True 7 | expression: | 8 | 'Pulse Connect Secure' in r.content.decode() and '