diff --git a/README.md b/README.md index b42c59e..77201e0 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,8 @@ CertStreamMonitor architecture relies on 3 scripts : - it collects informations about the sites that are up to DB and to a JSON file. - `gethost.py` - Due to [@nbeguier](https://github.com/nbeguier) contribution, the project has also a `gethost.py` script that provides a way for security operators to request the last hostnames which have been detected by `certstreammointor.py` since X seconds. +- `check_rules.py` + - Due to [@nbeguier](https://github.com/nbeguier) contribution, the project has also a `check_rules.py` script that provides a way for security operators to check their own rules, especially SearchKeywords, DetectionThreshold and BlacklistKeywords. ## Features - **Monitoring:** @@ -129,6 +131,38 @@ socialmediaforsocialaction.com 2019-06-12T15:54:31 social.socialbride.co.za None ~~~ +### check_rules.py + +~~~ +$ python3 check_rules.py --help + + -h --help Print this help + -c --config Configuration file to use + -d --domain Domain name to check +~~~ + +~~~ +# No match - Keywords not found. +$ ./check_rules.py -c conf/example.conf -d www.google.com +Looking for these strings: paypal|apple|account|secure|login, detection threshold: 2 +No match - Keywords not found. + +# No match - Detection threashold not reached. +$ ./check_rules.py -c conf/example.conf -d paypal.com +Looking for these strings: paypal|apple|account|secure|login, detection threshold: 2 +No match - Detection threashold not reached. + +# No match - Blacklisted keywords. +$ ./check_rules.py -c conf/example.conf -d login-paypal.gouv +Looking for these strings: paypal|apple|account|secure|login, detection threshold: 2 +No match - Blacklisted keywords. + +# This is a match, detection threashold reached. +$ ./check_rules.py -c conf/example.conf -d login-paypal.com +Looking for these strings: paypal|apple|account|secure|login, detection threshold: 2 +This is a match, detection threashold reached. +~~~ + ## Authors - Thomas Damonneville ([thomas.damonneville@assurance-maladie.fr](mailto:thomas.damonneville@assurance-maladie.fr)) - Christophe Brocas ([christophe.brocas@assurance-maladie.fr](mailto:christophe.brocas@assurance-maladie.fr)) diff --git a/check_rules.py b/check_rules.py new file mode 100755 index 0000000..9151735 --- /dev/null +++ b/check_rules.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2018 Caisse nationale d'Assurance Maladie +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +import os +import re +import sys +import getopt +import logging +from utils.confparser import ConfParser +from utils.utils import VerifyPath + +VERSION = "0.0.1" + +def usage(): + """ + CLI usage printing + """ + usage_output = """ + -h --help Print this help + -c --config Configuration file to use + -d --domain Domain name to check + """ + print(usage_output) + sys.exit(0) + + +def ConfAnalysis(configuration_file): + """ + configuration file analysis. Load global variables with parameters found + in configuration file. + + :param configuration_file: the configuration file + """ + global CONF + global SearchKeywords + global BlacklistKeywords + global DetectionThreshold + + try: + CONF = ConfParser(configuration_file) + + SearchKeywords = CONF.SearchKeywords + BlacklistKeywords = CONF.BlacklistKeywords + DetectionThreshold = CONF.DetectionThreshold + except: + err = sys.exc_info() + logging.error(" ConfParser Error: %s", err) + + +def args_parse(): + """ + Tool options + """ + global ConfFile + global DOMAIN + if not len(sys.argv[1:]): + usage() + try: + opts, _ = getopt.getopt(sys.argv[1:], "hc:d:", ["help", "conf="]) + except getopt.GetoptError as err: + logging.error(" Option Error. Exiting... %s", err) + usage() + sys.exit(2) + + DOMAIN = None + for o, a in opts: + if o in ("-h", "--help"): + usage() + elif o in ("-c", "--config"): + if os.path.isfile(a): + ConfFile = a + else: + logging.error(" Can't find configuration file. Exiting...") + sys.exit(1) + elif o in ("-d", "--domain"): + DOMAIN = a + else: + assert False, "Unhandled Option" + if not DOMAIN: + usage() + sys.exit(2) + + +def print_callback(): + """ + Truncate CertStreamMonitor/print_callback function, SQL/Logging support removed + """ + is_blacklisted = False + if BlacklistKeywords != str(): + is_blacklisted = re.findall(BlacklistKeywords, DOMAIN) + results = re.findall(SearchKeywords, DOMAIN) + FindNb = len(set(results)) + + # Matching host whith blacklisted keywords are ignored + if is_blacklisted and FindNb >= DetectionThreshold: + logging.info("No match - Blacklisted keywords.") + return + + # If search keywords occurence in the hostname is greater or equal to DetectionThreshold + if FindNb >= DetectionThreshold: + logging.info("This is a match, detection threashold reached.") + elif FindNb > 0 and FindNb < DetectionThreshold: + logging.info("No match - Detection threashold not reached.") + else: + logging.info("No match - Keywords not found.") + return + + +# Main +def main(): + # Config + ConfAnalysis(ConfFile) + VerifyPath() + + # logging + logger = logging.getLogger() + logger.setLevel(logging.DEBUG) + + # term handler + stream_handler = logging.StreamHandler() + stream_handler.setLevel(logging.INFO) + logger.addHandler(stream_handler) + logging.info( + "Looking for these strings: %s, detection threshold: %s", + SearchKeywords, + DetectionThreshold) + print_callback() + + +# Start +if __name__ == '__main__': + args_parse() + main() diff --git a/conf/example.conf b/conf/example.conf index 91cb971..c67868b 100644 --- a/conf/example.conf +++ b/conf/example.conf @@ -14,7 +14,7 @@ DetectionThreshold = 2 # Keywords to ignore matched hosts (with '|' (or) as separator). # Leave it empty or comment it to disable this feature. -# BlacklistKeywords = mail\.|\.com|bitcoin +BlacklistKeywords = mail\.|\.gouv|bitcoin [DATABASE] # SQLite3 database path (will be created if not exist)