├── LICENSE
├── README.md
├── UseHelp.md
├── config.yaml
├── github_cve_monitor.py
├── images
├── 124256679-27701e00-db5e-11eb-9432-d3a9048daeec.png
├── image-20210729172507519.png
├── image-20211118142412234.png
├── image-20211118145021974.png
├── image-20220126105710922.png
├── image-20220126110109185.png
├── image-20220126110312664.png
└── image-20220126110919827.png
├── requirements.txt
└── tools_list.yaml
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 yhy
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # github-cve-monitor
2 |
3 | 
4 |
5 | ## 实时监控github上新增的cve和安全工具更新,多渠道推送通知
6 |
7 | 每3分钟检测一次github是否有新的cve漏洞提交或者安全工具更新记录,若有则通过配置的渠道通知用户
8 |
9 | 时间间隔修改在 467 行
10 |
11 | 建议使用[screen命令](https://www.runoob.com/linux/linux-comm-screen.html)运行在自己的linux vps后台上,就可以愉快的接收各种cve了
12 |
13 | ```bash
14 | #创建一个screen,名字为github_cve,在新窗口运行本项目, 成功后直接叉掉该窗口, 项目就会在后台一直运行了
15 | screen -S github_cve
16 | #查看创建的screen
17 | screen -ls
18 | #连接github_cve后台screen,如果存在的话
19 | screen -r github_cve
20 | ```
21 |
22 | # 使用帮助
23 |
24 | `tools_list.yaml` 监控的工具列表,新添加按照已有的格式写
25 |
26 | `config.yaml` 推送token 设置
27 |
28 |
29 |
30 | 详细见[使用帮助](UseHelp.md)
31 |
32 | # 效果
33 |
34 |
35 |
36 | # 鸣谢
37 |
38 | [洛米唯熊](https://my.oschina.net/u/4581868/blog/4380482)
39 |
40 | [kiang70](https://github.com/kiang70/Github-Monitor)
41 |
42 | 感谢 [JetBrains](https://www.jetbrains.com/?from=github-cve-monitor) 提供的一系列好用的 IDE 和对本项目的支持。
43 |
44 | 
45 |
--------------------------------------------------------------------------------
/UseHelp.md:
--------------------------------------------------------------------------------
1 | # 推送设置
2 |
3 | ## 钉钉
4 |
5 | 1. 建立群聊(可以单人建群)
6 |
7 | 2. 智能群助手添加自定义机器人
8 |
9 | 选择加签
10 |
11 | 
12 |
13 | 建立机器人,之后在`config.yaml`中配置,将webhook和秘钥secretKey填入对应的字段,`enable`设置为`1`表示使用该通知
14 |
15 | 效果:
16 |
17 |
18 |
19 | ## 飞书捷径推送
20 |
21 | @[sodmelody](https://github.com/sodmelody) 添加
22 |
23 | > 飞书工作台 - 飞书捷径 -webhook
24 |
25 | 
26 |
27 | 注意参数这里:
28 |
29 | 添加下列json信息
30 |
31 | ```php
32 | {"at":{},"msgtype":"text","text":{"content":"有新的CVE送达!\r\nCVE编号:CVE-2021-41773\r\nGithub地址:https://github.com/iilegacyyii/PoC-CVE-2021-41773\r\nCVE描述:\r\n在Apache HTTP Server 2.4.49的路径规范化更改中发现了一个缺陷。攻击者可以使用路径遍历攻击将url映射到预期文档根之外的文件。如果文档根目录之外的文件没有被“require all denied”保护,这些请求就可以成功。此外,这个缺陷可能会泄露解释文件(如CGI脚本)的源代码。众所周知,这个问题是在野外被利用的。此问题仅影响Apache 2.4.49,不影响Apache 2.4.49之前的版本。"}}
33 | ```
34 |
35 |
36 |
37 |
38 |
39 | > 选择json里面的模块
40 |
41 |
42 |
43 | `config.yaml`中配置`feishu`的`webhook`,`enable`设置为 `1`表示推送
44 |
45 | 效果:
46 |
47 | 
48 |
49 | ## Telegram Bot推送支持
50 |
51 | @[atsud0](https://github.com/atsud0) 师傅添加了 Telegram 推送
52 |
53 | 安装telegram bot
54 |
55 | ```
56 | pip install python-telegram-bot
57 | ```
58 |
59 | 生成bot 获得群组或用户聊天ID
60 |
61 | 创建bot详情谷歌
62 |
63 | ### 获得ID
64 |
65 | 将bot加入群组后,发送几条消息。访问https://api.telegram.org/bot{TOKEN}/getUpdates
66 |
67 | 用户ID同理,
68 |
69 | 
70 |
71 | `config.yaml`中配置`tgbot`的`token`等信息,`enable`设置为 `1`表示推送
72 |
73 |
74 |
75 | ## Server 酱
76 |
77 | ps:因微信的原因,server酱的旧版将在2021年4月后下线,新版以企业微信为主,这里使用的是旧版,想改新版的话,搞个企业微信,从新配置server酱,使用新链接 sctapi.ftqq.com
78 |
79 | 具体查看server酱官方,http://sc.ftqq.com/ ,配置简单,只需要将脚本中的uri换掉即可
80 |
81 | [server酱新版](https://sct.ftqq.com/)支持多通道(微信、客户端、群机器人、邮件和短信)
82 |
83 | `config.yaml`中配置`server`的`token`等信息,`enable`设置为 `1`表示推送
84 |
85 | ## 推送加【Mac 版微信可用】
86 |
87 | 免费的微信模板消息通知,支持在 Mac 版微信查看
88 |
89 | ### Mac微信效果
90 |
91 | 
92 |
93 | 具体配置方法见 pushplus 公众号文章:https://mp.weixin.qq.com/s/YRYb04PUFNVZejzV2G-k4w
94 |
95 | 同时也支持使用企业微信应用通知,只需从 API 接口修改默认配置即可:
96 |
97 | 
98 |
99 | 修改成功:
100 |
101 | 
102 |
103 | ### 企业微信应用效果
104 |
105 | 
106 |
107 | # Github 访问限制
108 |
109 | 监控工具更新 请求次数过多,超过了每小时请求,添加gihtub token
110 |
111 | > 对于未经身份验证的请求,github 速率限制允许每小时最多 60 个请求
112 | >
113 | > 而通过使用基本身份验证的 API 请求,每小时最多可以发出 5,000 个请求
114 | >
115 | > https://github.com/settings/tokens/new 创建token,时间的话选无限制的,毕竟要一直跑
116 |
117 | `config.yaml`中配置github_token
118 |
119 |
--------------------------------------------------------------------------------
/config.yaml:
--------------------------------------------------------------------------------
1 | all_config:
2 | github_token: xxxxxx
3 | dingding:
4 | - enable: 1
5 | - webhook: xxxxxxx
6 | - secretKey: xxxxxxx
7 | - app_name: dingding
8 | feishu:
9 | - enable: 0
10 | - webhook: xxx
11 | - app_name: feishu
12 | server:
13 | - enable: 0
14 | - sckey: 123123
15 | - app_name: server
16 | tgbot:
17 | - enable: 0
18 | - token: 123
19 | - group_id: 123
20 | - app_name: tgbot
21 | pushplus:
22 | - enable: 0
23 | - token: 123456
24 | - app_name: pushplus
25 | translate:
26 | - enable: 0
27 | black_user:
28 | - AlAIAL90
--------------------------------------------------------------------------------
/github_cve_monitor.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 | # -*- coding:utf-8 -*-
3 | # @Author : yhy&ddm&w4ter
4 |
5 | # 每3分钟检测一次githu
6 | # 是否有新的cve漏洞提交记录,若有则通过server酱和钉钉机器人推送,飞书捷径推送(二者配置一个即可)
7 | # 建议使用screen命令运行在自己的linux vps后台上,就可以愉快的接收各种cve了
8 | # https://my.oschina.net/u/4581868/blog/4380482
9 | # https://github.com/kiang70/Github-Monitor
10 | import json
11 | from collections import OrderedDict
12 | import requests, time, re
13 | import dingtalkchatbot.chatbot as cb
14 | import datetime
15 | import hashlib
16 | import yaml
17 | from lxml import etree
18 | import sqlite3
19 |
20 |
21 | # cve 仓库拥有者计数器(也就是黑名单,不过每天会清空重新计数),每天最多推送一个人名下的三个 cve 仓库,防止某些 sb 玩意
22 | counter = {}
23 |
24 | #读取配置文件
25 | def load_config():
26 | with open('config.yaml', 'r', encoding='utf-8') as f:
27 | config = yaml.load(f,Loader=yaml.FullLoader)
28 | github_token = config['all_config']['github_token']
29 | translate = False
30 | if int(config['all_config']['translate'][0]['enable']) == 1:
31 | translate = True
32 | if int(config['all_config']['dingding'][0]['enable']) == 1:
33 | dingding_webhook = config['all_config']['dingding'][1]['webhook']
34 | dingding_secretKey = config['all_config']['dingding'][2]['secretKey']
35 | app_name = config['all_config']['dingding'][3]['app_name']
36 | return app_name,github_token,dingding_webhook,dingding_secretKey, translate
37 | elif int(config['all_config']['feishu'][0]['enable']) == 1:
38 | feishu_webhook = config['all_config']['feishu'][1]['webhook']
39 | app_name = config['all_config']['feishu'][2]['app_name']
40 | return app_name,github_token,feishu_webhook,feishu_webhook, translate
41 | elif int(config['all_config']['server'][0]['enable']) == 1:
42 | server_sckey = config['all_config']['server'][1]['sckey']
43 | app_name = config['all_config']['server'][2]['app_name']
44 | return app_name,github_token,server_sckey, translate
45 | elif int(config['all_config']['pushplus'][0]['enable']) == 1:
46 | pushplus_token = config['all_config']['pushplus'][1]['token']
47 | app_name = config['all_config']['pushplus'][2]['app_name']
48 | return app_name,github_token,pushplus_token, translate
49 | elif int(config['all_config']['tgbot'][0]['enable']) ==1 :
50 | tgbot_token = config['all_config']['tgbot'][1]['token']
51 | tgbot_group_id = config['all_config']['tgbot'][2]['group_id']
52 | app_name = config['all_config']['tgbot'][3]['app_name']
53 | return app_name,github_token,tgbot_token,tgbot_group_id, translate
54 | elif int(config['all_config']['tgbot'][0]['enable']) == 0 and int(config['all_config']['feishu'][0]['enable']) == 0 and int(config['all_config']['server'][0]['enable']) == 0 and int(config['all_config']['pushplus'][0]['enable']) == 0 and int(config['all_config']['dingding'][0]['enable']) == 0:
55 | print("[-] 配置文件有误, 五个社交软件的enable不能为0")
56 |
57 | github_headers = {
58 | 'Authorization': "token {}".format(load_config()[1])
59 | }
60 |
61 | #读取黑名单用户
62 | def black_user():
63 | with open('config.yaml', 'r', encoding='utf-8') as f:
64 | config = yaml.load(f, Loader=yaml.FullLoader)
65 | black_user = config['all_config']['black_user']
66 | return black_user
67 |
68 | #初始化创建数据库
69 | def create_database():
70 | conn = sqlite3.connect('data.db')
71 | # print("[]create_database 函数 连接数据库成功!")
72 | # logging.info("create_database 函数 连接数据库成功!")
73 | cur = conn.cursor()
74 | try:
75 | cur.execute('''CREATE TABLE IF NOT EXISTS cve_monitor
76 | (cve_name varchar(255),
77 | pushed_at varchar(255),
78 | cve_url varchar(255));''')
79 | print("成功创建CVE监控表")
80 | cur.execute('''CREATE TABLE IF NOT EXISTS keyword_monitor
81 | (keyword_name varchar(255),
82 | pushed_at varchar(255),
83 | keyword_url varchar(255));''')
84 | print("成功创建关键字监控表")
85 | cur.execute('''CREATE TABLE IF NOT EXISTS redteam_tools_monitor
86 | (tools_name varchar(255),
87 | pushed_at varchar(255),
88 | tag_name varchar(255));''')
89 | print("成功创建红队工具监控表")
90 | cur.execute('''CREATE TABLE IF NOT EXISTS user_monitor
91 | (repo_name varchar(255));''')
92 | print("成功创建大佬仓库监控表")
93 | except Exception as e:
94 | print("创建监控表失败!报错:{}".format(e))
95 | conn.commit() # 数据库存储在硬盘上需要commit 存储在内存中的数据库不需要
96 | conn.close()
97 | if load_config()[0] == "dingding":
98 | dingding("test", "连接成功", load_config()[2], load_config()[3])
99 | elif load_config()[0] == "server":
100 | server("test", "连接成功", load_config()[2])
101 | elif load_config()[0] == "pushplus":
102 | pushplus("test", "连接成功", load_config()[2])
103 | elif load_config()[0] == "tgbot":
104 | tgbot("test", "连接成功", load_config()[2], load_config()[3])
105 | #根据排序获取本年前20条CVE
106 | def getNews():
107 | today_cve_info_tmp = []
108 | try:
109 | # 抓取本年的
110 | year = datetime.datetime.now().year
111 | api = "https://api.github.com/search/repositories?q=CVE-{}&sort=updated".format(year)
112 | json_str = requests.get(api, headers=github_headers, timeout=10).json()
113 | # cve_total_count = json_str['total_count']
114 | # cve_description = json_str['items'][0]['description']
115 | today_date = datetime.date.today()
116 | n = len(json_str['items'])
117 | if n > 30:
118 | n = 30
119 | for i in range(0, n):
120 | cve_url = json_str['items'][i]['html_url']
121 | if cve_url.split("/")[-2] not in black_user():
122 | try:
123 | cve_name_tmp = json_str['items'][i]['name'].upper()
124 | cve_name = re.findall('(CVE\-\d+\-\d+)', cve_name_tmp)[0].upper()
125 | pushed_at_tmp = json_str['items'][i]['created_at']
126 | pushed_at = re.findall('\d{4}-\d{2}-\d{2}', pushed_at_tmp)[0]
127 | if pushed_at == str(today_date):
128 | today_cve_info_tmp.append({"cve_name": cve_name, "cve_url": cve_url, "pushed_at": pushed_at})
129 | else:
130 | print("[-] 该{}的更新时间为{}, 不属于今天的CVE".format(cve_name, pushed_at))
131 | except Exception as e:
132 | pass
133 | else:
134 | pass
135 | today_cve_info = OrderedDict()
136 | for item in today_cve_info_tmp:
137 | user_name = item['cve_url'].split("/")[-2]
138 | if user_name in counter:
139 | if counter[user_name] < 3:
140 | counter[user_name] +=1
141 | today_cve_info.setdefault(item['cve_name'], {**item, })
142 | else:
143 | counter[user_name] = 0
144 | today_cve_info.setdefault(item['cve_name'], {**item, })
145 | today_cve_info = list(today_cve_info.values())
146 |
147 | return today_cve_info
148 | # return cve_total_count, cve_description, cve_url, cve_name
149 | #\d{4}-\d{2}-\d{2}
150 |
151 | except Exception as e:
152 | print(e, "github链接不通")
153 | return '', '', ''
154 |
155 | def getKeywordNews(keyword):
156 | today_keyword_info_tmp = []
157 | try:
158 | # 抓取本年的
159 | api = "https://api.github.com/search/repositories?q={}&sort=updated".format(keyword)
160 | json_str = requests.get(api, headers=github_headers, timeout=10).json()
161 | today_date = datetime.date.today()
162 | n = len(json_str['items'])
163 | if n > 20:
164 | n = 20
165 | for i in range(0, n):
166 | keyword_url = json_str['items'][i]['html_url']
167 | if keyword_url.split("/")[-2] not in black_user():
168 | try:
169 | keyword_name = json_str['items'][i]['name']
170 | pushed_at_tmp = json_str['items'][i]['created_at']
171 | pushed_at = re.findall('\d{4}-\d{2}-\d{2}', pushed_at_tmp)[0]
172 | if pushed_at == str(today_date):
173 | today_keyword_info_tmp.append({"keyword_name": keyword_name, "keyword_url": keyword_url, "pushed_at": pushed_at})
174 | print("[+] keyword: {} ,{}".format(keyword, keyword_name))
175 | else:
176 | print("[-] keyword: {} ,该{}的更新时间为{}, 不属于今天".format(keyword, keyword_name, pushed_at))
177 | except Exception as e:
178 | pass
179 | else:
180 | pass
181 | today_keyword_info = OrderedDict()
182 | for item in today_keyword_info_tmp:
183 | user_name = item['keyword_url'].split("/")[-2]
184 | if user_name in counter:
185 | if counter[user_name] < 3:
186 | counter[user_name] +=1
187 | today_keyword_info.setdefault(item['keyword_name'], {**item, })
188 | else:
189 | counter[user_name] = 0
190 | today_keyword_info.setdefault(item['keyword_name'], {**item, })
191 | today_keyword_info = list(today_keyword_info.values())
192 |
193 | return today_keyword_info
194 |
195 | except Exception as e:
196 | print(e, "github链接不通")
197 | return today_keyword_info_tmp
198 |
199 | #获取到的关键字仓库信息插入到数据库
200 | def keyword_insert_into_sqlite3(data):
201 | conn = sqlite3.connect('data.db')
202 | print("keyword_insert_into_sqlite3 函数 打开数据库成功!")
203 | print(data)
204 | cur = conn.cursor()
205 | for i in range(len(data)):
206 | try:
207 | keyword_name = data[i]['keyword_name']
208 | cur.execute("INSERT INTO keyword_monitor (keyword_name,pushed_at,keyword_url) VALUES ('{}', '{}', '{}')".format(keyword_name, data[i]['pushed_at'], data[i]['keyword_url']))
209 | print("keyword_insert_into_sqlite3 函数: {}插入数据成功!".format(keyword_name))
210 | except Exception as e:
211 | print("keyword_insert_into_sqlite3 error {}".format(e))
212 | pass
213 | conn.commit()
214 | conn.close()
215 | #查询数据库里是否存在该关键字仓库的方法
216 | def query_keyword_info_database(keyword_name):
217 | conn = sqlite3.connect('data.db')
218 | cur = conn.cursor()
219 | sql_grammar = "SELECT keyword_name FROM keyword_monitor WHERE keyword_name = '{}';".format(keyword_name)
220 | cursor = cur.execute(sql_grammar)
221 | return len(list(cursor))
222 |
223 | #获取不存在数据库里的关键字信息
224 | def get_today_keyword_info(today_keyword_info_data):
225 | today_all_keyword_info = []
226 | for i in range(len(today_keyword_info_data)):
227 | try:
228 | today_keyword_name = today_keyword_info_data[i]['keyword_name']
229 | today_cve_name = re.findall('(CVE\-\d+\-\d+)', today_keyword_info_data[i]['keyword_name'].upper())
230 | # 如果仓库名字带有 cve-xxx-xxx, 先查询看看 cve 监控中是否存在, 防止重复推送
231 | if len(today_cve_name) > 0 and query_cve_info_database(today_cve_name.upper()) == 1:
232 | pass
233 | Verify = query_keyword_info_database(today_keyword_name)
234 | if Verify == 0:
235 | print("[+] 数据库里不存在{}".format(today_keyword_name))
236 | today_all_keyword_info.append(today_keyword_info_data[i])
237 | else:
238 | print("[-] 数据库里存在{}".format(today_keyword_name))
239 | except Exception as e:
240 | pass
241 | return today_all_keyword_info
242 |
243 |
244 | #获取到的CVE信息插入到数据库
245 | def cve_insert_into_sqlite3(data):
246 | conn = sqlite3.connect('data.db')
247 | print("cve_insert_into_sqlite3 函数 打开数据库成功!")
248 | cur = conn.cursor()
249 | for i in range(len(data)):
250 | try:
251 | cve_name = re.findall('(CVE\-\d+\-\d+)', data[i]['cve_name'])[0].upper()
252 | cur.execute("INSERT INTO cve_monitor (cve_name,pushed_at,cve_url) VALUES ('{}', '{}', '{}')".format(cve_name, data[i]['pushed_at'], data[i]['cve_url']))
253 | print("cve_insert_into_sqlite3 函数: {}插入数据成功!".format(cve_name))
254 | except Exception as e:
255 | pass
256 | conn.commit()
257 | conn.close()
258 | #查询数据库里是否存在该CVE的方法
259 | def query_cve_info_database(cve_name):
260 | conn = sqlite3.connect('data.db')
261 | cur = conn.cursor()
262 | sql_grammar = "SELECT cve_name FROM cve_monitor WHERE cve_name = '{}';".format(cve_name)
263 | cursor = cur.execute(sql_grammar)
264 | return len(list(cursor))
265 | #查询数据库里是否存在该tools工具名字的方法
266 | def query_tools_info_database(tools_name):
267 | conn = sqlite3.connect('data.db')
268 | cur = conn.cursor()
269 | sql_grammar = "SELECT tools_name FROM redteam_tools_monitor WHERE tools_name = '{}';".format(tools_name)
270 | cursor = cur.execute(sql_grammar)
271 | return len(list(cursor))
272 | #获取不存在数据库里的CVE信息
273 | def get_today_cve_info(today_cve_info_data):
274 | today_all_cve_info = []
275 | # today_cve_info_data = getNews()
276 | for i in range(len(today_cve_info_data)):
277 | try:
278 | today_cve_name = re.findall('(CVE\-\d+\-\d+)', today_cve_info_data[i]['cve_name'])[0].upper()
279 | if exist_cve(today_cve_name) == 1:
280 | Verify = query_cve_info_database(today_cve_name.upper())
281 | if Verify == 0:
282 | print("[+] 数据库里不存在{}".format(today_cve_name.upper()))
283 | today_all_cve_info.append(today_cve_info_data[i])
284 | else:
285 | print("[-] 数据库里存在{}".format(today_cve_name.upper()))
286 | except Exception as e:
287 | pass
288 | return today_all_cve_info
289 | #获取红队工具信息插入到数据库
290 | def tools_insert_into_sqlite3(data):
291 | conn = sqlite3.connect('data.db')
292 | print("tools_insert_into_sqlite3 函数 打开数据库成功!")
293 | cur = conn.cursor()
294 | for i in range(len(data)):
295 | Verify = query_tools_info_database(data[i]['tools_name'])
296 | if Verify == 0:
297 | print("[+] 红队工具表数据库里不存在{}".format(data[i]['tools_name']))
298 | cur.execute("INSERT INTO redteam_tools_monitor (tools_name,pushed_at,tag_name) VALUES ('{}', '{}','{}')".format(data[i]['tools_name'], data[i]['pushed_at'], data[i]['tag_name']))
299 | print("tools_insert_into_sqlite3 函数: {}插入数据成功!".format(format(data[i]['tools_name'])))
300 | else:
301 | print("[-] 红队工具表数据库里存在{}".format(data[i]['tools_name']))
302 | conn.commit()
303 | conn.close()
304 | #读取本地红队工具链接文件转换成list
305 | def load_tools_list():
306 | with open('tools_list.yaml', 'r', encoding='utf-8') as f:
307 | list = yaml.load(f,Loader=yaml.FullLoader)
308 | return list['tools_list'], list['keyword_list'], list['user_list']
309 | #获取红队工具的名称,更新时间,版本名称信息
310 | def get_pushed_at_time(tools_list):
311 | tools_info_list = []
312 | for url in tools_list:
313 | try:
314 | tools_json = requests.get(url, headers=github_headers, timeout=10).json()
315 | pushed_at_tmp = tools_json['pushed_at']
316 | pushed_at = re.findall('\d{4}-\d{2}-\d{2}', pushed_at_tmp)[0] #获取的是API上的时间
317 | tools_name = tools_json['name']
318 | api_url = tools_json['url']
319 | try:
320 | releases_json = requests.get(url+"/releases", headers=github_headers, timeout=10).json()
321 | tag_name = releases_json[0]['tag_name']
322 | except Exception as e:
323 | tag_name = "no releases"
324 | tools_info_list.append({"tools_name":tools_name,"pushed_at":pushed_at,"api_url":api_url,"tag_name":tag_name})
325 | except Exception as e:
326 | print("get_pushed_at_time ", e)
327 | pass
328 |
329 | return tools_info_list
330 | #根据红队名名称查询数据库红队工具的更新时间以及版本名称并返回
331 | def tools_query_sqlite3(tools_name):
332 | result_list = []
333 | conn = sqlite3.connect('data.db')
334 | cur = conn.cursor()
335 | sql_grammar = "SELECT pushed_at,tag_name FROM redteam_tools_monitor WHERE tools_name = '{}';".format(tools_name)
336 | cursor = cur.execute(sql_grammar)
337 | for result in cursor:
338 | result_list.append({"pushed_at":result[0],"tag_name":result[1]})
339 | conn.close()
340 | print("[###########] tools_query_sqlite3 函数内 result_list 的值 为 - > {}".format(result_list))
341 | return result_list
342 | #获取更新了的红队工具在数据库里面的时间和版本
343 | def get_tools_update_list(data):
344 | tools_update_list = []
345 | for dist in data:
346 | print("dist 变量 ->{}".format(dist))
347 | query_result = tools_query_sqlite3(dist['tools_name'])
348 | if len(query_result) > 0:
349 | today_tools_pushed_at = query_result[0]['pushed_at']
350 | # print("[!!] 今日获取时间: ", dist['pushed_at'], "获取数据库时间: ", today_tools_pushed_at, dist['tools_name'])
351 | if dist['pushed_at'] != today_tools_pushed_at:
352 | print("今日获取时间: ",dist['pushed_at'],"获取数据库时间: ",today_tools_pushed_at,dist['tools_name'],"update!!!!")
353 | #返回数据库里面的时间和版本
354 | tools_update_list.append({"api_url":dist['api_url'],"pushed_at":today_tools_pushed_at,"tag_name":query_result[0]['tag_name']})
355 | else:
356 | print("今日获取时间: ",dist['pushed_at'],"获取数据库时间: ",today_tools_pushed_at,dist['tools_name']," no update")
357 | return tools_update_list
358 |
359 |
360 | # 监控用户是否新增仓库,不是 fork 的
361 | def getUserRepos(user):
362 | try:
363 | api = "https://api.github.com/users/{}/repos".format(user)
364 | json_str = requests.get(api, headers=github_headers, timeout=10).json()
365 | today_date = datetime.date.today()
366 |
367 | for i in range(0, len(json_str)):
368 | created_at = re.findall('\d{4}-\d{2}-\d{2}', json_str[i]['created_at'])[0]
369 | if json_str[i]['fork'] == False and created_at == str(today_date):
370 | Verify = user_insert_into_sqlite3(json_str[i]['full_name'])
371 | print(json_str[i]['full_name'], Verify)
372 | if Verify == 0:
373 | name = json_str[i]['name']
374 | try:
375 | description = json_str[i]['description']
376 | except Exception as e:
377 | description = "作者未写描述"
378 | download_url = json_str[i]['html_url']
379 | text = r'大佬' + r'** ' + user + r' ** ' + r'又分享了一款工具! '
380 | body = "工具名称: " + name + " \r\n" + "工具地址: " + download_url + " \r\n" + "工具描述: " + "" + description
381 | if load_config()[0] == "dingding":
382 | dingding(text, body,load_config()[2],load_config()[3])
383 | if load_config()[0] == "server":
384 | server(text, body,load_config()[2])
385 | if load_config()[0] == "pushplus":
386 | pushplus(text, body,load_config()[2])
387 | if load_config()[0] == "tgbot":
388 | tgbot(text,body,load_config()[2],load_config()[3])
389 | except Exception as e:
390 | print(e, "github链接不通")
391 |
392 | #获取用户或者组织信息插入到数据库
393 | def user_insert_into_sqlite3(repo_name):
394 | conn = sqlite3.connect('data.db')
395 | cur = conn.cursor()
396 | sql_grammar = "SELECT repo_name FROM user_monitor WHERE repo_name = '{}';".format(repo_name)
397 | Verify = len(list(cur.execute(sql_grammar)))
398 | if Verify == 0:
399 | print("[+] 用户仓库表数据库里不存在{}".format(repo_name))
400 | cur.execute("INSERT INTO user_monitor (repo_name) VALUES ('{}')".format(repo_name))
401 | print("user_insert_into_sqlite3 函数: {}插入数据成功!".format(repo_name))
402 | else:
403 | print("[-] 用户仓库表数据库里存在{}".format(repo_name))
404 | conn.commit()
405 | conn.close()
406 | return Verify
407 |
408 | #获取更新信息并发送到对应社交软件
409 | def send_body(url,query_pushed_at,query_tag_name):
410 | # 考虑到有的工具没有 releases, 则通过 commits 记录获取更新描述
411 | # 判断是否有 releases 记录
412 | json_str = requests.get(url + '/releases', headers=github_headers, timeout=10).json()
413 | new_pushed_at = re.findall('\d{4}-\d{2}-\d{2}', requests.get(url, headers=github_headers, timeout=10).json()['pushed_at'])[0]
414 | if len(json_str) != 0:
415 | tag_name = json_str[0]['tag_name']
416 | if query_pushed_at < new_pushed_at :
417 | print("[*] 数据库里的pushed_at -->", query_pushed_at, ";;;; api的pushed_at -->", new_pushed_at)
418 | if tag_name != query_tag_name:
419 | try:
420 | update_log = json_str[0]['body']
421 | except Exception as e:
422 | update_log = "作者未写更新内容"
423 | download_url = json_str[0]['html_url']
424 | tools_name = url.split('/')[-1]
425 | text = r'** ' + tools_name + r' ** 工具,版本更新啦!'
426 | body = "工具名称:" + tools_name + "\r\n" + "工具地址:" + download_url + "\r\n" + "工具更新日志:" + "\r\n" + update_log
427 | if load_config()[0] == "dingding":
428 | dingding(text, body,load_config()[2],load_config()[3])
429 | if load_config()[0] == "server":
430 | server(text, body,load_config()[2])
431 | if load_config()[0] == "pushplus":
432 | pushplus(text, body,load_config()[2])
433 | if load_config()[0] == "tgbot":
434 | tgbot(text,body,load_config()[2],load_config()[3])
435 | conn = sqlite3.connect('data.db')
436 | cur = conn.cursor()
437 | sql_grammar = "UPDATE redteam_tools_monitor SET tag_name = '{}' WHERE tools_name='{}'".format(tag_name,tools_name)
438 | sql_grammar1 = "UPDATE redteam_tools_monitor SET pushed_at = '{}' WHERE tools_name='{}'".format(new_pushed_at, tools_name)
439 | cur.execute(sql_grammar)
440 | cur.execute(sql_grammar1)
441 | conn.commit()
442 | conn.close()
443 | print("[+] tools_name -->", tools_name, "pushed_at 已更新,现在pushed_at 为 -->", new_pushed_at,"tag_name 已更新,现在tag_name为 -->",tag_name)
444 | elif tag_name == query_tag_name:
445 | commits_url = url + "/commits"
446 | commits_url_response_json = requests.get(commits_url).text
447 | commits_json = json.loads(commits_url_response_json)
448 | tools_name = url.split('/')[-1]
449 | download_url = commits_json[0]['html_url']
450 | try:
451 | update_log = commits_json[0]['commit']['message']
452 | except Exception as e:
453 | update_log = "作者未写更新内容,具体点击更新详情地址的URL进行查看"
454 | text = r'** ' + tools_name + r' ** 工具小更新了一波!'
455 | body = "工具名称:" + tools_name + "\r\n" + "更新详情地址:" + download_url + "\r\n" + "commit更新日志:" + "\r\n" + update_log
456 | if load_config()[0] == "dingding":
457 | dingding(text, body,load_config()[2],load_config()[3])
458 | if load_config()[0] == "feishu":
459 | feishu(text,body,load_config()[2])
460 | if load_config()[0] == "server":
461 | server(text, body,load_config()[2])
462 | if load_config()[0] == "pushplus":
463 | pushplus(text, body,load_config()[2])
464 | if load_config()[0] == "tgbot":
465 | tgbot(text,body,load_config()[2],load_config()[3])
466 | conn = sqlite3.connect('data.db')
467 | cur = conn.cursor()
468 | sql_grammar = "UPDATE redteam_tools_monitor SET pushed_at = '{}' WHERE tools_name='{}'".format(new_pushed_at,tools_name)
469 | cur.execute(sql_grammar)
470 | conn.commit()
471 | conn.close()
472 | print("[+] tools_name -->",tools_name,"pushed_at 已更新,现在pushed_at 为 -->",new_pushed_at)
473 |
474 | # return update_log, download_url, tools_version
475 | else:
476 | if query_pushed_at != new_pushed_at:
477 | print("[*] 数据库里的pushed_at -->", query_pushed_at, ";;;; api的pushed_at -->", new_pushed_at)
478 | json_str = requests.get(url + '/commits', headers=github_headers, timeout=10).json()
479 | update_log = json_str[0]['commit']['message']
480 | download_url = json_str[0]['html_url']
481 | tools_name = url.split('/')[-1]
482 | text = r'** ' + tools_name + r' ** 工具更新啦!'
483 | body = "工具名称:" + tools_name + "\r\n" + "工具地址:" + download_url + "\r\n" + "commit更新日志:" + "\r\n" + update_log
484 | if load_config()[0] == "dingding":
485 | dingding(text, body, load_config()[2], load_config()[3])
486 | if load_config()[0] == "feishu":
487 | feishu(text,body,load_config[2])
488 | if load_config()[0] == "server":
489 | server(text, body, load_config()[2])
490 | if load_config()[0] == "pushplus":
491 | pushplus(text, body,load_config()[2])
492 | if load_config()[0] == "tgbot":
493 | tgbot(text, body, load_config()[2], load_config()[3])
494 | conn = sqlite3.connect('data.db')
495 | cur = conn.cursor()
496 | sql_grammar = "UPDATE redteam_tools_monitor SET pushed_at = '{}' WHERE tools_name='{}'".format(new_pushed_at,tools_name)
497 | cur.execute(sql_grammar)
498 | conn.commit()
499 | conn.close()
500 | print("[+] tools_name -->", tools_name, "pushed_at 已更新,现在pushed_at 为 -->", new_pushed_at)
501 | # return update_log, download_url
502 | # 创建md5对象
503 | def nmd5(str):
504 | m = hashlib.md5()
505 | b = str.encode(encoding='utf-8')
506 | m.update(b)
507 | str_md5 = m.hexdigest()
508 | return str_md5
509 | # 有道翻译
510 | def translate(word):
511 | headerstr = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36'
512 | bv = nmd5(headerstr)
513 | lts = str(round(time.time() * 1000))
514 | salt = lts + '90'
515 | # 如果翻译失败,{'errorCode': 50} 请查看 fanyi.min.js: https://shared.ydstatic.com/fanyi/newweb/v1.1.7/scripts/newweb/fanyi.min.js
516 | # 搜索 fanyideskweb sign: n.md5("fanyideskweb" + e + i + "Y2FYu%TNSbMCxc3t2u^XT") ,Y2FYu%TNSbMCxc3t2u^XT是否改变,替换即可
517 | strexample = 'fanyideskweb' + word + salt + 'Y2FYu%TNSbMCxc3t2u^XT'
518 | sign = nmd5(strexample)
519 | data = {
520 | 'i': word,
521 | 'from': 'AUTO',
522 | 'to': 'AUTO',
523 | 'smartresult': 'dict',
524 | 'client': 'fanyideskweb',
525 | 'salt': salt,
526 | 'sign': sign,
527 | 'lts': lts,
528 | 'bv': bv,
529 | 'doctype': 'json',
530 | 'version': '2.1',
531 | 'keyfrom': 'fanyi.web',
532 | 'action': 'FY_BY_CLICKBUTTION',
533 | }
534 | url = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'
535 | header = {
536 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36',
537 | 'Referer': 'http://fanyi.youdao.com/',
538 | 'Origin': 'http://fanyi.youdao.com',
539 | 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
540 | 'X-Requested-With': 'XMLHttpRequest',
541 | 'Accept': 'application/json, text/javascript, */*; q=0.01',
542 | 'Accept-Encoding': 'gzip, deflate',
543 | 'Accept-Language': 'zh-CN,zh;q=0.9',
544 | 'Connection': 'keep-alive',
545 | 'Host': 'fanyi.youdao.com',
546 | 'cookie': '_ntes_nnid=937f1c788f1e087cf91d616319dc536a,1564395185984; OUTFOX_SEARCH_USER_ID_NCOO=; OUTFOX_SEARCH_USER_ID=-10218418@11.136.67.24; JSESSIONID=; ___rl__test__cookies=1'
547 | }
548 | res = requests.post(url=url, data=data, headers=header)
549 | result_dict = res.json()
550 | result = ""
551 | for json_str in result_dict['translateResult'][0]:
552 | tgt = json_str['tgt']
553 | result += tgt
554 | return result
555 |
556 | # 钉钉
557 | def dingding(text, msg,webhook,secretKey):
558 | ding = cb.DingtalkChatbot(webhook, secret=secretKey)
559 | ding.send_text(msg='{}\r\n{}'.format(text, msg), is_at_all=False)
560 | ## 飞书
561 | def feishu(text,msg,webhook):
562 | ding = cb.DingtalkChatbot(webhook)
563 | ding.send_text(msg='{}\r\n{}'.format(text, msg), is_at_all=False)
564 | # server酱 http://sc.ftqq.com/?c=code
565 | def server(text, msg,sckey):
566 | try:
567 | uri = 'https://sc.ftqq.com/{}.send?text={}&desp={}'.format(sckey,text, msg)# 将 xxxx 换成自己的server SCKEY
568 | requests.get(uri, timeout=10)
569 | except Exception as e:
570 | pass
571 | # pushplus https://www.pushplus.plus/push1.html
572 | def pushplus(text, msg,token):
573 | try:
574 | uri = 'https://www.pushplus.plus/send?token={}&title={}&content={}'.format(token,text, msg)# 将 xxxx 换成自己的pushplus的 token
575 | requests.get(uri, timeout=10)
576 | except Exception as e:
577 | pass
578 | # 添加Telegram Bot推送支持
579 | def tgbot(text, msg,token,group_id):
580 | import telegram
581 | try:
582 | bot = telegram.Bot(token='{}'.format(token))# Your Telegram Bot Token
583 | bot.send_message(chat_id=group_id, text='{}\r\n{}'.format(text, msg))
584 | except Exception as e:
585 | pass
586 |
587 | #判断是否存在该CVE
588 | def exist_cve(cve):
589 | try:
590 | query_cve_url = "https://cve.mitre.org/cgi-bin/cvename.cgi?name=" + cve
591 | response = requests.get(query_cve_url, timeout=10)
592 | html = etree.HTML(response.text)
593 | des = html.xpath('//*[@id="GeneratedTable"]/table//tr[4]/td/text()')[0].strip()
594 | return 1
595 | except Exception as e:
596 | return 0
597 |
598 | # 根据cve 名字,获取描述,并翻译
599 | def get_cve_des_zh(cve):
600 | time.sleep(3)
601 | try:
602 | query_cve_url = "https://cve.mitre.org/cgi-bin/cvename.cgi?name=" + cve
603 | response = requests.get(query_cve_url, timeout=10)
604 | html = etree.HTML(response.text)
605 | des = html.xpath('//*[@id="GeneratedTable"]/table//tr[4]/td/text()')[0].strip()
606 | cve_time = html.xpath('//*[@id="GeneratedTable"]/table//tr[11]/td[1]/b/text()')[0].strip()
607 | if load_config()[-1]:
608 | return translate(des)
609 | return des, cve_time
610 | except Exception as e:
611 | pass
612 | #发送CVE信息到社交工具
613 | def sendNews(data):
614 | try:
615 | text = '有新的CVE送达! \r\n** 请自行分辨是否为红队钓鱼!!! **'
616 | # 获取 cve 名字 ,根据cve 名字,获取描述,并翻译
617 | for i in range(len(data)):
618 | try:
619 | cve_name = re.findall('(CVE\-\d+\-\d+)', data[i]['cve_name'])[0].upper()
620 | cve_zh, cve_time = get_cve_des_zh(cve_name)
621 | body = "CVE编号: " + cve_name + " --- " + cve_time + " \r\n" + "Github地址: " + str(data[i]['cve_url']) + "\r\n" + "CVE描述: " + "\r\n" + cve_zh
622 | if load_config()[0] == "dingding":
623 | dingding(text, body, load_config()[2], load_config()[3])
624 | print("钉钉 发送 CVE 成功")
625 | if load_config()[0] == "feishu":
626 | feishu(text, body, load_config()[2])
627 | print("飞书 发送 CVE 成功")
628 | if load_config()[0] == "server":
629 | server(text, body, load_config()[2])
630 | print("server酱 发送 CVE 成功")
631 | if load_config()[0] == "pushplus":
632 | pushplus(text, body, load_config()[2])
633 | print("pushplus 发送 CVE 成功")
634 | if load_config()[0] == "tgbot":
635 | tgbot(text, body, load_config()[2], load_config()[3])
636 | print("tgbot 发送 CVE 成功")
637 | except IndexError:
638 | pass
639 | except Exception as e:
640 | print("sendNews 函数 error:{}".format(e))
641 |
642 | #发送信息到社交工具
643 | def sendKeywordNews(keyword, data):
644 | try:
645 | text = '有新的关键字监控 - {} - 送达! \r\n** 请自行分辨是否为红队钓鱼!!! **'.format(keyword)
646 | # 获取 cve 名字 ,根据cve 名字,获取描述,并翻译
647 | for i in range(len(data)):
648 | try:
649 | keyword_name = data[i]['keyword_name']
650 | body = "项目名称: " + keyword_name + "\r\n" + "Github地址: " + str(data[i]['keyword_url']) + "\r\n"
651 | if load_config()[0] == "dingding":
652 | dingding(text, body, load_config()[2], load_config()[3])
653 | print("钉钉 发送 CVE 成功")
654 | if load_config()[0] == "feishu":
655 | feishu(text, body, load_config()[2])
656 | print("飞书 发送 CVE 成功")
657 | if load_config()[0] == "server":
658 | server(text, body, load_config()[2])
659 | print("server酱 发送 CVE 成功")
660 | if load_config()[0] == "pushplus":
661 | pushplus(text, body, load_config()[2])
662 | print("pushplus 发送 CVE 成功")
663 | if load_config()[0] == "tgbot":
664 | tgbot(text, body, load_config()[2], load_config()[3])
665 | print("tgbot 发送 CVE 成功")
666 | except IndexError:
667 | pass
668 | except Exception as e:
669 | print("sendKeywordNews 函数 error:{}".format(e))
670 |
671 | #main函数
672 | if __name__ == '__main__':
673 | print("cve 、github 工具 和 大佬仓库 监控中 ...")
674 | #初始化部分
675 | create_database()
676 |
677 | while True:
678 | # 判断是否达到设定时间
679 | now = datetime.datetime.now()
680 | # 到达设定时间,结束内循环
681 | if now.hour == 23 and now.minute > 50:
682 | counter = {} # 每天初始化黑名单
683 |
684 | tools_list, keyword_list, user_list = load_tools_list()
685 | tools_data = get_pushed_at_time(tools_list)
686 | tools_insert_into_sqlite3(tools_data) # 获取文件中的工具列表,并从 github 获取相关信息,存储下来
687 |
688 | print("\r\n\t\t 用户仓库监控 \t\t\r\n")
689 | for user in user_list:
690 | getUserRepos(user)
691 | #CVE部分
692 | print("\r\n\t\t CVE 监控 \t\t\r\n")
693 | cve_data = getNews()
694 | if len(cve_data) > 0 :
695 | today_cve_data = get_today_cve_info(cve_data)
696 | sendNews(today_cve_data)
697 | cve_insert_into_sqlite3(today_cve_data)
698 |
699 | print("\r\n\t\t 关键字监控 \t\t\r\n")
700 | # 关键字监控 , 最好不要太多关键字,防止 github 次要速率限制 https://docs.github.com/en/rest/overview/resources-in-the-rest-api#secondary-rate-limits=
701 | for keyword in keyword_list:
702 | time.sleep(1) # 每个关键字停 1s ,防止关键字过多导致速率限制
703 | keyword_data = getKeywordNews(keyword)
704 |
705 | if len(keyword_data) > 0:
706 | today_keyword_data = get_today_keyword_info(keyword_data)
707 | if len(today_keyword_data) > 0:
708 | sendKeywordNews(keyword, today_keyword_data)
709 | keyword_insert_into_sqlite3(today_keyword_data)
710 |
711 | print("\r\n\t\t 红队工具监控 \t\t\r\n")
712 | time.sleep(5*60)
713 | tools_list_new, keyword_list, user_list = load_tools_list()
714 | data2 = get_pushed_at_time(tools_list_new) # 再次从文件中获取工具列表,并从 github 获取相关信息,
715 | data3 = get_tools_update_list(data2) # 与 3 分钟前数据进行对比,如果在三分钟内有新增工具清单或者工具有更新则通知一下用户
716 | for i in range(len(data3)):
717 | try:
718 | send_body(data3[i]['api_url'],data3[i]['pushed_at'],data3[i]['tag_name'])
719 | except Exception as e:
720 | print("main函数 try循环 遇到错误-->{}".format(e))
721 |
--------------------------------------------------------------------------------
/images/124256679-27701e00-db5e-11eb-9432-d3a9048daeec.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhy0/github-cve-monitor/570b0645f8f51706d984ff9ba97e0a79d733bf66/images/124256679-27701e00-db5e-11eb-9432-d3a9048daeec.png
--------------------------------------------------------------------------------
/images/image-20210729172507519.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhy0/github-cve-monitor/570b0645f8f51706d984ff9ba97e0a79d733bf66/images/image-20210729172507519.png
--------------------------------------------------------------------------------
/images/image-20211118142412234.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhy0/github-cve-monitor/570b0645f8f51706d984ff9ba97e0a79d733bf66/images/image-20211118142412234.png
--------------------------------------------------------------------------------
/images/image-20211118145021974.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhy0/github-cve-monitor/570b0645f8f51706d984ff9ba97e0a79d733bf66/images/image-20211118145021974.png
--------------------------------------------------------------------------------
/images/image-20220126105710922.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhy0/github-cve-monitor/570b0645f8f51706d984ff9ba97e0a79d733bf66/images/image-20220126105710922.png
--------------------------------------------------------------------------------
/images/image-20220126110109185.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhy0/github-cve-monitor/570b0645f8f51706d984ff9ba97e0a79d733bf66/images/image-20220126110109185.png
--------------------------------------------------------------------------------
/images/image-20220126110312664.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhy0/github-cve-monitor/570b0645f8f51706d984ff9ba97e0a79d733bf66/images/image-20220126110312664.png
--------------------------------------------------------------------------------
/images/image-20220126110919827.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhy0/github-cve-monitor/570b0645f8f51706d984ff9ba97e0a79d733bf66/images/image-20220126110919827.png
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | requests
2 | dingtalkchatbot
3 | pyyaml
4 | lxml
5 |
--------------------------------------------------------------------------------
/tools_list.yaml:
--------------------------------------------------------------------------------
1 | tools_list:
2 | - https://api.github.com/repos/BeichenDream/Godzilla
3 | - https://api.github.com/repos/rebeyond/Behinder
4 | - https://api.github.com/repos/AntSwordProject/antSword
5 | - https://api.github.com/repos/j1anFen/shiro_attack
6 | - https://api.github.com/repos/yhy0/github-cve-monitor
7 | - https://api.github.com/repos/gentilkiwi/mimikatz
8 | - https://api.github.com/repos/ehang-io/nps
9 | - https://api.github.com/repos/chaitin/xray
10 | - https://api.github.com/repos/FunnyWolf/pystinger
11 | - https://api.github.com/repos/L-codes/Neo-reGeorg
12 | - https://api.github.com/repos/shadow1ng/fscan
13 | - https://api.github.com/repos/SafeGroceryStore/MDUT
14 | - https://api.github.com/repos/EdgeSecurityTeam/Vulnerability
15 |
16 | keyword_list:
17 | - Sql注入
18 | - cnvd
19 | - 未授权
20 |
21 | user_list:
22 | - yhy0
23 | - su18
24 | - BeichenDream
25 | - phith0n
26 | - zhzyker
27 | - lijiejie
28 | - projectdiscovery
29 | - HavocFramework
--------------------------------------------------------------------------------