Analyzing apache
This commit is contained in:
+1
-1
@@ -56,7 +56,7 @@ def main():
|
||||
|
||||
# Get system informations
|
||||
report['kernel'] = getKernelVersion()
|
||||
report['release'] = f"{identifySystem()} {getRelease()} ({getCodeName()}) "
|
||||
report['release'] = f"{identifySystem()} {getRelease()} {getCodeName().strip()}"
|
||||
|
||||
# Create our dispatcher
|
||||
dispatcher = Dispatcher()
|
||||
|
||||
+198
-41
@@ -2,14 +2,14 @@
|
||||
|
||||
import re
|
||||
from os import listdir
|
||||
from os.path import isdir
|
||||
from os.path import isdir, isfile
|
||||
from audit.system.plugins.apache import apache_protocols, apache_signature, apache_indexes
|
||||
|
||||
|
||||
class Apache:
|
||||
def __init__(self, arguments):
|
||||
self._ssl_versions = apache_protocols()
|
||||
self._signature = apache_signature()
|
||||
self._signatures = apache_signature()
|
||||
self._indexes = apache_indexes()
|
||||
self._reports = dict()
|
||||
self._apache_directory = arguments["apache_directory"]
|
||||
@@ -26,36 +26,42 @@ class 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"
|
||||
|
||||
print(self._reports)
|
||||
|
||||
def getReports(self) -> dict:
|
||||
return self._reports
|
||||
|
||||
################################################
|
||||
# Analyzing SSL
|
||||
################################################
|
||||
def _analyzingSslVersion(self):
|
||||
# Check if the file exist
|
||||
path = f"{self._apache_directory}/sites-available"
|
||||
if isdir(path):
|
||||
self._reports['audit'] = True
|
||||
self._reports['ssl']['audit'] = True
|
||||
count = 0
|
||||
self._reports["ssl"]["virtualhost"] = dict()
|
||||
for site in listdir(path):
|
||||
with open(f"{path}/{site}", 'rb') as f:
|
||||
self._parseFile(f)
|
||||
vh = f"{path}/{site}"
|
||||
with open(vh, 'rb') as f:
|
||||
self._parseFileFindingSsl(f, site)
|
||||
count += 1
|
||||
|
||||
if count == 0:
|
||||
self._reports['audit'] = False
|
||||
self._reports['msg'] = \
|
||||
self._reports['ssl']['audit'] = False
|
||||
self._reports['ssl']['msg'] = \
|
||||
f'No virtual host found in the directory {path}'
|
||||
else:
|
||||
self._reports['audit'] = False
|
||||
self._reports["msg"] = f"No directory {path} found"
|
||||
self._reports['ssl']['audit'] = False
|
||||
self._reports['ssl']["msg"] = f"No directory {path} found"
|
||||
|
||||
def _parseFile(self, fdata):
|
||||
def _parseFileFindingSsl(self, fdata, virtualhost):
|
||||
data = fdata.read()
|
||||
lines = data.splitlines()
|
||||
|
||||
@@ -63,57 +69,208 @@ class Apache:
|
||||
line = line.decode('utf-8')
|
||||
|
||||
# check if SSL is enable for the VirtualHost
|
||||
grSSLEngine = re.search("SSLEngine on", line)
|
||||
# (?#) -> remove commentary
|
||||
# (\s) -> remove space and tabulation
|
||||
grSSLEngine = re.search(
|
||||
"(?#)(\s)SSLEngine on",
|
||||
line,
|
||||
re.IGNORECASE
|
||||
)
|
||||
if grSSLEngine:
|
||||
self._check_ssl_version(lines)
|
||||
report = self._check_ssl_version(lines)
|
||||
|
||||
def _check_ssl_version(self, lines):
|
||||
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("SSLProtocol", line)
|
||||
grSSLProtocol = re.search(
|
||||
"(?#)(\s)SSLProtocol",
|
||||
line,
|
||||
re.IGNORECASE
|
||||
)
|
||||
if grSSLProtocol:
|
||||
for protocol in self._ssl_versions["protocols"]:
|
||||
if protocol in line:
|
||||
print(line)
|
||||
grProtocol = re.search(f"-{protocol}", line)
|
||||
if grProtocol:
|
||||
protocolsFound.append(protocol)
|
||||
findProtocol = True
|
||||
|
||||
print(protocolsFound)
|
||||
|
||||
if len(self._ssl_versions) == len(protocolsFound):
|
||||
print("Success")
|
||||
if len(self._ssl_versions["protocols"]) == len(protocolsFound):
|
||||
report["result"] = "success"
|
||||
else:
|
||||
print("Failed")
|
||||
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"
|
||||
)
|
||||
|
||||
if findProtocol:
|
||||
self._reports["ssl"]["result"] = "success"
|
||||
else:
|
||||
self._reports["ssl"]["result"] = "failed"
|
||||
|
||||
|
||||
self._reports["ssl"]["description"] = \
|
||||
report["description"] = \
|
||||
self._ssl_versions["description"]
|
||||
self._reports["ssl"]["level"] = self._ssl_versions["level"]
|
||||
self._reports["ssl"]["recommand_value"] = \
|
||||
report["level"] = self._ssl_versions["level"]
|
||||
report["recommand_value"] = \
|
||||
self._ssl_versions["recommand_value"]
|
||||
return report
|
||||
|
||||
def _check_value_exist(self, line, value) -> bool:
|
||||
grValue = re.search(value, line)
|
||||
if grValue:
|
||||
return True
|
||||
return False
|
||||
################################################
|
||||
# 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"]["audit"] = \
|
||||
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"]["indexes"] = \
|
||||
self._parsingApacheConfig(fdata)
|
||||
else:
|
||||
self._reports["indexes"]["audit"] = False
|
||||
self._reports["indexes"]["audit"] = \
|
||||
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 = list()
|
||||
directoryFound = False
|
||||
index = 0
|
||||
optsFound = list()
|
||||
|
||||
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
|
||||
directories.append(list())
|
||||
directories[index].append(line)
|
||||
else:
|
||||
#directory.append(line)
|
||||
directories[index].append(line)
|
||||
grDirectory = re.search("</Directory>", line, re.IGNORECASE)
|
||||
if grDirectory:
|
||||
directoryFound = False
|
||||
index += 1
|
||||
|
||||
# We will find if we find an indexes option
|
||||
for d in directories:
|
||||
for entry in d:
|
||||
# We get the directory path
|
||||
grDirectory = re.search(
|
||||
f"<Directory",
|
||||
entry,
|
||||
re.IGNORECASE
|
||||
)
|
||||
if grDirectory:
|
||||
path = entry.replace("<Directory", "")
|
||||
path = path.replace(">", "")
|
||||
path = path.replace("\"", "")
|
||||
report["directories"][path] = dict()
|
||||
|
||||
# Try to find the Option flag
|
||||
grFlag = re.search(
|
||||
f"{self._indexes['flag']}",
|
||||
entry,
|
||||
re.IGNORECASE
|
||||
)
|
||||
if grFlag:
|
||||
for opt in self._indexes['options']:
|
||||
grOption = re.search(
|
||||
f"-{opt}",
|
||||
entry,
|
||||
re.IGNORECASE
|
||||
)
|
||||
if grOption:
|
||||
optsFound.append(opt)
|
||||
#print(d[0])
|
||||
|
||||
report["audit"] = True
|
||||
report["options"] = dict()
|
||||
if len(optsFound) == len(self._indexes['options']):
|
||||
report["result"] = "success"
|
||||
else:
|
||||
report["result"] = "failed"
|
||||
for opt in self._indexes["options"]:
|
||||
if opt not in optsFound:
|
||||
report["options"][opt] = f"{opt} is not removed. You should disable it"
|
||||
|
||||
report["description"] = self._indexes["description"]
|
||||
report["level"] = self._indexes["level"]
|
||||
report["recommand_value"] = self._indexes["recommand_value"]
|
||||
print(report)
|
||||
return report
|
||||
|
||||
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
|
||||
"""
|
||||
|
||||
+20
-4
@@ -38,15 +38,31 @@ def generateHtmlReport(data):
|
||||
_generateAccordion(dataJinja2['sysctl']['file']['sysctl'], 'sysctl')
|
||||
|
||||
if 'apache' in data['system']:
|
||||
dataJinja2['apache'] = data['system']['apache']
|
||||
|
||||
if data['system']['apache']['audit']:
|
||||
dataJinja2['apache'] = data['system']['apache']
|
||||
else:
|
||||
dataJinja2['apache'] = data['system']['apache']
|
||||
if data['system']['apache']['ssl']['audit']:
|
||||
_generateAccordion(
|
||||
dataJinja2["apache"]["ssl"]["virtualhost"],
|
||||
"apache-virtualhost"
|
||||
)
|
||||
if data['system']['apache']['signature']['audit']:
|
||||
print(dataJinja2['apache']['signature'])
|
||||
_generateAccordion(
|
||||
dataJinja2["apache"]["signature"]["signature"],
|
||||
"apache-signature"
|
||||
)
|
||||
print("")
|
||||
if data['system']['apache']['indexes']['audit']:
|
||||
print(dataJinja2['apache']['indexes'])
|
||||
_generateAccordion(
|
||||
dataJinja2["apache"]["indexes"]["indexes"],
|
||||
"apache-indexes"
|
||||
)
|
||||
|
||||
if 'localaccount' in data['system']:
|
||||
if 'profile' in data['system']['localaccount']:
|
||||
dataJinja2['profile'] = dict()
|
||||
#dataJinja2['profile']['level'] = data['system']['localaccount']['profile']['level']
|
||||
dataJinja2['profile']['filename'] = data['system']['localaccount']['profile']['filename']
|
||||
dataJinja2['profile']['vulnerabilities'] = data['system']['localaccount']['profile']['vulnerabilities']
|
||||
|
||||
|
||||
Reference in New Issue
Block a user