├── __init__.py
├── CNAME
├── gsil
├── tests
│ ├── __init__.py
│ ├── test_process.py
│ ├── test_notification.py
│ └── test_github.py
├── log.py
├── notification.py
├── __init__.py
├── process.py
├── config.py
└── engine.py
├── _config.yml
├── .gitignore
├── requirements.txt
├── config.gsil.cfg.example
├── rules.gsil.yaml.example
├── tests.py
├── tests
└── test.gsil
├── gsil.py
├── README-zh.md
├── README.md
└── LICENSE
/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/CNAME:
--------------------------------------------------------------------------------
1 | gsil.feei.cn
--------------------------------------------------------------------------------
/gsil/tests/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-midnight
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | logs/
2 | .idea/
3 | .cache/
4 | *.pyc
5 | config.gsil
6 | rules.gsil
--------------------------------------------------------------------------------
/gsil/tests/test_process.py:
--------------------------------------------------------------------------------
1 | from gsil.process import clone
2 |
3 |
4 | def test_clone():
5 | clone('https://github.com/FeeiCN/dict', 'ttt')
6 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | beautifulsoup4==4.6.0
2 | PyGithub==1.35
3 | IPy==0.83
4 | tld==0.7.9
5 | html5lib==0.999999999
6 | requests>=2.20.0
7 | colorlog==3.1.0
8 | Jinja2==2.11.3
9 | pyyaml
--------------------------------------------------------------------------------
/config.gsil.cfg.example:
--------------------------------------------------------------------------------
1 | [mail]
2 | host : smtp.exmail.qq.com
3 | port : 25
4 | mails : your_mail
5 | from : GSIL
6 | password : your_password
7 | to : feei@feei.cn
8 | cc : feei@feei.cn
9 |
10 | [github]
11 | clone : false
12 | tokens : your_github_token
13 |
--------------------------------------------------------------------------------
/rules.gsil.yaml.example:
--------------------------------------------------------------------------------
1 | {
2 | "test": {
3 | "mogujie.com": {
4 | "\"mogujie.org\"": {
5 | "mode": "normal-match",
6 | "ext": "php,java,python,go,js,properties"
7 | }
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/tests.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | from gsil.notification import Notification
3 |
4 |
5 | class Tests(unittest.TestCase):
6 | def test_notification(self):
7 | subject = 'test from GSIL'
8 | to = cc = 'feei@feei.cn'
9 | html = '
Test Content from GSIL
'
10 | self.assertTrue(Notification(subject, to, cc).notification(html))
11 |
12 |
13 | if __name__ == '__main__':
14 | unittest.main()
15 |
--------------------------------------------------------------------------------
/tests/test.gsil:
--------------------------------------------------------------------------------
1 | # 如果从扫描器看过来的,对比这个文件的最后修改时间和收到泄露通知的时间
2 | # 如果大于10分钟,可以直接使用GSIL替换掉原有的泄露监控
3 | http://gsil.home.mogujie.org/test_by_feei_for_gsil.py
4 | http://gsil.tencent.oa.com/test_by_feei_for_gsil.py
5 | http://gsil.www.mogujie.org/test_by_feei_for_gsil.java
6 | http://gsil.iqiyi.host/test_by_feei_for_gsil.java
7 | http://gsil.dev.qunar.com/test_by_feei_for_gsil.java
8 | http://gsil.taobao.net/test_by_feei_for_gsil.java
9 | http://gsil.alipay.net/test_by_feei_for_gsil.java
10 | http://gsil.intra.xiaojukeji.com/test_by_feei_for_gsil.java
11 | http://gsil.tencent.com/test_by_feei_for_gsil.java
12 |
--------------------------------------------------------------------------------
/gsil/tests/test_notification.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | tests.text_notification
5 | ~~~~~~~~~~~~~~~~~~~~~~~
6 |
7 | Implements test notification
8 |
9 | :author: Feei
10 | :homepage: https://github.com/FeeiCN/gsil
11 | :license: GPL, see LICENSE for more details.
12 | :copyright: Copyright (c) 2018 Feei. All rights reserved
13 | """
14 | from gsil.notification import Notification
15 | from gsil.process import send_running_data_report
16 |
17 |
18 | def test_send():
19 | assert True is Notification('Test', 'feei@feei.cn').notification('This is a test mail')
20 |
21 |
22 | def test_send_running_data():
23 | assert send_running_data_report()
24 |
--------------------------------------------------------------------------------
/gsil.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | """
5 | GSIL
6 | ~~~~
7 |
8 | Implements GSIL entry
9 |
10 | Usage:
11 | python gsil.py test
12 |
13 | :author: Feei
14 | :homepage: https://github.com/wufeifei/cobra
15 | :license: MIT, see LICENSE for more details.
16 | :copyright: Copyright (c) 2018 Feei. All rights reserved
17 | """
18 | import sys
19 | import traceback
20 | from gsil import gsil
21 | from gsil.notification import Notification
22 |
23 | if __name__ == '__main__':
24 | try:
25 | if len(sys.argv) < 2:
26 | print('python gsil.py ')
27 | exit(0)
28 | sys.exit(gsil())
29 | except Exception as e:
30 | # 发送异常报告
31 | content = '{a}\r\n{e}'.format(a=' '.join(sys.argv), e=traceback.format_exc())
32 | Notification('GSIL Exception').notification(content)
33 |
--------------------------------------------------------------------------------
/gsil/tests/test_github.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | tests.test_github
5 | ~~~~~~~~~~~~~~~~~
6 |
7 | Implements test GitHub API
8 |
9 | :author: Feei
10 | :homepage: https://github.com/FeeiCN/gsil
11 | :license: GPL, see LICENSE for more details.
12 | :copyright: Copyright (c) 2018 Feei. All rights reserved
13 | """
14 | import base64
15 | import pytest
16 | from github import Github, BadCredentialsException
17 |
18 | TOKEN = base64.b64decode('YzA4YTVhOTA1ZGExYjg5YTc1ZmI4NmE3MmM3ZjUyNzg2NmRmZmRlNA==').decode()
19 |
20 |
21 | def test_init_success():
22 | g = Github(login_or_token=TOKEN)
23 | try:
24 | limit, limit2 = g.rate_limiting
25 | assert limit > 4900
26 | except BadCredentialsException as e:
27 | assert False
28 |
29 | g = Github(login_or_token=TOKEN[0:18])
30 | with pytest.raises(BadCredentialsException) as e:
31 | g = g.rate_limiting
32 |
--------------------------------------------------------------------------------
/gsil/log.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | log
5 | ~~~
6 |
7 | Implements color logger
8 |
9 | :author: Feei
10 | :homepage: https://github.com/wufeifei/cobra
11 | :license: MIT, see LICENSE for more details.
12 | :copyright: Copyright (c) 2018 Feei. All rights reserved
13 | """
14 | import os
15 | import colorlog
16 | import logging
17 | from logging import handlers
18 |
19 | log_path = 'logs'
20 | if os.path.isdir(log_path) is not True:
21 | os.mkdir(log_path, 0o755)
22 | logfile = os.path.join(log_path, 'gsil.log')
23 |
24 | handler = colorlog.StreamHandler()
25 | formatter = colorlog.ColoredFormatter(
26 | '%(log_color)s%(asctime)s [%(name)s] [%(levelname)s] %(message)s%(reset)s',
27 | datefmt=None,
28 | reset=True,
29 | log_colors={
30 | 'DEBUG': 'cyan',
31 | 'INFO': 'green',
32 | 'WARNING': 'yellow',
33 | 'ERROR': 'red',
34 | 'CRITICAL': 'red,bg_white',
35 | },
36 | secondary_log_colors={},
37 | style='%'
38 | )
39 | handler.setFormatter(formatter)
40 |
41 | file_handler = handlers.RotatingFileHandler(logfile, maxBytes=(1048576 * 5), backupCount=7)
42 | file_handler.setFormatter(formatter)
43 |
44 | logger = colorlog.getLogger('GSIL')
45 | logger.addHandler(handler)
46 | logger.addHandler(file_handler)
47 | logger.setLevel(logging.INFO)
48 |
--------------------------------------------------------------------------------
/gsil/notification.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | notification
5 | ~~~~~~~~~~~~
6 |
7 | Implements notification(mail)
8 |
9 | :author: Feei
10 | :homepage: https://github.com/FeeiCN/gsil
11 | :license: GPL, see LICENSE for more details.
12 | :copyright: Copyright (c) 2018 Feei. All rights reserved
13 | """
14 | import random
15 | import smtplib
16 | import traceback
17 | from smtplib import SMTPException
18 | from email.mime.text import MIMEText
19 | from email.mime.multipart import MIMEMultipart
20 | from .config import get
21 | from .log import logger
22 |
23 |
24 | class Notification(object):
25 | def __init__(self, subject, to=None, cc=None):
26 | """
27 | Initialize notification class
28 | :param subject:
29 | :param to:
30 | """
31 | self.subject = subject
32 | if to is None:
33 | self.to = get('mail', 'to')
34 | else:
35 | self.to = to
36 | if cc is None:
37 | self.cc = get('mail', 'cc')
38 | else:
39 | self.cc = cc
40 |
41 | def notification(self, html):
42 | """
43 | Send notification use by mail
44 | :param html:
45 | :return:
46 | """
47 | # 随机挑选一个邮箱来发送,避免由于发送量过大导致被封
48 | mails = get('mail', 'mails').split(',')
49 | mail = random.choice(mails)
50 | mail_from = get('mail', 'from')
51 | msg = MIMEMultipart()
52 | msg['Subject'] = self.subject
53 | msg['From'] = f'{mail} <{mail_from}>'
54 | # 支持多用户接收邮件
55 | msg['To'] = self.to
56 | msg['Cc'] = self.cc
57 |
58 | text = MIMEText(html, 'html', 'utf-8')
59 | msg.attach(text)
60 | host = get('mail', 'host').strip()
61 | port = get('mail', 'port').strip()
62 |
63 | try:
64 | if port == '465':
65 | port = int(port)
66 | s = smtplib.SMTP_SSL(host, port)
67 | else:
68 | s = smtplib.SMTP(host, port)
69 | s.ehlo()
70 | s.starttls()
71 | s.ehlo()
72 | s.login(mail, get('mail', 'password'))
73 | s.sendmail(mail, self.to.split(',')+self.cc.split(','), msg.as_string())
74 | s.quit()
75 | return True
76 | except SMTPException:
77 | logger.critical('Send mail failed')
78 | traceback.print_exc()
79 | return False
80 |
--------------------------------------------------------------------------------
/README-zh.md:
--------------------------------------------------------------------------------
1 | # GSIL(GitHub敏感信息泄露)
2 |
3 | [English documents](https://github.com/FeeiCN/GSIL/blob/master/README.md)
4 |
5 | > 近实时监控GitHub敏感信息泄露,并发送告警通知。
6 |
7 | ## 安装
8 |
9 | > 仅在Python3下验证过
10 |
11 | ```bash
12 | $ git clone https://github.com/FeeiCN/GSIL.git
13 | $ cd GSIL/
14 | $ pip install -r requirements.txt
15 | ```
16 |
17 | ## 配置
18 |
19 | ### GSIL/config.gsil(复制config.gsil.cfg.example并重命名config.gsil.cfg): 告警邮箱和Github配置
20 |
21 | ```
22 | [mail]
23 | host : smtp.exmail.qq.com
24 | # SMTP端口(非SSL端口,但会使用TLS加密)
25 | port : 25
26 | # 多个发件人使用逗号(,)分隔
27 | mails : gsil@feei.cn
28 | from : GSIL
29 | password : your_password
30 | # 多个收件人使用逗号(,)分隔
31 | to : feei@feei.cn
32 |
33 | [github]
34 | # 扫描到的漏洞仓库是否立刻Clone到本地(~/.gsil/codes/)
35 | # 此选项用作监控其它厂商,避免因为仓库所有者发现后被删除
36 | clone: false
37 |
38 | # GitHub Token用来调用相关API,多个Token使用逗号(,)分隔
39 | # https://github.com/settings/tokens
40 | # GitHub已调整最新的速度限制,请求数量大幅降低,单账户多Token将共享限速,详见https://docs.github.com/en/rest/reference/search#rate-limit 以及 https://docs.github.com/en/rest/reference/rate-limit
41 | # 建议你根据关键词数量配置多个GitHub账户的Token以避免超速
42 | tokens : your_token
43 | ```
44 |
45 | ### GSIL/rules.gsil(复制rules.gsil.yaml.example并重命名rules.gsil.yaml): 扫描规则
46 |
47 | > 规则一般选用内网独立的特征,比如蘑菇街的外网是mogujie.com,蘑菇街的内网是mogujie.org,则可以将mogujie.org作为一条规则。
48 |
49 | > 其它还有类似代码头部特征、外部邮箱特征等
50 |
51 | | 字段 | 意义 | 选填 | 默认 | 描述 |
52 | | --- | --- | --- | --- | --- |
53 | | keyword | 关键词 | 必填 | - | 多个关键词可以用空格,比如‘账号 密码’;某些关键字出现的结果非常多,所以需要精确搜索时可以用双引号括起来,比如‘”ele.me“’;|
54 | | ext | 指定文件后缀 | 可选 | 全部后缀 | 多个后缀可以使用英文半角逗号(,)分隔,比如`java,php,python` |
55 | | mode | 匹配模式 | 可选 | 正常匹配(normal-match) | 正常匹配(normal-match):匹配包含keyword的行,并记录该行附近行 / 仅匹配(only-match):仅匹配包含keyword行 / 全部匹配(full-match)(不推荐使用):搜出来的整个问题都算作结果 |
56 |
57 | ```
58 | {
59 | # 一级分类,一般使用公司名,用作开启扫描的第一个参数(python gsil.py test)
60 | "test": {
61 | # 二级分类,一般使用产品线
62 | "mogujie": {
63 | # 公司内部域名
64 | "\"mogujie.org\"": {
65 | # mode/ext默认可不填
66 | "mode": "normal-match",
67 | "ext": "php,java,python,go,js,properties"
68 | },
69 | # 公司代码特征
70 | "copyright meili inc": {},
71 | # 内部主机域名
72 | "yewu1.db.mogujie.host": {},
73 | # 外部邮箱
74 | "mail.mogujie.com": {}
75 | },
76 | "meilishuo": {
77 | "meilishuo.org": {},
78 | "meilishuo.io": {}
79 | }
80 | }
81 | }
82 | ```
83 |
84 | ## 用法
85 |
86 | ```bash
87 | # 启动测试
88 | $ python gsil.py test
89 |
90 | # 测试token有效性
91 | $ python gsil.py --verify-tokens
92 | ```
93 |
94 | ```bash
95 | $ crontab -e
96 |
97 | # 漏洞报告,此项任务发现漏洞后会立刻发送漏洞报告
98 | # 每个小时运行一次,GitHub API接口调用频率限制可以根据token数量、规则数量来调整crontab频率实现,若觉得麻烦可简单配置多个token来实现。
99 | # crontab执行时间决定了报告的发送时效性,间隔越短报告越快但频率限制越容易触发
100 | # 建议配置5个token+20条规则,每15分钟运行一次(可以配置更短,根据各自需求确定)
101 | */15 * * * * /usr/bin/python /var/app/GSIL/gsil.py test > /tmp/gsil
102 |
103 | # 统计报告,发送一天的扫描进展,包括运行次数、成功次数、失败次数、发现漏洞数、各域名状况、异常等等
104 | # 每天晚上11点发送统计报告
105 | 0 23 * * * /usr/bin/python /var/app/GSIL/gsil.py --report
106 | ```
107 |
108 | *扫描报告过一次的将不会重复报告,缓存记录在~/.gsil/目录*
109 |
110 | ## 引用
111 |
112 | - [GSIL详细介绍](https://feei.cn/gsil/)
113 |
--------------------------------------------------------------------------------
/gsil/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | GSIL
5 | ~~~~
6 |
7 | Implements Github Sensitive Information Leak
8 |
9 | :author: Feei
10 | :homepage: https://github.com/FeeiCN/gsil
11 | :license: GPL, see LICENSE for more details.
12 | :copyright: Copyright (c) 2018 Feei. All rights reserved
13 | """
14 | import sys
15 | import time
16 | import random
17 | import traceback
18 | import multiprocessing
19 | from .engine import Engine
20 | from .log import logger
21 | from .config import Config, get_rules, tokens, daily_run_data
22 | from .process import send_running_data_report
23 |
24 | running_data = []
25 |
26 |
27 | # search single rule
28 | def search(idx, rule):
29 | """
30 | class instance can't pickle in apply_async
31 | :param idx:
32 | :param rule:
33 | :return:
34 | """
35 | token = random.choice(tokens)
36 | try:
37 | return Engine(token=token).search(rule)
38 | except Exception as e:
39 | traceback.print_exc()
40 | return False, None, traceback.format_exc()
41 |
42 |
43 | # store search result
44 | def store_result(result):
45 | """
46 | store running result
47 | :param result:
48 | :return:
49 | """
50 | r_ret, r_rule, r_msg = result
51 | if r_ret:
52 | r_datetime = time.strftime("%Y-%m-%d %H:%M:%S")
53 | # 不需要的类型过滤掉
54 | if r_rule.corp.lower() in ['vulbox']:
55 | return
56 | with open(Config().run_data, 'a') as f:
57 | rule = f'[{r_rule.types}][{r_rule.corp}][{r_rule.keyword}]'
58 | f.write(f'{r_datetime} {r_ret} {rule} {r_msg}\r\n')
59 | # store list
60 | running_data.append([r_datetime, r_ret, rule, r_msg])
61 |
62 |
63 | # start
64 | def start(rule_types):
65 | rules = get_rules(rule_types)
66 | if len(rules) == 0:
67 | logger.critical('get rules failed, rule types not found!')
68 | exit(0)
69 | logger.info(f'rules length: {len(rules)}')
70 | pool = multiprocessing.Pool()
71 | for idx, rule_object in enumerate(rules):
72 | logger.info(f'>>>>>>>>>>>>> {rule_object.corp} > {rule_object.keyword} >>>>>>')
73 | pool.apply_async(search, args=(idx, rule_object), callback=store_result)
74 | pool.close()
75 | pool.join()
76 |
77 |
78 | # generate report file
79 | def generate_report(data):
80 | for rd in data:
81 | datetime, ret, rule, msg = rd
82 | html = f' {datetime} {ret} {rule} {msg}'
83 | run_data = daily_run_data()
84 | run_data['list'].append(html)
85 | if ret:
86 | run_data['found_count'] += msg
87 | run_data['job_success'] += 1
88 | else:
89 | run_data['job_failed'] += 1
90 | daily_run_data(run_data)
91 |
92 |
93 | def gsil():
94 | if sys.argv[1] == '--report':
95 | # send daily running data report
96 | send_running_data_report()
97 | elif sys.argv[1] == '--verify-tokens':
98 | # verify tokens
99 | for i, token in enumerate(tokens):
100 | ret, msg = Engine(token=token).verify()
101 | logger.info(f'{i} {ret} token: {token} {msg}')
102 | else:
103 | logger.info('start monitor github information leakage: {types}'.format(types=sys.argv[1]))
104 | # start
105 | start(sys.argv[1])
106 | # start generate report file
107 | generate_report(running_data)
108 |
109 |
110 | if __name__ == '__main__':
111 | gsil()
112 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # GSIL(GitHub Sensitive Information Leakage)
2 |
3 | [中文文档](https://github.com/FeeiCN/GSIL/blob/master/README-zh.md)
4 |
5 | > Monitor Github sensitive information leaks in near real time and send alert notifications.
6 |
7 | ## Installation
8 |
9 | > Python3(Python2 is not tested)
10 |
11 | ```bash
12 | $ git clone https://github.com/FeeiCN/GSIL.git
13 | $ cd GSIL/
14 | $ pip install -r requirements.txt
15 | ```
16 |
17 | ## Configuration
18 |
19 | ### GSIL/config.gsil(Copy config.gsil.cfg.example to config.gsil.cfg): Alarm mailbox and Github configuration
20 |
21 | ```conf
22 | [mail]
23 | host : smtp.exmail.qq.com
24 | # SMTP port (Not SSL port, but will use TLS encryption)
25 | port : 25
26 | # Multiple senders are separated by comma (,)
27 | mails : gsil@domain.com
28 | from : GSIL
29 | password : your_password
30 | # Multiple recipients are separated by comma (,)
31 | to : feei@feei.cn
32 |
33 | [github]
34 | # Whether the scanned data will be cloned to the local area immediately
35 | # Clone to ~/.gsil/codes/ directory
36 | clone: false
37 |
38 | # Github Token, multiple tokens are separated by comma (,)
39 | # https://github.com/settings/tokens
40 | tokens : your_token
41 | ```
42 |
43 | ### GSIL/rules.gsil(Copy rules.gsil.yaml.example to rules.gsil.yaml): scanning rules
44 |
45 | > Generally, The best rule is the characteristic code of the intranet(Example: mogujie's extranet is `mogujie.com`, intranet is `mogujie.org`. At this time, `mogujie.org` can be used as a rule)
46 |
47 | > There are other similar code head characteristic code, external mailbox characteristic code, and so on
48 |
49 | | field | meaning | optional | default | describe |
50 | | --- | --- | --- | --- | --- |
51 | | keyword | key word | required | - | When multiple keywords are used, space segmentation is used(Example: `'username password'`), When you need a precise search, use double(Example: `"quotesele.me"`) |
52 | | ext | file suffix | optional | all suffixes | Multiple suffixes are separated by comma(Example: `java,php,python`) |
53 | | mode | matching mode | optional | normal-match | `normal-match`(The line that contains the keyword is matched, and the line near the line is matched) / `only-match`(Only the lines that match the key words) / `full-match`(Not recommended for use)(The search results show the entire file)|
54 |
55 | ```
56 | {
57 | # usually using the company name, used as the first parameter to open the scan(Example:`python gsil.py test`)
58 | "test": {
59 | # General use of product name
60 | "mogujie": {
61 | # Internal domain name of the company
62 | "\"mogujie.org\"": {
63 | # mode/ext options no need to configure by default
64 | "mode": "normal-match",
65 | "ext": "php,java,python,go,js,properties"
66 | },
67 | # Company code's characteristic code
68 | "copyright meili inc": {},
69 | # Internal host domain name
70 | "yewu1.db.mogujie.host": {},
71 | # External mailbox
72 | "mail.mogujie.com": {}
73 | },
74 | "meilishuo": {
75 | "meilishuo.org": {},
76 | "meilishuo.io": {}
77 | }
78 | }
79 | }
80 | ```
81 |
82 | ## Usage
83 |
84 | ```bash
85 | $ python gsil.py test
86 |
87 | # Verify tokens validity
88 | $ python gsil.py --verify-tokens
89 | ```
90 |
91 | ```bash
92 | $ crontab -e
93 |
94 | # Run every hour
95 | 0 * * * * /usr/bin/python /var/app/GSIL/gsil.py test > /tmp/gsil
96 | # Send a statistical report at 11 p. m. every night
97 | 0 23 * * * /usr/bin/python /var/app/GSIL/gsil.py --report
98 | ```
99 | * Once the scan report will not repeat the report, the cache records in ~/.gsil/ directory *
100 |
101 | ## Reference
102 | - [GSIL详细介绍](https://feei.cn/gsil/)
103 |
--------------------------------------------------------------------------------
/gsil/process.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | process
5 | ~~~~~~~
6 |
7 | Implements process content
8 |
9 | :author: Feei
10 | :homepage: https://github.com/FeeiCN/gsil
11 | :license: GPL, see LICENSE for more details.
12 | :copyright: Copyright (c) 2018 Feei. All rights reserved
13 | """
14 | import os
15 | import time
16 | import shutil
17 | import subprocess
18 | from jinja2 import utils
19 | from .notification import Notification
20 | from .config import Config, get, daily_run_data, code_path
21 | from .log import logger
22 |
23 |
24 | class Process(object):
25 | def __init__(self, content, rule_object):
26 | """
27 | Process content
28 | :param content:
29 | :param rule_object:
30 | """
31 | self.content = content
32 | self.rule_object = rule_object
33 |
34 | def process(self, maybe_mistake=False):
35 | logger.info(f'Process count: {len(self.content)}')
36 | ret_mail = self._send_mail(maybe_mistake)
37 | if ret_mail:
38 | for i, v in self.content.items():
39 | Config().add_hash(v['hash'])
40 | logger.debug('{hash} add success!'.format(hash=v['hash']))
41 | logger.debug('send mail success!')
42 | return ret_mail
43 |
44 | def _send_mail(self, maybe_mistake=False):
45 | """
46 | Send mail
47 | :return: boolean
48 | """
49 | if len(self.content) == 0:
50 | logger.info('none content for send mail')
51 | return True
52 | if maybe_mistake:
53 | title = '〔GSIL〕MB_MT '
54 | else:
55 | title = '〔GSIL〕'
56 | subject = f'{title}[{self.rule_object.types}] [{self.rule_object.corp}] {len(self.content)}'
57 | to = get('mail', 'to')
58 | cc = get('mail', 'cc')
59 | html = 'Rule: {rule_regex} Count: {count} Datetime: {datetime}
'.format(
60 | rule_regex=self.rule_object.keyword, datetime=time.strftime("%Y-%m-%d %H:%M:%S"), count=len(self.content))
61 | for i, v in self.content.items():
62 | html += '({i}){hash} {repository}/{path}
'.format(i=i, url=v['url'],
63 | hash=v['hash'][:6],
64 | repository=v['repository'],
65 | path=v['path'])
66 | if len(v['match_codes']) > 0:
67 | code = ''
68 | for c in v['match_codes']:
69 | code += '{c}
'.format(c=utils.escape(c))
70 | html += '{code}
'.format(code=code)
71 | self._save_file(v['hash'], v['code'])
72 | html += '