From 582b85bb075d9460d40f1fbd4520f94e74dcd3dc Mon Sep 17 00:00:00 2001 From: geoffrey Date: Sun, 10 Sep 2023 18:08:48 +0200 Subject: [PATCH] Parsing postfix --- .../plugins/apache/{apaches.py => apache.py} | 2 +- audit/system/plugins/postfix/postfix.py | 12 ++- config.yaml | 2 + core/config.py | 22 +---- core/dispatcher.py | 4 +- core/main.py | 28 +++--- core/plugins/apache.py | 67 ++++++++++++++ core/plugins/postfix.py | 89 +++++++++++++++++++ core/{ => plugins}/sysctl.py | 0 core/postfix.py | 29 ------ core/report.py | 22 +++-- reports/templates/apache.html.j2 | 43 +++++++++ reports/templates/index.html.j2 | 1 + reports/templates/postfix.html.j2 | 37 ++++++-- 14 files changed, 281 insertions(+), 77 deletions(-) rename audit/system/plugins/apache/{apaches.py => apache.py} (81%) create mode 100644 core/plugins/apache.py create mode 100644 core/plugins/postfix.py rename core/{ => plugins}/sysctl.py (100%) delete mode 100644 core/postfix.py create mode 100644 reports/templates/apache.html.j2 diff --git a/audit/system/plugins/apache/apaches.py b/audit/system/plugins/apache/apache.py similarity index 81% rename from audit/system/plugins/apache/apaches.py rename to audit/system/plugins/apache/apache.py index d279df4..5f5a95b 100644 --- a/audit/system/plugins/apache/apaches.py +++ b/audit/system/plugins/apache/apache.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -def apaches_ssl() -> list: +def apache() -> list: ssl = list() # Check if apaches has disabled the bad SSL/TLS version diff --git a/audit/system/plugins/postfix/postfix.py b/audit/system/plugins/postfix/postfix.py index 56d1657..8b387f3 100644 --- a/audit/system/plugins/postfix/postfix.py +++ b/audit/system/plugins/postfix/postfix.py @@ -3,7 +3,15 @@ def postfix() -> list: postfix = list() postfix.append({ - 'directive': "inet_interfaces", - 'value': "loopback-only", + 'from': 'cis', + 'id': '', + 'description': 'Disable the listening from all interfaces', + 'flag': "inet_interfaces", + 'level': 'medium', + 'value': [ + "127.0.0.1", + "loopback-only", + "[::1]", + ] }) return postfix diff --git a/config.yaml b/config.yaml index a6c5854..8e349e2 100644 --- a/config.yaml +++ b/config.yaml @@ -6,6 +6,8 @@ system: postfix_file: "/etc/postfix/master.cf" sysctl: sysctl_file: "/etc/sysctl.conf" + apache: + apache_directory: "/etc/apache2/" # Audit application application: diff --git a/core/config.py b/core/config.py index a56327c..9210423 100644 --- a/core/config.py +++ b/core/config.py @@ -11,6 +11,7 @@ LOW = "low" AUDIT_SYSTEM = [ "sysctl", "postfix", + "apache", ] AUDIT_APPLICATION = [ @@ -24,6 +25,8 @@ def generateConfig() -> dict: config["system"] = dict() config["system"]["postfix"] = dict() config["system"]["postfix"]["postfix_file"] = "/etc/postfix/main.cf" + config["system"]["apache"] = dict() + config["system"]["apache"]["apache_directory"] = "/etc/apache2/" config["system"]["sysctl"] = dict() config["system"]["sysctl"]["sysctl_file"] = "/etc/sysctl.conf" config["system"]["exclude_plugins"] = list() @@ -80,24 +83,5 @@ def parsingConfigFile(filename, configs): # except TypeError: # pass - - #fdata = f.read() - #lines = fdata.splitlines() - - #for line in lines: - # line = line.decode('utf-8') - # try: - # sLine = line.split("=") - # flag = sLine[0].strip() - # value = sLine[1].strip() - - # if flag in configs: - # if flag == "exclude_plugins": - # value = value.replace("\"", "") - # value = value.split(",") - # configs[flag] = value - # except IndexError: - # pass - except FileNotFoundError: print(f"Config file {filename} not found. Bypass it") diff --git a/core/dispatcher.py b/core/dispatcher.py index 75b2c6a..4fc6186 100644 --- a/core/dispatcher.py +++ b/core/dispatcher.py @@ -8,7 +8,7 @@ class Dispatcher: def runPlugin(self, plugin, *args) -> dict: """ - We run the puglin. The result of this function + We run the plugin. The result of this function is the report of the audit """ return self._plugins[plugin](self, *args) @@ -18,3 +18,5 @@ class Dispatcher: cls._plugins[plugin.__name__] = plugin return plugin + def get_plugins(self): + return self._plugins diff --git a/core/main.py b/core/main.py index 8ff0c8e..387de73 100644 --- a/core/main.py +++ b/core/main.py @@ -1,14 +1,13 @@ #!/usr/bin/env python from argparse import ArgumentParser -from core.sysctl import Sysctl -from core.postfix import Postfix +from core.plugins.sysctl import Sysctl +from core.plugins.postfix import Postfix +from core.plugins.apache import Apache from core.report import generateHtmlReport from core.config import AUDIT_SYSTEM, AUDIT_APPLICATION, generateConfig, parsingConfigFile from core.dispatcher import Dispatcher from utils import getHostname, getKernelVersion, identifySystem, getCodeName, getRelease -from os import listdir -from os.path import isdir def checkArguments(): @@ -20,15 +19,14 @@ def checkArguments(): def getAllPlugins(audit): print(f"List all plugins for {audit}") - path = str() - if audit == "system": - path = "audit/system/plugins/" - else: - path = "audit/applications/" - for directory in listdir(path): - if isdir(f"{path}/{directory}"): - print(directory) + if audit == "system": + dis = Dispatcher() + plugins = dis.get_plugins() + for plugin in plugins: + print(plugin) + elif audit == "application": + pass def main(): args = checkArguments() @@ -91,5 +89,11 @@ def postfix(*args) -> dict: postfix.runAudit() return postfix.getReports() +@Dispatcher.register_plugins +def apache(*args) -> dict: + apache = Apache(args[1]) + apache.runAudit() + return apache.getReports() + if __name__ == "__main__": main() diff --git a/core/plugins/apache.py b/core/plugins/apache.py new file mode 100644 index 0000000..82f16f9 --- /dev/null +++ b/core/plugins/apache.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python3 + +import re +from os import listdir +from os.path import isdir +from audit.system.plugins.apache.apache import apache + + +class Apache: + def __init__(self, arguments): + self._objects = apache() + self._reports = dict() + self._apache_directory = arguments["apache_directory"] + + # Create the report + self._constructReports() + + # Report + self._reports["directory"] = self._apache_directory + + def runAudit(self): + print("Running test for Apache") + self._runParsing() + + def getReports(self) -> dict: + return self._reports + + def _runParsing(self): + # Check if the file exist + path = f"{self._apache_directory}/sites-available" + if isdir(self._apache_directory): + for site in listdir(path): + with open(f"{path}/{site}", 'rb') as f: + self._parseFile(f) + else: + self._reports["apache"]["test"] = "No directory found" + + def _parseFile(self, fdata): + data = fdata.read() + lines = data.splitlines() + + for line in lines: + line = line.decode('utf-8') + + # check if SSL is enable for the VirtualHost + grSSLEngine = re.search("SSLEngine on", line) + if grSSLEngine: + print(line) + + def _check_value_exist(self, line, value) -> bool: + grValue = re.search(value, line) + if grValue: + return True + return False + + def _constructReports(self): + """ + Construct dictionary for result of the tests + Each entry contains: + Key: + - filename: filename of the test + - line: line of the test + - parse: Display the line where the vulnerabilites has been found + - description: description of the vulnerability + - level: high, medium or low + """ + self._reports['apache'] = dict() diff --git a/core/plugins/postfix.py b/core/plugins/postfix.py new file mode 100644 index 0000000..236a81f --- /dev/null +++ b/core/plugins/postfix.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python3 + +import re +from audit.system.plugins.postfix.postfix import postfix + + +class Postfix: + def __init__(self, arguments): + self._objects = postfix() + self._reports = dict() + self._postfix_file = arguments["postfix_file"] + + # Create the report + self._constructReports() + + # Report + self._reports["filename"] = self._postfix_file + + def runAudit(self): + print("Running test for postfix") + self._runParsing() + + def getReports(self) -> dict: + return self._reports + + def _runParsing(self): + # Check if the file exist + try: + with open(self._postfix_file, 'rb') as fdata: + self._parseFile(fdata) + except FileNotFoundError: + print("No postfix file found. Add into the report") + pass + + def _parseFile(self, fdata): + data = fdata.read() + lines = data.splitlines() + + for line in lines: + line = line.decode('utf-8') + for obj in self._objects: + grDirective = re.search( + f"^({obj['flag']})", + line + ) + if grDirective: + res = False + if not isinstance(obj['value'], list): + obj['value'] = [obj['value']] + + for value in obj['value']: + res = self._check_value_exist(line, value) + if res: + break + + if res: + self._reports["postfix"][obj['flag']] = dict() + self._reports["postfix"][obj['flag']]["result"] = "success" + self._reports["postfix"][obj['flag']]["description"] = obj['description'] + self._reports["postfix"][obj['flag']]["flagFound"] = line + else: + self._reports["postfix"][obj['flag']] = dict() + self._reports["postfix"][obj['flag']]["result"] = "failed" + self._reports["postfix"][obj["flag"]]["recommand_value"] = obj["value"] + self._reports["postfix"][obj['flag']]["description"] = obj['description'] + self._reports["postfix"][obj['flag']]["flag"] = obj['flag'] + + def _check_value_exist(self, line, value) -> bool: + if '[' in value: + value = value.replace('[', '\[') + if ']' in value: + value = value.replace(']', '\]') + grValue = re.search(value, line) + if grValue: + return True + return False + + def _constructReports(self): + """ + Construct dictionary for result of the tests + Each entry contains: + Key: + - filename: filename of the test + - line: line of the test + - parse: Display the line where the vulnerabilites has been found + - description: description of the vulnerability + - level: high, medium or low + """ + self._reports['postfix'] = dict() diff --git a/core/sysctl.py b/core/plugins/sysctl.py similarity index 100% rename from core/sysctl.py rename to core/plugins/sysctl.py diff --git a/core/postfix.py b/core/postfix.py deleted file mode 100644 index 9844b09..0000000 --- a/core/postfix.py +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env python3 - -from audit.system.plugins.postfix.parsing import Parsing -from audit.system.plugins.postfix.postfix import postfix - -class Postfix: - def __init__(self, arguments): - self._objects = dict() - self._reports = dict() - self._arguments = arguments - - self._postfix() - - self._parsing = Parsing(self._objects, arguments) - - def _postfix(self): - """ - Store all data to analyze in the object variable - """ - self._objects = postfix() - - def runAudit(self): - print("Running test for postfix") - self._parsing.runParsing() - - self._reports = self._parsing.getResults() - - def getReports(self) -> dict: - return self._reports diff --git a/core/report.py b/core/report.py index b4db34e..1d9f173 100644 --- a/core/report.py +++ b/core/report.py @@ -24,8 +24,11 @@ def generateHtmlReport(data): dataJinja2['plugins'].append(f"{plugin}.html.j2") if 'postfix' in data['system']: - #print(data['system']['postfix']) - pass + dataJinja2['postfix'] = dict() + dataJinja2['postfix']['filename'] = data["system"]["postfix"]["filename"] + dataJinja2['postfix']['vulnerabilities'] = data['system']['postfix']['postfix'] + + _generateAccordion(dataJinja2['postfix']['vulnerabilities']) if 'sysctl' in data['system']: dataJinja2['sysctl'] = dict() @@ -33,11 +36,10 @@ def generateHtmlReport(data): dataJinja2['sysctl']['file']['filename'] = data['system']['sysctl']['file']['filename'] dataJinja2['sysctl']['file']['sysctl'] = data['system']['sysctl']['file']['sysctl'] - index = 1 - - for sysctl in dataJinja2['sysctl']['file']['sysctl']: - dataJinja2['sysctl']['file']['sysctl'][sysctl]['accordion-id'] = f"accordion-{index}" - index += 1 + _generateAccordion(dataJinja2['sysctl']['file']['sysctl']) + + if 'apache' in data['system']: + pass dataJinja2['year'] = '2023' dataJinja2['hostname'] = data['hostname'] @@ -50,3 +52,9 @@ def generateHtmlReport(data): print("The report is generated at this location: " \ f"reports/reports_{today}.html") + +def _generateAccordion(obj): + index = 1 + for entry in obj: + obj[entry]['accordion-id'] = f"accordion-{index}" + index += 1 diff --git a/reports/templates/apache.html.j2 b/reports/templates/apache.html.j2 new file mode 100644 index 0000000..a107073 --- /dev/null +++ b/reports/templates/apache.html.j2 @@ -0,0 +1,43 @@ +

Apache

+ +{% for item in data['postfix']['vulnerabilities'] %} +
+
+

+ +

+
+
+ {{ data['postfix']['vulnerabilities'][item]['description'] }}.
+ {% if data['postfix']['vulnerabilities'][item]['result'] == 'success' %} +
+
+

+                {{ data['postfix']['vulnerabilities'][item]['flagFound'] }}
+	            
+
+
+ {% else %} + For resolving the issue, add this line in the {{ data['postfix']['filename'] }} vulnerabilities: +
+
+

+            {% for value in data['postfix']['vulnerabilities'][item]['recommand_value'] %}
+ 	          {{ data['postfix']['vulnerabilities'][item]['flag'] }} = {{ value }}
+            {% endfor %}
+	        
+
+
+ {% endif %} +
+
+
+
+{% endfor %} diff --git a/reports/templates/index.html.j2 b/reports/templates/index.html.j2 index 0eb3da5..6b2dc80 100644 --- a/reports/templates/index.html.j2 +++ b/reports/templates/index.html.j2 @@ -31,6 +31,7 @@ {% for plugin in data['plugins'] %} {% include plugin %} +
{% endfor %} diff --git a/reports/templates/postfix.html.j2 b/reports/templates/postfix.html.j2 index 29601f0..2cc2694 100644 --- a/reports/templates/postfix.html.j2 +++ b/reports/templates/postfix.html.j2 @@ -1,16 +1,41 @@

Postfix

-{% for item in data['postfix'] %} -
+{% for item in data['postfix']['vulnerabilities'] %} +

-

-
+
- + {{ data['postfix']['vulnerabilities'][item]['description'] }}.
+ {% if data['postfix']['vulnerabilities'][item]['result'] == 'success' %} +
+
+

+                {{ data['postfix']['vulnerabilities'][item]['flagFound'] }}
+	            
+
+
+ {% else %} + For resolving the issue, add this line in the {{ data['postfix']['filename'] }} vulnerabilities: +
+
+

+            {% for value in data['postfix']['vulnerabilities'][item]['recommand_value'] %}
+ 	          {{ data['postfix']['vulnerabilities'][item]['flag'] }} = {{ value }}
+            {% endfor %}
+	        
+
+
+ {% endif %}