Compare commits

..

No commits in common. "876bb7e8e0edc20cf7c3dbb8a29dd3260f2a15eb" and "9843ca26b92efa032d5bc53fbb4b52b51bca6361" have entirely different histories.

25 changed files with 319 additions and 562 deletions

@ -1,40 +1,10 @@
#!/usr/bin/env python3
def apache_protocols() -> dict:
ssl = dict()
def apache() -> list:
ssl = list()
# Check if apaches has disabled the bad SSL/TLS version
ssl["description"] = "Disable deprecated SSL/TLS versions"
ssl["level"] = "high"
ssl["protocols"] = list()
# https://httpd.apache.org/docs/trunk/ssl/ssl_howto.html
ssl["protocols"].append("TLSv1")
ssl["protocols"].append("TLSv1.1")
ssl["protocols"].append("SSLv3")
ssl["recommand_value"] = "SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1"
return ssl
def apache_signature() -> dict:
signature = dict()
signature["description"] = "Disable Apache signature"
signature["level"] = "high"
signature['signature'] = list()
signature['signature'].append('ServerSignature On')
signature['signature'].append('ServerTokens Prod')
return signature
def apache_indexes() -> dict:
indexes = dict()
indexes['description'] = 'Disable files and directory indexes'
indexes['level'] = 'medium'
indexes['flag'] = 'Options'
indexes['options'] = list()
indexes['options'].append('Indexes')
indexes['options'].append('FollowSymLinks')
indexes['recommand_value'] = 'Options -Indexes -FollowSymLinks'
return indexes

@ -5,6 +5,4 @@ def grub() -> dict:
grub['description'] = 'Change boot permission'
grub['filename'] = '/boot/grub/grub.cfg'
grub['value'] = 0o600
grub['resolve'] = 'chmod 600 /boot/grub/grub.cfg'
grub['level'] = 'medium'
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

@ -6,7 +6,6 @@ def profile() -> dict:
profile['flag'] = 'TMOUT'
profile['value'] = 600
profile['filename'] = '/etc/profile'
profile['level'] = 'low'
return profile
def password_quality() -> list:

@ -214,16 +214,6 @@ def sysctl() -> list:
"value": 0,
"level": "medium",
})
# Random VirtualAddress
sysctl.append({
"from": "cis",
"id": "",
"description": "Enable random VirtualAddress space for avoiding buffer overflow attacks",
"flag": "kernel.randomize_va_space",
"value": 2,
"level": "medium",
})
return sysctl

@ -30,7 +30,7 @@ def getAllPlugins(audit):
elif audit == "application":
pass
def main(path):
def main():
args = checkArguments()
if args.plugins is not None:
@ -56,7 +56,7 @@ def main(path):
# Get system informations
report['kernel'] = getKernelVersion()
report['release'] = f"{identifySystem()} {getRelease()} {getCodeName().strip()}"
report['release'] = f"{identifySystem()} {getRelease()} ({getCodeName()}) "
# Create our dispatcher
dispatcher = Dispatcher()
@ -76,7 +76,7 @@ def main(path):
pass
print("End of the audit. Generating the report")
generateHtmlReport(path, report)
generateHtmlReport(report)
@Dispatcher.register_plugins
def sysctl(*args) -> dict:

@ -2,15 +2,13 @@
import re
from os import listdir
from os.path import isdir, isfile
from audit.system.plugins.apache import apache_protocols, apache_signature, apache_indexes
from os.path import isdir
from audit.system.plugins.apache import apache
class Apache:
def __init__(self, arguments):
self._ssl_versions = apache_protocols()
self._signatures = apache_signature()
self._indexes = apache_indexes()
self._objects = apache()
self._reports = dict()
self._apache_directory = arguments["apache_directory"]
@ -22,46 +20,22 @@ class Apache:
def runAudit(self):
print("Running test for Apache")
# Check if the directory exist
path = f"{self._apache_directory}"
if isdir(path):
self._reports['audit'] = True
self._analyzingSslVersion()
self._analyzingSignature()
self._analyzingIndexes()
else:
self._reports['audit'] = False
self._reports["msg"] = "No directory found"
self._runParsing()
def getReports(self) -> dict:
return self._reports
################################################
# Analyzing SSL
################################################
def _analyzingSslVersion(self):
def _runParsing(self):
# Check if the file exist
path = f"{self._apache_directory}/sites-available"
if isdir(path):
self._reports['ssl']['audit'] = True
count = 0
self._reports["ssl"]["virtualhost"] = dict()
for site in listdir(path):
vh = f"{path}/{site}"
with open(vh, 'rb') as f:
self._parseFileFindingSsl(f, site)
count += 1
#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"
if count == 0:
self._reports['ssl']['audit'] = False
self._reports['ssl']['msg'] = \
f'No virtual host found in the directory {path}'
else:
self._reports['ssl']['audit'] = False
self._reports['ssl']["msg"] = f"No directory {path} found"
def _parseFileFindingSsl(self, fdata, virtualhost):
def _parseFile(self, fdata):
data = fdata.read()
lines = data.splitlines()
@ -69,220 +43,25 @@ class Apache:
line = line.decode('utf-8')
# check if SSL is enable for the VirtualHost
# (?#) -> remove commentary
# (\s) -> remove space and tabulation
grSSLEngine = re.search(
"(?#)(\s)SSLEngine on",
line,
re.IGNORECASE
)
grSSLEngine = re.search("SSLEngine on", line)
if grSSLEngine:
report = self._check_ssl_version(lines)
print(line)
self._reports["ssl"]["virtualhost"][virtualhost] = report
def _check_ssl_version(self, lines) -> dict:
report = dict()
findProtocol = False
protocolsFound = list()
for line in lines:
line = line.decode("utf-8")
grSSLProtocol = re.search(
"(?#)(\s)SSLProtocol",
line,
re.IGNORECASE
)
if grSSLProtocol:
for protocol in self._ssl_versions["protocols"]:
grProtocol = re.search(f"-{protocol}", line)
if grProtocol:
protocolsFound.append(protocol)
if len(self._ssl_versions["protocols"]) == len(protocolsFound):
report["result"] = "success"
else:
report["msg"] = list()
report["result"] = "failed"
for proto in self._ssl_versions["protocols"]:
if proto not in protocolsFound:
report["msg"].append(
f"{proto} need to be disabled"
)
report["description"] = \
self._ssl_versions["description"]
report["level"] = self._ssl_versions["level"]
report["recommand_value"] = \
self._ssl_versions["recommand_value"]
return report
################################################
# Analyzing Signature
################################################
def _analyzingSignature(self):
# Check if the apache2.conf exist
path = f"{self._apache_directory}/apache2.conf"
if isfile(path):
self._reports["signature"]["audit"] = True
with open(path, 'rb') as fdata:
self._reports["signature"]["signature"] = \
self._parsingApacheConfigForSignature(fdata)
else:
self._reports["signature"]["audit"] = False
self._reports["signature"]["msg"] = \
f"The file {path} do not exist"
def _parsingApacheConfigForSignature(self, fdata) -> dict:
report = dict()
data = fdata.read()
lines = data.splitlines()
for signature in self._signatures["signature"]:
report[signature] = dict()
for line in lines:
line = line.decode('utf-8')
for signature in self._signatures["signature"]:
grSignature = re.search(
f"(?#){signature}",
line,
re.IGNORECASE
)
if grSignature:
# It's not a comment
if '#' not in line:
report[signature]["audit"] = True
report[signature]["result"] = "success"
report[signature]["description"] = self._signatures["description"]
report[signature]["level"] = self._signatures["level"]
for signature in report:
if len(report[signature]) == 0:
report[signature]["audit"] = True
report[signature]["result"] = "failed"
report[signature]["recommand_value"] = signature
report[signature]["description"] = self._signatures["description"]
report[signature]["level"] = self._signatures["level"]
return report
################################################
# Analyzing Indexes
################################################
def _analyzingIndexes(self):
# Check if the apache2.conf exist
path = f"{self._apache_directory}/apache2.conf"
if isfile(path):
self._reports["indexes"]["audit"] = True
with open(path, 'rb') as fdata:
self._reports["indexes"] = \
self._parsingApacheConfig(fdata)
else:
self._reports["indexes"]["audit"] = False
self._reports["indexes"]["msg"] = \
f"The file {path} do not exist"
def _parsingApacheConfig(self, fdata) -> dict:
report = dict()
report["directories"] = dict()
data = fdata.read()
lines = data.splitlines()
# Each entry in the variable directories contains a list
# of <Directory> with all data in it
# We create another entry when a found </Directory>
directories = dict()
directoryFound = False
index = 0
optsFound = list()
currentPath = None
for line in lines:
line = line.decode('utf-8')
# Find a <Directory
if not directoryFound:
grDirectory = re.search("<Directory ", line, re.IGNORECASE)
if grDirectory:
directoryFound = True
currentPath = self._getDirectoryPath(line)
directories[currentPath] = list()
directories[currentPath].append(line)
else:
directories[currentPath].append(line)
grDirectory = re.search("</Directory>", line, re.IGNORECASE)
if grDirectory:
directoryFound = False
index += 1
currentPath = None
# We will find if we find an indexes option
for directory in directories:
report["directories"][directory] = dict()
report["directories"][directory]["options"] = list()
for line in directories[directory]:
grFlag = re.search(
f"{self._indexes['flag']}",
line,
re.IGNORECASE
)
if grFlag:
for opt in self._indexes['options']:
grOption = re.search(
f"-{opt}",
line,
re.IGNORECASE
)
if grOption:
optsFound.append(opt)
# We can check if you found the options
if len(optsFound) == len(self._indexes['options']):
report["directories"][directory]["result"] = "success"
else:
report["directories"][directory]["result"] = "failed"
for opt in self._indexes["options"]:
if opt not in optsFound:
report["directories"][directory]["options"].append(
f"{opt} is not removed. You should disable it"
)
optsFound.clear()
report["audit"] = True
report["description"] = self._indexes["description"]
report["level"] = self._indexes["level"]
report["recommand_value"] = self._indexes["recommand_value"]
return report
def _getDirectoryPath(self, line) -> str:
"""
This function return the directory path
"""
path = None
grDirectory = re.search(
f"<Directory",
line,
re.IGNORECASE
)
if grDirectory:
path = line.replace("<Directory", "")
path = path.replace(">", "")
path = path.replace("\"", "")
return path
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['ssl'] = dict()
self._reports['signature'] = dict()
self._reports['indexes'] = dict()
self._reports['apache'] = dict()

@ -29,12 +29,10 @@ class Grub:
if permission != oct(self._object['value']):
self._reports['result'] = 'failed'
self._reports['resolve'] = self._object['resolve']
else:
self._reports['result'] = 'success'
self._reports['description'] = self._object['description']
self._reports['level'] = self._object['level']
self._reports['current_value'] = permission[2:]
self._reports['recommand_value'] = self._object['value']
except FileNotFoundError:
self._reports['grub']['error'] = \
f'File {path} not found'

@ -50,14 +50,12 @@ class LocalAccount:
self._reports['profile']['vulnerabilities'] = dict()
self._reports['profile']['vulnerabilities'][self._profile['flag']] = dict()
self._reports['profile']['vulnerabilities'][self._profile['flag']]["result"] = "success"
self._reports['profile']['vulnerabilities'][self._profile['flag']]['level'] = self._profile['level']
self._reports['profile']['vulnerabilities'][self._profile['flag']]["description"] = self._profile['description']
self._reports['profile']['vulnerabilities'][self._profile['flag']]["flagFound"] = lineFound
else:
self._reports['profile']['vulnerabilities'] = dict()
self._reports['profile']['vulnerabilities'][self._profile['flag']] = dict()
self._reports['profile']['vulnerabilities'][self._profile['flag']]["result"] = "failed"
self._reports['profile']['vulnerabilities'][self._profile['flag']]['level'] = self._profile['level']
self._reports['profile']['vulnerabilities'][self._profile["flag"]]["recommand_value"] = self._profile["value"]
self._reports['profile']['vulnerabilities'][self._profile['flag']]["description"] = self._profile['description']
self._reports['profile']['vulnerabilities'][self._profile['flag']]["flag"] = self._profile['flag']

@ -56,13 +56,11 @@ class Postfix:
if res:
self._reports["postfix"][obj['flag']] = dict()
self._reports["postfix"][obj['flag']]["result"] = "success"
self._reports["postfix"][obj['flag']]["level"] = obj['level']
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']]["level"] = obj['level']
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']

@ -4,8 +4,8 @@ from datetime import datetime
import jinja2
def generateHtmlReport(path, data):
today = datetime.now().isoformat()[0:10]
def generateHtmlReport(data):
today = datetime.now().isoformat()[0:10].replace("-", "_")
dataJinja2 = dict()
dataJinja2['title'] = 'Report check system'
dataJinja2['plugins'] = list()
@ -20,6 +20,7 @@ def generateHtmlReport(path, data):
body = str()
for plugin in data['system']:
#print(plugin)
dataJinja2['plugins'].append(f"{plugin}.html.j2")
if 'postfix' in data['system']:
@ -38,24 +39,7 @@ def generateHtmlReport(path, data):
_generateAccordion(dataJinja2['sysctl']['file']['sysctl'], 'sysctl')
if 'apache' in data['system']:
dataJinja2['apache'] = data['system']['apache']
if data['system']['apache']['audit']:
if data['system']['apache']['ssl']['audit']:
_generateAccordion(
dataJinja2["apache"]["ssl"]["virtualhost"],
"apache-virtualhost"
)
if data['system']['apache']['signature']['audit']:
_generateAccordion(
dataJinja2["apache"]["signature"]["signature"],
"apache-signature"
)
if data['system']['apache']['indexes']['audit']:
_generateAccordion(
dataJinja2["apache"]["indexes"]["directories"],
"apache-indexes"
)
pass
if 'localaccount' in data['system']:
if 'profile' in data['system']['localaccount']:
@ -69,6 +53,8 @@ def generateHtmlReport(path, data):
if 'grub' in data['system']:
dataJinja2['grub'] = data['system']['grub']
dataJinja2['grub']['accordion-id'] = f"accordion-grub-1"
#_generateAccordion(dataJinja2['grub'], 'grub')
print(dataJinja2['grub'])
dataJinja2['year'] = '2023'
dataJinja2['hostname'] = data['hostname']
@ -76,12 +62,11 @@ def generateHtmlReport(path, data):
dataJinja2['release'] = data['release']
rdr = tmplIndex.render(data=dataJinja2)
hostname = data['hostname'].lower()
with open(f"{path}/reports/reports_{hostname}_{today}.html", "w") as f:
with open(f"reports/reports_{today}.html", "w") as f:
f.write(rdr)
print("The report is generated at this location: " \
f"reports/reports_{hostname}_{today}.html")
f"reports/reports_{today}.html")
def _generateAccordion(obj, parent):
index = 1

35
issues.py Normal file

@ -0,0 +1,35 @@
#!/usr/bin/env python3
class Issues:
OS = ['Debian', 'Ubuntu', 'Redhat']
CATEGORY = ['cve', 'cis']
def __init__(self, alias, os, severity, priority, component, description, category):
self._alias = alias # CVE-xxxx-yyyy
self._os = os
self._severity = severity
self._priority = priority
self._component = component
self._description = description
self._category = category
def getAlias(self) -> str:
return self._alias
def getOs(self) -> str:
return self._os
def getSeverity(self) -> str:
return self._severity
def getPriority(self) -> str:
return self._priority
def getComponent(self) -> str:
return self._component
def getDescription(self) -> str:
return self._description
def getCategory(self) -> str:
return self._category

@ -1,9 +1,7 @@
#!/usr/bin/env python
from core.main import main
import os
if __name__ == "__main__":
path = f"{os.path.dirname(__file__)}"
main(path)
main()

118
old_main.py Executable file

@ -0,0 +1,118 @@
# coding: utf-8
import re
from os import path
from subprocess import call, check_output, run
# 3 levels to tests: low, medium anh high
CHECKSLIST = {}
# TIPS
# https://www.process.st/server-security/
def identifySystem():
os = None
with open('/etc/issue', 'r') as f:
line = f.readline()
if re.search('Arch Linux', line):
os = 'ARCHLINUX'
elif re.search('Ubuntu', line):
os = 'UBUNTU'
elif re.search('Debian', line):
os = 'DEBIAN'
else:
os = 'UNKNOWN'
return os
def check_upgrade_packages():
pass
def check_telnet_is_open():
# check port 23 is listening
r = run(['ss', '-atn'], capture_output=True)
r = r.stdout.decode()
print(r)
def check_empty_local_passwords():
pass
def check_security_access():
# Check in /etc/security/access
pass
def check_hosts_allow():
# Check in /etc/hosts.allow
pass
def check_sshd_root():
res = False
if not path.exists("/etc/ssh/sshd_config"):
print("File sshd_config doesn't exist")
return False
with open("/etc/ssh/sshd_config", "r") as f:
for l in f.readlines():
l = l.replace('\n', '')
if re.search("PermitRootLogin.*root", l):
if not re.search("^#", l):
res = True
return res
def generateChecksList():
# LOW
CHECKSLIST['low'] = []
CHECKSLIST['low'].append({
'callback': check_sshd_root,
'name': check_sshd_root.__name__,
'resolution': 'Please, remove root auth to your server',
'score': 100
})
CHECKSLIST['low'].append({
'callback': check_upgrade_packages,
'name': check_upgrade_packages.__name__,
'resolution': 'Please, upgrade your packages',
'score': 50
})
CHECKSLIST['low'].append({
'callback': check_telnet_is_open,
'name': check_telnet_is_open.__name__,
'resolution': 'Telnet is enabled. Please, disabled this program if you could.',
'score': 50
})
# MEDIUM
CHECKSLIST['medium'] = {}
# HIGH
CHECKSLIST['high'] = {}
def getTotalScore():
score = 0
for entry in CHECKSLIST['low']:
score += entry['score']
return score
def main():
# Generate our checklist
generateChecksList()
# Get total score
totalScore = getTotalScore()
# Identify system
identifySystem()
score = totalScore
for entry in CHECKSLIST['low']:
print(f'Checking {entry["name"]}...')
res = entry['callback']()
if res:
print(entry['resolution'])
score -= entry['score']
print(f'Your total score: {score}')
if __name__ == "__main__":
main()

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1,48 +0,0 @@
{% if data["apache"]["indexes"]["audit"] %}
{% for item in data['apache']['indexes']['directories'] %}
<div class="accordion" id="accordionApacheIndexes">
<div class="accordion-item">
<h2 class="accordion-header">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#{{ data['apache']['indexes']['directories'][item]['accordion-id'] }}" aria-expanded="true" aria-controls="{{ data['apache']['indexes']['directories'][item]['accordion-id'] }}">
<strong>Directory {{ item }}</strong>
{% if data['apache']['indexes']['directories'][item]['result'] == 'failed' %}
<span class="text-bg-danger p-1" style="padding-left:10pt;padding-right:10pt;margin-left:15pt;">{{ data['apache']['indexes']['directories'][item]['result'] }}</span>
{% elif data['apache']['indexes']['directories'][item]['result'] == 'success' %}
<span class="text-bg-success p-1" style="padding-left:10pt;padding-right:10pt;margin-left:15pt;">{{ data['apache']['indexes']['directories'][item]['result'] }}</span>
{% endif %}
<span class="text-bg-primary p-1" style="padding-left:10pt;padding-right:10pt;margin-left:15pt;">{{ data['apache']['indexes']['level'] }}</span>
</button>
</h2>
<div id="{{ data['apache']['indexes']['directories'][item]['accordion-id'] }}" class="accordion-collapse collapse" data-bs-parent="#accordionApacheIndexes">
<div class="accordion-body">
{{ data['apache']['indexes']['description'] }}. <br />
{% if data['apache']['indexes']["directories"][item]['result'] == 'failed' %}
Result of the audit:
<div class="bd-example-snippet bd-code-snippet">
<div class="highlight">
<pre tabindex="0" class="chroma"><code class="language-shell">
{% for indexes in data['apache']['indexes']["directories"][item]['options'] %}
{{ indexes }}
{% endfor %}
</pre></code>
</div> <!-- end .highlight -->
</div> <!-- end .bd-code-snippet -->
For resolving the issue, add this line in the apache config file:
<div class="bd-example-snippet bd-code-snippet">
<div class="highlight">
<pre tabindex="0" class="chroma"><code class="language-shell">
{{ data['apache']['indexes']['recommand_value'] }}
</pre></code>
</div> <!-- end .highlight -->
</div> <!-- end .bd-code-snippet -->
{% endif %}
</div> <!-- end .accordion-body -->
</div> <!-- end .accordion-collapse -->
</div> <!-- end .accordion-item -->
</div> <!-- end .accordion -->
{% endfor %}
{% else %}
{{ data['apache']['indexes']['msg'] }}
{% endif %}

@ -1,38 +0,0 @@
{% if data['apache']['signature']['audit'] %}
{% for item in data['apache']['signature']['signature'] %}
<div class="accordion" id="accordionApacheSignature">
<div class="accordion-item">
<h2 class="accordion-header">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#{{ data['apache']['signature']['signature'][item]['accordion-id'] }}" aria-expanded="true" aria-controls="{{ data['apache']['signature']['signature'][item]['accordion-id'] }}">
<strong>VirtualHost {{ item }}</strong>
{% if data['apache']['signature']['signature'][item]['result'] == 'failed' %}
<span class="text-bg-danger p-1" style="padding-left:10pt;padding-right:10pt;margin-left:15pt;">{{ data['apache']['signature']['signature'][item]['result'] }}</span>
{% elif data['apache']['signature']['signature'][item]['result'] == 'success' %}
<span class="text-bg-success p-1" style="padding-left:10pt;padding-right:10pt;margin-left:15pt;">{{ data['apache']['signature']['signature'][item]['result'] }}</span>
{% endif %}
<span class="text-bg-primary p-1" style="padding-left:10pt;padding-right:10pt;margin-left:15pt;">{{ data['apache']['signature']['signature'][item]['level'] }}</span>
</button>
</h2>
<div id="{{ data['apache']['signature']['signature'][item]['accordion-id'] }}" class="accordion-collapse collapse" data-bs-parent="#accordionApacheSignature">
<div class="accordion-body">
{{ data['apache']['signature']['signature'][item]['description'] }}. <br />
{% if data['apache']['signature']['signature'][item]['result'] == 'failed' %}
For resolving the issue, add this line in the VirtualHost file:
<div class="bd-example-snippet bd-code-snippet">
<div class="highlight">
<pre tabindex="0" class="chroma"><code class="language-shell">
{{ data['apache']['signature']['signature'][item]['recommand_value'] }}
</pre></code>
</div> <!-- end .highlight -->
</div> <!-- end .bd-code-snippet -->
{% endif %}
</div> <!-- end .accordion-body -->
</div> <!-- end .accordion-collapse -->
</div> <!-- end .accordion-item -->
</div> <!-- end .accordion -->
{% endfor %}
{% else %}
{{ data['apache']['signature']['msg'] }}
{% endif %}

@ -1,48 +0,0 @@
{% if data["apache"]["ssl"]["audit"] %}
{% for item in data['apache']['ssl']['virtualhost'] %}
<div class="accordion" id="accordionApacheSsl">
<div class="accordion-item">
<h2 class="accordion-header">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#{{ data['apache']['ssl']['virtualhost'][item]['accordion-id'] }}" aria-expanded="true" aria-controls="{{ data['apache']['ssl']['virtualhost'][item]['accordion-id'] }}">
<strong>VirtualHost {{ item }}</strong>
{% if data['apache']['ssl']['virtualhost'][item]['result'] == 'failed' %}
<span class="text-bg-danger p-1" style="padding-left:10pt;padding-right:10pt;margin-left:15pt;">{{ data['apache']['ssl']['virtualhost'][item]['result'] }}</span>
{% elif data['apache']['ssl']['virtualhost'][item]['result'] == 'success' %}
<span class="text-bg-success p-1" style="padding-left:10pt;padding-right:10pt;margin-left:15pt;">{{ data['apache']['ssl']['virtualhost'][item]['result'] }}</span>
{% endif %}
<span class="text-bg-primary p-1" style="padding-left:10pt;padding-right:10pt;margin-left:15pt;">{{ data['apache']['ssl']['virtualhost'][item]['level'] }}</span>
</button>
</h2>
<div id="{{ data['apache']['ssl']['virtualhost'][item]['accordion-id'] }}" class="accordion-collapse collapse" data-bs-parent="#accordionApacheSsl">
<div class="accordion-body">
{{ data['apache']['ssl']['virtualhost'][item]['description'] }}. <br />
{% if data['apache']['ssl']['virtualhost'][item]['result'] == 'failed' %}
Result of the audit:
<div class="bd-example-snippet bd-code-snippet">
<div class="highlight">
<pre tabindex="0" class="chroma"><code class="language-shell">
{% for protocol in data['apache']['ssl']['virtualhost'][item]['msg'] %}
{{ protocol }}
{% endfor %}
</pre></code>
</div> <!-- end .highlight -->
</div> <!-- end .bd-code-snippet -->
For resolving the issue, add this line in the VirtualHost file:
<div class="bd-example-snippet bd-code-snippet">
<div class="highlight">
<pre tabindex="0" class="chroma"><code class="language-shell">
{{ data['apache']['ssl']['virtualhost'][item]['recommand_value'] }}
</pre></code>
</div> <!-- end .highlight -->
</div> <!-- end .bd-code-snippet -->
{% endif %}
</div> <!-- end .accordion-body -->
</div> <!-- end .accordion-collapse -->
</div> <!-- end .accordion-item -->
</div> <!-- end .accordion -->
{% endfor %}
{% else %}
{{ data['apache']['ssl']['msg'] }}
{% endif %}

@ -1,19 +1,43 @@
<h3 class="fs-3">Apache</h3>
{% if data['apache']['audit'] %}
<h5 class="fs-5">SSL</h5>
{% include 'apache-ssl.html.j2' %}
<div style="margin-bottom: 15pt"></div>
<h5 class="fs-5">Signature</h5>
{% include 'apache-signature.html.j2' %}
<div style="margin-bottom: 15pt"></div>
<h5 class="fs-5">Indexes</h5>
{% include 'apache-indexes.html.j2' %}
{% else %}
{{ data['apache']['msg'] }}
{% endif %}
{% 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="#accordionApache">
<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 %}

@ -1,46 +1,39 @@
<h3 class="fs-3">Grub</h3>
<div class="accordion" id="accordionGrub">
<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['grub']['accordion-id'] }}" aria-expanded="true" aria-controls="{{ data['grub']['accordion-id'] }}">
<strong>Grub</strong>
{% if data['grub']['result'] == 'failed' %}
<strong>Grub</strong>
{% if data['grub']['result'] == 'failed' %}
<span class="text-bg-danger p-1" style="padding-left:10pt;padding-right:10pt;margin-left:15pt;">{{ data['grub']['result'] }}</span>
{% elif data['grub']['result'] == 'success' %}
{% elif data['grub']['result'] == 'success' %}
<span class="text-bg-success p-1" style="padding-left:10pt;padding-right:10pt;margin-left:15pt;">{{ data['grub']['result'] }}</span>
{% endif %}
<span class="text-bg-primary p-1" style="padding-left:10pt;padding-right:10pt;margin-left:15pt;">{{ data['grub']['level'] }}</span>
{% endif %}
</button>
</h2>
<div id="{{ data['grub']['accordion-id'] }}" class="accordion-collapse collapse" data-bs-parent="#accordionGrub">
<div class="accordion-body">
{{ data['grub']['description'] }}. <br />
{% if data['grub']['result'] == 'success' %}
Your current permission of this file:
<div class="bd-example-snippet bd-code-snippet">
<div class="highlight">
<pre tabindex="0" class="chroma"><code class="language-shell">
{{ data['grub']['current_value'] }}
</pre></code>
</div> <!-- end .highlight -->
</div> <!-- end .bd-code-snippet -->
<div class="bd-example-snippet bd-code-snippet">
<div class="highlight">
<pre tabindex="0" class="chroma"><code class="language-shell">
{{ data['grub']['recommand_value'] }}
</pre></code>
</div>
</div>
{% else %}
For resolving the issue, change the permission of the file:
For resolving the issue, add this line in the <strong>{{ data['filename'] }}</strong> profile:
<div class="bd-example-snippet bd-code-snippet">
<div class="highlight">
<pre tabindex="0" class="chroma"><code class="language-shell">
{{ data['grub']['resolve'] }}
{{ data['grub']['recommand_value'] }}
</pre></code>
</div> <!-- end highlight -->
</div> <!-- end bd-code-snippet -->
</div>
</div>
{% endif %}
{% if 'id' in data['grub'] %}
linked with the <strong>{{ data['grub']['id'] }}</strong>
{% endif %}
</div> <!-- end .accordion-body -->
</div> <!-- end .accordion-collapse -->
</div> <!-- end .accordion-item -->
</div> <!-- end .accordion -->
</div>
</div>
</div>
</div>

@ -1,30 +1,29 @@
<h3 class="fs-3">Profile</h3>
{% for item in data['profile']['vulnerabilities'] %}
<div class="accordion" id="accordionProfile">
<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['profile']['vulnerabilities'][item]['accordion-id'] }}" aria-expanded="true" aria-controls="{{ data['profile']['vulnerabilities'][item]['accordion-id'] }}">
<strong>{{ item }}</strong>
{% if data['profile']['vulnerabilities'][item]['result'] == 'failed' %}
{% if data['profile']['vulnerabilities'][item]['result'] == 'failed' %}
<span class="text-bg-danger p-1" style="padding-left:10pt;padding-right:10pt;margin-left:15pt;">{{ data['profile']['vulnerabilities'][item]['result'] }}</span>
{% elif data['profile']['vulnerabilities'][item]['result'] == 'success' %}
{% elif data['profile']['vulnerabilities'][item]['result'] == 'success' %}
<span class="text-bg-success p-1" style="padding-left:10pt;padding-right:10pt;margin-left:15pt;">{{ data['profile']['vulnerabilities'][item]['result'] }}</span>
{% endif %}
<span class="text-bg-primary p-1" style="padding-left:10pt;padding-right:10pt;margin-left:15pt;">{{ data['profile']['vulnerabilities'][item]['level'] }}</span>
{% endif %}
</button>
</h2>
<div id="{{ data['profile']['vulnerabilities'][item]['accordion-id'] }}" class="accordion-collapse collapse" data-bs-parent="#accordionProfile">
<div class="accordion-body">
{{ data['profile']['vulnerabilities'][item]['description'] }}. <br />
{% if data['profile']['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['profile']['vulnerabilities'][item]['flagFound'] }}
</pre></code>
</div> <!-- end highlight -->
</div> <!-- end bd-code-snippet -->
<div class="bd-example-snippet bd-code-snippet">
<div class="highlight">
<pre tabindex="0" class="chroma"><code class="language-shell">
{{ data['profile']['vulnerabilities'][item]['flagFound'] }}
</pre></code>
</div>
</div>
{% else %}
For resolving the issue, add this line in the <strong>{{ data['filename'] }}</strong> profile:
<div class="bd-example-snippet bd-code-snippet">
@ -32,16 +31,11 @@
<pre tabindex="0" class="chroma"><code class="language-shell">
{{ data['profile']['vulnerabilities'][item]['flag'] }} = {{ data['profile']['vulnerabilities'][item]['recommand_value'] }}
</pre></code>
</div> <!-- end highlight -->
</div> <!-- end bd-code-snippet -->
</div>
</div>
{% endif %}
{% if 'id' in data['profile']['vulnerabilities']['item'] %}
Linked with the <strong>{{ data['profile']['vulnerabilities'][item]['id'] }}</strong>
{% endif %}
</div> <!-- end .accordion-body -->
</div> <!-- end .accordion-collapse -->
</div> <!-- end .accordion-item -->
</div> <!-- end .accordion -->
</div>
</div>
</div>
</div>
{% endfor %}

@ -1,17 +1,16 @@
<h3 class="fs-3">Postfix</h3>
{% for item in data['postfix']['vulnerabilities'] %}
<div class="accordion" id="accordionPostfix">
<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>
<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>
<span class="text-bg-success p-1" style="padding-left:10pt;padding-right:10pt;margin-left:15pt;">{{ data['postfix']['vulnerabilities'][item]['result'] }}</span>
{% endif %}
<span class="text-bg-primary p-1" style="padding-left:10pt;padding-right:10pt;margin-left:15pt;">{{ data['postfix']['vulnerabilities'][item]['level'] }}</span>
</button>
</h2>
<div id="{{ data['postfix']['vulnerabilities'][item]['accordion-id'] }}" class="accordion-collapse collapse" data-bs-parent="#accordionPostfix">
@ -23,8 +22,8 @@
<pre tabindex="0" class="chroma"><code class="language-shell">
{{ data['postfix']['vulnerabilities'][item]['flagFound'] }}
</pre></code>
</div> <!-- end .highlight -->
</div> <!-- end .bd-code-snippet -->
</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">
@ -34,16 +33,11 @@
{{ data['postfix']['vulnerabilities'][item]['flag'] }} = {{ value }}
{% endfor %}
</pre></code>
</div> <!-- end .highlight -->
</div> <!-- end .bd-code-snippet -->
</div>
</div>
{% endif %}
{% if 'id' in data['postfix']['vulnerabilities'][item] %}
linked with the <strong>{{ data['postfix']['vulnerabilities'][item]['id'] }}</strong>
{% endif %}
</div> <!-- end .accordion-body -->
</div> <!-- end .accordion-collapse -->
</div> <!-- end .accordion-item -->
</div> <!-- end .accordion -->
</div>
</div>
</div>
</div>
{% endfor %}

@ -11,27 +11,21 @@
{% elif data['sysctl']['file']['sysctl'][item]['result']['result'] == 'success' %}
<span class="text-bg-success p-1" style="padding-left:10pt;padding-right:10pt;margin-left:15pt;">{{ data['sysctl']['file']['sysctl'][item]['result']['result'] }}</span>
{% endif %}
<span class="text-bg-primary p-1" style="padding-left:10pt;padding-right:10pt;margin-left:15pt;">{{ data['sysctl']['file']['sysctl'][item]['level'] }}</span>
</button>
</h2>
<div id="{{ data['sysctl']['file']['sysctl'][item]['accordion-id'] }}" class="accordion-collapse collapse" data-bs-parent="#accordionSysctl">
<div class="accordion-body">
{{ data['sysctl']['file']['sysctl'][item]['description'] }}. <br />
For resolving the issue, add this line in the <strong>{{ data['sysctl']['file']['filename'] }}</strong> file:
<div class="bd-example-snippet bd-code-snippet">
<div class="highlight">
<pre tabindex="0" class="chroma"><code class="language-shell">
{{ data['sysctl']['file']['sysctl'][item]['flag'] }} = {{ data['sysctl']['file']['sysctl'][item]['value'] }}
</pre></code>
</div> <!-- end highlight -->
</div> <!-- end bd-code-snippet -->
{% if 'id' in data['sysctl']['file']['sysctl'][item] %}
Linked with the <strong>{{ data['sysctl']['file']['sysctl'][item]['id'] }}</strong>
{% endif %}
</div> <!-- end accordion-body -->
</div> <!-- end accordion-collapse -->
</div> <!-- end accordion-item -->
</div> <!-- end .accordion -->
For resolving the issue, add this line in the <strong>{{ data['sysctl']['file']['filename'] }}</strong> file:
<div class="bd-example-snippet bd-code-snippet">
<div class="highlight">
<pre tabindex="0" class="chroma"><code class="language-shell">
{{ data['sysctl']['file']['sysctl'][item]['flag'] }} = {{ data['sysctl']['file']['sysctl'][item]['value'] }}
</pre></code>
</div>
</div>
</div>
</div>
</div>
</div>
{% endfor %}

@ -14,6 +14,17 @@ class ConfigError(Exception):
super().__init__(self.message)
def identifySystem():
#os = None
#with open('/etc/issue', 'r') as f:
# line = f.readline()
# if re.search('Arch Linux', line):
# os = 'ARCHLINUX'
# elif re.search('Ubuntu', line):
# os = 'UBUNTU'
# elif re.search('Debian', line):
# os = 'DEBIAN'
# else:
# os = 'UNKNOWN'
kernelVers = run(['/usr/bin/lsb_release', '-is'], capture_output=True)
return kernelVers.stdout.decode('utf-8')