#!/usr/bin/env python3 import re from audit.system.plugins.sysctl import sysctl class Sysctl: def __init__(self, args): self._objects = sysctl() self._reports = dict() self._audit = list() self._audit.append({ 'audit': 'file', 'value': args["sysctl_file"], }) self._audit.append({ 'audit': 'process', 'value': 'sysctl -a', }) self._constructReports() def runAudit(self): print("Running test for sysctl") self.runParsing() #self._reports = self.getResults() def runParsing(self): # Generate report # TODO: # We are not parse file and process. We parse file and process and for each # line, we try to find in the file and in the process for audit in self._audit: if audit['audit'] == 'file': with open(audit['value'], 'rb') as fdata: self._parseFile(fdata) if audit['audit'] == 'process': self._parseProcess() def _parseFile(self, fdata): data = fdata.read() lines = data.splitlines() numLines = 1 vulnerabilityFound = dict() # I create an array which contains all flag we need to find # After that, for each data, I put the number of occurence I found. # If the array is empty, no entry found for a flag, otherwise, we check the value for obj in self._objects: vulnerabilityFound[obj['flag']] = dict() vulnerabilityFound[obj['flag']]['recommand_value'] = obj['value'] vulnerabilityFound[obj['flag']]['occurence'] = 0 for item in obj: vulnerabilityFound[obj['flag']][item] = obj[item] for line in lines: line = line.decode("utf-8") for obj in self._objects: result = self._parsingFile(line, obj, vulnerabilityFound) if result: vulnerabilityFound[obj['flag']]['lineNumber'] = numLines vulnerabilityFound[obj['flag']]['occurence'] += 1 numLines += 1 # Now, we can check if the value is specified or not # And check if the flag is specified and need to put on the sysctl config for entry in vulnerabilityFound: obj = vulnerabilityFound[entry] vulnerabilityFound[entry]['result'] = dict() if obj['occurence'] > 0: if obj['current_value'] != obj['recommand_value']: vulnerabilityFound[entry]['result']['result'] = "failed" else: vulnerabilityFound[entry]['result']['result'] = "success" else: # No find the flag, we recommand to enable it vulnerabilityFound[entry]['result']['result'] = "failed" # Generate report self._generateReport(vulnerabilityFound) def _parseProcess(self): vulnerabilityFound = dict() # Generate report #self._generateReport(vulnerabilityFound) def _generateReport(self, objects): # We can generate the report for sysctl in self._reports['file']['sysctl']: self._reports['file']['sysctl'][sysctl] = objects[sysctl] def _parsingFile(self, line, obj, vulnerabilityFound) -> bool: """ This function parse the line and try to find the item in it """ result = bool() groupLine = re.search(obj['flag'], line) if groupLine: # Avoid the comment if not line.startswith('#'): sLine = line.split('=') flag = sLine[0].strip() value = int(sLine[1].strip()) vulnerabilityFound[flag]['current_value'] = value result = True return result 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 """ # For file self._reports['file'] = dict() self._reports['file']['filename'] = self._audit[0]['value'] self._reports['file']['sysctl'] = dict() # For process self._reports['process'] = dict() self._reports['process']['sysctl'] = dict() for sysctl in self._objects: self._reports['file']['sysctl'][sysctl['flag']] = dict() self._reports['process']['sysctl'][sysctl['flag']] = dict() def getReports(self) -> dict: return self._reports