Add new vulnerabilities

This commit is contained in:
gbucchino 2023-09-11 16:49:30 +02:00
parent a2ff9f1fb9
commit 7bfb138511
12 changed files with 288 additions and 152 deletions

@ -0,0 +1,11 @@
#!/usr/bin/env python3
def grub() -> list:
grub = list()
grub.append({
'description': 'Boot permission',
'filename': '/boot/grub/grub.cfg'
'chmod': 600,
})
return grub

@ -0,0 +1,13 @@
#!/usr/bin/env python3
def kernel_va_space() -> list:
va = list()
sysctl.append({
"from": "cis",
"id": "",
"description": "",
"flag": "kernel.randomize_va_space",
"value": 2,
"level": "medium",
})
return va

@ -0,0 +1,17 @@
#!/usr/bin/env python3
def profile() -> dict:
profile = dict()
profile['filename'] = '/etc/profile'
profile['data'] = list()
profile['data'].append({
'description': 'Set timeout for session',
'flag': 'TMOUT',
'value': 600,
})
return profile
def password_quality() -> list:
passwd = list()
return passwd

@ -1 +0,0 @@
#!/usr/bin/env python3

@ -1,132 +0,0 @@
#!/usr/bin/env python3
import re
from json import dumps
from parsing.base import ParsingBase
class Parsing(ParsingBase):
def __init__(self, objects, audit):
self._parsing = dict()
self._reports = dict()
self._objects = objects
self._audit = audit
def runParsing(self):
# Generate report
self._constructReports()
# 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:
#print(entry)
#print(obj)
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 getResults(self) -> dict:
return self._reports

@ -12,6 +12,7 @@ AUDIT_SYSTEM = [
"sysctl", "sysctl",
"postfix", "postfix",
"apache", "apache",
"localaccount",
] ]
AUDIT_APPLICATION = [ AUDIT_APPLICATION = [
@ -29,6 +30,7 @@ def generateConfig() -> dict:
config["system"]["apache"]["apache_directory"] = "/etc/apache2/" config["system"]["apache"]["apache_directory"] = "/etc/apache2/"
config["system"]["sysctl"] = dict() config["system"]["sysctl"] = dict()
config["system"]["sysctl"]["sysctl_file"] = "/etc/sysctl.conf" config["system"]["sysctl"]["sysctl_file"] = "/etc/sysctl.conf"
config['system']['localaccount'] = dict()
config["system"]["exclude_plugins"] = list() config["system"]["exclude_plugins"] = list()
# Application # Application
config["application"] = dict() config["application"] = dict()

@ -4,6 +4,7 @@ from argparse import ArgumentParser
from core.plugins.sysctl import Sysctl from core.plugins.sysctl import Sysctl
from core.plugins.postfix import Postfix from core.plugins.postfix import Postfix
from core.plugins.apache import Apache from core.plugins.apache import Apache
from core.plugins.localaccount import LocalAccount
from core.report import generateHtmlReport from core.report import generateHtmlReport
from core.config import AUDIT_SYSTEM, AUDIT_APPLICATION, generateConfig, parsingConfigFile from core.config import AUDIT_SYSTEM, AUDIT_APPLICATION, generateConfig, parsingConfigFile
from core.dispatcher import Dispatcher from core.dispatcher import Dispatcher
@ -95,5 +96,11 @@ def apache(*args) -> dict:
apache.runAudit() apache.runAudit()
return apache.getReports() return apache.getReports()
@Dispatcher.register_plugins
def localaccount(*args) -> dict:
account = LocalAccount(args[1])
account.runAudit()
return account.getReports()
if __name__ == "__main__": if __name__ == "__main__":
main() main()

@ -28,12 +28,12 @@ class Apache:
def _runParsing(self): def _runParsing(self):
# Check if the file exist # Check if the file exist
path = f"{self._apache_directory}/sites-available" path = f"{self._apache_directory}/sites-available"
if isdir(self._apache_directory): #if isdir(self._apache_directory):
for site in listdir(path): # for site in listdir(path):
with open(f"{path}/{site}", 'rb') as f: # with open(f"{path}/{site}", 'rb') as f:
self._parseFile(f) # self._parseFile(f)
else: #else:
self._reports["apache"]["test"] = "No directory found" # self._reports["apache"]["test"] = "No directory found"
def _parseFile(self, fdata): def _parseFile(self, fdata):
data = fdata.read() data = fdata.read()

@ -0,0 +1,69 @@
#!/usr/bin/env python3
import re
from os import listdir
from os.path import isdir
from audit.system.plugins.localaccount import profile, password_quality
class LocalAccount:
def __init__(self, arguments):
self._profile = profile()
self._passwd_quality = password_quality()
self._reports = dict()
# Create the report
self._constructReports()
# Report
#self._reports[""] = self._apache_directory
def runAudit(self):
print("Running test for Local account")
self._analyzingProfile()
self._analyzingPasswordQuality()
print(self._reports)
def getReports(self) -> dict:
return self._reports
def _analyzingProfile(self):
# Check if the file exist
path = self._profile['filename']
try:
with open(path, 'rb') as fdata:
self._parseFile(fdata)
except FileNotFoundError:
self._reports['localaccount']['profile']['error'] = \
f'File {path} not found'
def _parseFile(self, fdata):
data = fdata.read()
lines = data.splitlines()
for line in lines:
line = line.decode('utf-8')
for obj in self._profile['data']:
grFlag = re.search(f"^{obj['flag']}", line)
if grFlag:
print(line)
def _analyzingPasswordQuality(self):
pass
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['localaccount'] = dict()
self._reports['localaccount']['profile'] = dict()
self._reports['localaccount']['pwd_quality'] = dict()

@ -1,15 +1,15 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from audit.system.plugins.sysctl.parsing import Parsing import re
from audit.system.plugins.sysctl.sysctl import sysctl from audit.system.plugins.sysctl import sysctl
class Sysctl: class Sysctl:
def __init__(self, args): def __init__(self, args):
self._objects = dict() self._objects = sysctl()
self._reports = dict() self._reports = dict()
self._audit = list() self._audit = list()
self._audit.append({ self._audit.append({
'audit': 'file', 'audit': 'file',
'value': args["sysctl_file"], 'value': args["sysctl_file"],
@ -19,19 +19,126 @@ class Sysctl:
'value': 'sysctl -a', 'value': 'sysctl -a',
}) })
self._sysctl() self._constructReports()
self._parsing = Parsing(self._objects, self._audit)
def _sysctl(self):
self._objects = sysctl()
def runAudit(self): def runAudit(self):
print("Running test for sysctl") print("Running test for sysctl")
self._parsing.runParsing() self.runParsing()
self._reports = self._parsing.getResults() #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: def getReports(self) -> dict:
return self._reports return self._reports

@ -0,0 +1,43 @@
<h3 class="fs-3">Apache</h3>
{% for item in data['postfix']['vulnerabilities'] %}
<div class="accordion" id="accordionSysctl">
<div class="accordion-item">
<h2 class="accordion-header">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#{{ data['postfix']['vulnerabilities'][item]['accordion-id'] }}" aria-expanded="true" aria-controls="{{ data['postfix']['vulnerabilities'][item]['accordion-id'] }}">
<strong>{{ item }}</strong>
{% if data['postfix']['vulnerabilities'][item]['result'] == 'failed' %}
<span class="text-bg-danger p-1" style="padding-left:10pt;padding-right:10pt;margin-left:15pt;">{{ data['postfix']['vulnerabilities'][item]['result'] }}</span>
{% elif data['postfix']['vulnerabilities'][item]['result'] == 'success' %}
<span class="text-bg-success p-1" style="padding-left:10pt;padding-right:10pt;margin-left:15pt;">{{ data['postfix']['vulnerabilities'][item]['result'] }}</span>
{% endif %}
</button>
</h2>
<div id="{{ data['postfix']['vulnerabilities'][item]['accordion-id'] }}" class="accordion-collapse collapse" data-bs-parent="#accordionPostfix">
<div class="accordion-body">
{{ data['postfix']['vulnerabilities'][item]['description'] }}. <br />
{% if data['postfix']['vulnerabilities'][item]['result'] == 'success' %}
<div class="bd-example-snippet bd-code-snippet">
<div class="highlight">
<pre tabindex="0" class="chroma"><code class="language-shell">
{{ data['postfix']['vulnerabilities'][item]['flagFound'] }}
</pre></code>
</div>
</div>
{% else %}
For resolving the issue, add this line in the <strong>{{ data['postfix']['filename'] }}</strong> vulnerabilities:
<div class="bd-example-snippet bd-code-snippet">
<div class="highlight">
<pre tabindex="0" class="chroma"><code class="language-shell">
{% for value in data['postfix']['vulnerabilities'][item]['recommand_value'] %}
{{ data['postfix']['vulnerabilities'][item]['flag'] }} = {{ value }}
{% endfor %}
</pre></code>
</div>
</div>
{% endif %}
</div>
</div>
</div>
</div>
{% endfor %}