Parse sysctl
This commit is contained in:
parent
8b2e9cbd29
commit
882cdf805f
16
core/postfix.py
Normal file
16
core/postfix.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from parsing.postfix import Parsing
|
||||||
|
from issues.postfix import postfix
|
||||||
|
|
||||||
|
class Postfix:
|
||||||
|
def __init__(self):
|
||||||
|
self._objects = dict()
|
||||||
|
self._reports = dict()
|
||||||
|
|
||||||
|
self._postfix()
|
||||||
|
|
||||||
|
self._parsing = Parsing(self._objects)
|
||||||
|
|
||||||
|
def _postfix(self):
|
||||||
|
self._objects = postfix()
|
@ -1,14 +1,13 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
from parsing.sysctl import Parsing
|
from parsing.sysctl import Parsing
|
||||||
from issues.system import system
|
|
||||||
from issues.sysctl import sysctl
|
from issues.sysctl import sysctl
|
||||||
|
|
||||||
|
|
||||||
class Sysctl:
|
class Sysctl:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._objects = dict()
|
self._objects = dict()
|
||||||
self._reports = list()
|
self._reports = dict()
|
||||||
self._audit = list()
|
self._audit = list()
|
||||||
|
|
||||||
self._audit.append({
|
self._audit.append({
|
||||||
@ -25,15 +24,16 @@ class Sysctl:
|
|||||||
self._parsing = Parsing(self._objects, self._audit)
|
self._parsing = Parsing(self._objects, self._audit)
|
||||||
|
|
||||||
def _sysctl(self):
|
def _sysctl(self):
|
||||||
self._objects['sysctl'] = sysctl()
|
self._objects = sysctl()
|
||||||
|
|
||||||
def runAudit(self):
|
def runAudit(self):
|
||||||
# Read /etc/sysctl.conf
|
# Read /etc/sysctl.conf
|
||||||
self._parsing.runParsing()
|
self._parsing.runParsing()
|
||||||
self._reports.append(self._parsing.getResults())
|
#self._reports.append(self._parsing.getResults())
|
||||||
|
self._reports = self._parsing.getResults()
|
||||||
|
|
||||||
# Run process sysctl
|
# Run process sysctl
|
||||||
|
|
||||||
def getReports(self) -> list:
|
def getReports(self) -> dict:
|
||||||
return self._reports
|
return self._reports
|
||||||
|
|
6
issues/postfix.py
Normal file
6
issues/postfix.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
def postfix() -> dict:
|
||||||
|
postfix = dict()
|
||||||
|
|
||||||
|
return postfix
|
186
issues/sysctl.py
186
issues/sysctl.py
@ -6,6 +6,9 @@ def sysctl() -> list:
|
|||||||
sysctl = list()
|
sysctl = list()
|
||||||
|
|
||||||
# https://access.redhat.com/security/sysctl/sysctl-2023-0179
|
# https://access.redhat.com/security/sysctl/sysctl-2023-0179
|
||||||
|
#####
|
||||||
|
# CVE
|
||||||
|
#####
|
||||||
sysctl.append({
|
sysctl.append({
|
||||||
"from": "cve",
|
"from": "cve",
|
||||||
"id": "cve-2023-0179",
|
"id": "cve-2023-0179",
|
||||||
@ -20,7 +23,9 @@ def sysctl() -> list:
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
#####
|
||||||
# Best practice from CIS
|
# Best practice from CIS
|
||||||
|
#####
|
||||||
sysctl.append({
|
sysctl.append({
|
||||||
"from": "cis",
|
"from": "cis",
|
||||||
"id": "",
|
"id": "",
|
||||||
@ -29,5 +34,186 @@ def sysctl() -> list:
|
|||||||
"value": 0,
|
"value": 0,
|
||||||
"level": "medium",
|
"level": "medium",
|
||||||
})
|
})
|
||||||
|
sysctl.append({
|
||||||
|
"from": "cis",
|
||||||
|
"id": "",
|
||||||
|
"description": "Disable ICMP redirects IPv4",
|
||||||
|
"flag": "net.ipv4.conf.all.accept_redirects",
|
||||||
|
"value": 0,
|
||||||
|
"level": "medium",
|
||||||
|
})
|
||||||
|
sysctl.append({
|
||||||
|
"from": "cis",
|
||||||
|
"id": "",
|
||||||
|
"description": "Disable Accepting Source Routed packets IPv4 for all interfaces",
|
||||||
|
"flag": "net.ipv4.conf.all.accept_source_route",
|
||||||
|
"value": 0,
|
||||||
|
"level": "medium",
|
||||||
|
})
|
||||||
|
sysctl.append({
|
||||||
|
"from": "cis",
|
||||||
|
"id": "",
|
||||||
|
"description": "Disable Accepting Source Routed packets IPv4 for default interface",
|
||||||
|
"flag": "net.ipv4.conf.default.accept_source_route",
|
||||||
|
"value": 0,
|
||||||
|
"level": "medium",
|
||||||
|
})
|
||||||
|
sysctl.append({
|
||||||
|
"from": "cis",
|
||||||
|
"id": "",
|
||||||
|
"description": "Disable ICMP Secure redirects IPv4 for all interfaces",
|
||||||
|
"flag": "net.ipv4.conf.all.secure_redirects",
|
||||||
|
"value": 0,
|
||||||
|
"level": "medium",
|
||||||
|
})
|
||||||
|
sysctl.append({
|
||||||
|
"from": "cis",
|
||||||
|
"id": "",
|
||||||
|
"description": "Disable ICMP Secure redirects IPv4 for default interface",
|
||||||
|
"flag": "net.ipv4.conf.default.secure_redirects",
|
||||||
|
"value": 0,
|
||||||
|
"level": "medium",
|
||||||
|
})
|
||||||
|
sysctl.append({
|
||||||
|
"from": "cis",
|
||||||
|
"id": "",
|
||||||
|
"description": "Enable Log martian packets IPv4 for all interfaces",
|
||||||
|
"flag": "net.ipv4.conf.all.log_martians",
|
||||||
|
"value": 1,
|
||||||
|
"level": "medium",
|
||||||
|
})
|
||||||
|
sysctl.append({
|
||||||
|
"from": "cis",
|
||||||
|
"id": "",
|
||||||
|
"description": "Enable Log martian packets IPv4 for default interface",
|
||||||
|
"flag": "net.ipv4.conf.default.log_martians",
|
||||||
|
"value": 1,
|
||||||
|
"level": "medium",
|
||||||
|
})
|
||||||
|
# https://lwn.net/Articles/277146/
|
||||||
|
sysctl.append({
|
||||||
|
"from": "cis",
|
||||||
|
"id": "",
|
||||||
|
"description": "Enable TCP syn cookies IPv4",
|
||||||
|
"flag": "net.ipv4.tcp_syncookies",
|
||||||
|
"value": 1,
|
||||||
|
"level": "medium",
|
||||||
|
})
|
||||||
|
sysctl.append({
|
||||||
|
"from": "cis",
|
||||||
|
"id": "",
|
||||||
|
"description": "Disable IPv4 forwarding on all interfaces",
|
||||||
|
"flag": "net.ipv4.ip_forward",
|
||||||
|
"value": 0,
|
||||||
|
"level": "medium",
|
||||||
|
})
|
||||||
|
sysctl.append({
|
||||||
|
"from": "cis",
|
||||||
|
"id": "",
|
||||||
|
"description": "Disable IPv4 send redirects on all interfaces",
|
||||||
|
"flag": "net.ipv4.conf.all.send_redirects",
|
||||||
|
"value": 0,
|
||||||
|
"level": "medium",
|
||||||
|
})
|
||||||
|
sysctl.append({
|
||||||
|
"from": "cis",
|
||||||
|
"id": "",
|
||||||
|
"description": "Disable IPv4 send redirects on default interface",
|
||||||
|
"flag": "net.ipv4.conf.default.send_redirects",
|
||||||
|
"value": 0,
|
||||||
|
"level": "medium",
|
||||||
|
})
|
||||||
|
sysctl.append({
|
||||||
|
"from": "cis",
|
||||||
|
"id": "",
|
||||||
|
"description": "Enable IPv4 reverse path filtering on all interfaces",
|
||||||
|
"flag": "net.ipv4.conf.all.rp_filter",
|
||||||
|
"value": 1,
|
||||||
|
"level": "medium",
|
||||||
|
})
|
||||||
|
sysctl.append({
|
||||||
|
"from": "cis",
|
||||||
|
"id": "",
|
||||||
|
"description": "Enable IPv4 reverse path filtering on default interface",
|
||||||
|
"flag": "net.ipv4.conf.default.rp_filter",
|
||||||
|
"value": 1,
|
||||||
|
"level": "medium",
|
||||||
|
})
|
||||||
|
|
||||||
|
# For IPv6
|
||||||
|
sysctl.append({
|
||||||
|
"from": "cis",
|
||||||
|
"id": "",
|
||||||
|
"description": "Disable IPvi6 forwarding",
|
||||||
|
"flag": "net.ipv6.conf.all.forwarding",
|
||||||
|
"value": 0,
|
||||||
|
"level": "medium",
|
||||||
|
})
|
||||||
|
sysctl.append({
|
||||||
|
"from": "cis",
|
||||||
|
"id": "",
|
||||||
|
"description": "Disable ICMP redirects IPv6",
|
||||||
|
"flag": "net.ipv6.conf.all.accept_redirects",
|
||||||
|
"value": 0,
|
||||||
|
"level": "medium",
|
||||||
|
})
|
||||||
|
sysctl.append({
|
||||||
|
"from": "cis",
|
||||||
|
"id": "",
|
||||||
|
"description": "Disable ICMP redirects IPv6 for default interface",
|
||||||
|
"flag": "net.ipv6.conf.default.accept_redirects",
|
||||||
|
"value": 0,
|
||||||
|
"level": "medium",
|
||||||
|
})
|
||||||
|
# https://datatracker.ietf.org/doc/html/rfc4861
|
||||||
|
sysctl.append({
|
||||||
|
"from": "cis",
|
||||||
|
"id": "",
|
||||||
|
"description": "Disable Route Advertisements for IPv6 for all interfaces",
|
||||||
|
"flag": "net.ipv6.conf.all.accept_ra",
|
||||||
|
"value": 0,
|
||||||
|
"level": "medium",
|
||||||
|
})
|
||||||
|
sysctl.append({
|
||||||
|
"from": "cis",
|
||||||
|
"id": "",
|
||||||
|
"description": "Disable Route Advertisements for IPv6 for default interface",
|
||||||
|
"flag": "net.ipv6.conf.default.accept_ra",
|
||||||
|
"value": 0,
|
||||||
|
"level": "medium",
|
||||||
|
})
|
||||||
|
sysctl.append({
|
||||||
|
"from": "cis",
|
||||||
|
"id": "",
|
||||||
|
"description": "Disable Accepting Source Routed for IPv6 for all interfaces",
|
||||||
|
"flag": "net.ipv6.conf.all.accept_source_route",
|
||||||
|
"value": 0,
|
||||||
|
"level": "medium",
|
||||||
|
})
|
||||||
|
sysctl.append({
|
||||||
|
"from": "cis",
|
||||||
|
"id": "",
|
||||||
|
"description": "Disable Accepting Source Routed for IPv6 for default interface",
|
||||||
|
"flag": "net.ipv6.conf.default.accept_source_route",
|
||||||
|
"value": 0,
|
||||||
|
"level": "medium",
|
||||||
|
})
|
||||||
|
sysctl.append({
|
||||||
|
"from": "cis",
|
||||||
|
"id": "",
|
||||||
|
"description": "Disable ICMP Secure redirects IPv6 for all interfaces",
|
||||||
|
"flag": "net.ipv6.conf.all.secure_redirects",
|
||||||
|
"value": 0,
|
||||||
|
"level": "medium",
|
||||||
|
})
|
||||||
|
sysctl.append({
|
||||||
|
"from": "cis",
|
||||||
|
"id": "",
|
||||||
|
"description": "Disable ICMP Secure redirects IPv6 for default interface",
|
||||||
|
"flag": "net.ipv6.conf.default.secure_redirects",
|
||||||
|
"value": 0,
|
||||||
|
"level": "medium",
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
return sysctl
|
return sysctl
|
||||||
|
9
main.py
9
main.py
@ -1,7 +1,9 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
from sysctl import Sysctl
|
from core.sysctl import Sysctl
|
||||||
|
from core.postfix import Postfix
|
||||||
|
from report import generateHtmlReport
|
||||||
|
|
||||||
|
|
||||||
def checkArguments():
|
def checkArguments():
|
||||||
@ -30,7 +32,10 @@ def main():
|
|||||||
sysctl = Sysctl()
|
sysctl = Sysctl()
|
||||||
sysctl.runAudit()
|
sysctl.runAudit()
|
||||||
|
|
||||||
|
# Getting reports
|
||||||
report['sysctl'] = sysctl.getReports()
|
report['sysctl'] = sysctl.getReports()
|
||||||
|
|
||||||
|
generateHtmlReport(report)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
51
parsing/postfix.py
Normal file
51
parsing/postfix.py
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import re
|
||||||
|
from json import dumps
|
||||||
|
from parsing.base import ParsingBase
|
||||||
|
|
||||||
|
|
||||||
|
class Parsing(ParsingBase):
|
||||||
|
def __init__(self, objects):
|
||||||
|
self._parsing = dict()
|
||||||
|
self._reports = dict()
|
||||||
|
self._objects = objects
|
||||||
|
|
||||||
|
def runParsing(self):
|
||||||
|
# Generate report
|
||||||
|
self._constructReports()
|
||||||
|
|
||||||
|
|
||||||
|
print(self._reports)
|
||||||
|
|
||||||
|
def _parseFile(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _generateReport(self, objects):
|
||||||
|
# We can generate the report
|
||||||
|
for postfix in self._reports['postfix']:
|
||||||
|
self._reports['postfix'][postfix] = objects[postfix]
|
||||||
|
|
||||||
|
def _parsingFile(self, line, obj, vulnerabilityFound) -> bool:
|
||||||
|
"""
|
||||||
|
This function parse the line and try to find the item in it
|
||||||
|
"""
|
||||||
|
result = bool()
|
||||||
|
|
||||||
|
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
|
||||||
|
"""
|
||||||
|
self._reports['postfix'] = dict()
|
||||||
|
|
||||||
|
def getResults(self) -> dict:
|
||||||
|
return self._reports
|
@ -1,3 +1,5 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from json import dumps
|
from json import dumps
|
||||||
from parsing.base import ParsingBase
|
from parsing.base import ParsingBase
|
||||||
@ -10,38 +12,37 @@ class Parsing(ParsingBase):
|
|||||||
self._audit = audit
|
self._audit = audit
|
||||||
|
|
||||||
def runParsing(self):
|
def runParsing(self):
|
||||||
|
# Generate report
|
||||||
|
self._constructReports()
|
||||||
|
|
||||||
for audit in self._audit:
|
for audit in self._audit:
|
||||||
if audit['audit'] == 'file':
|
if audit['audit'] == 'file':
|
||||||
with open(audit['value'], 'rb') as fdata:
|
with open(audit['value'], 'rb') as fdata:
|
||||||
self._parseFile(fdata)
|
self._parseFile(fdata)
|
||||||
if audit['audit'] == 'process':
|
if audit['audit'] == 'process':
|
||||||
pass
|
self._parseProcess()
|
||||||
|
|
||||||
def _parseFile(self, fdata):
|
def _parseFile(self, fdata):
|
||||||
data = fdata.read()
|
data = fdata.read()
|
||||||
lines = data.splitlines()
|
lines = data.splitlines()
|
||||||
numLines = 1
|
numLines = 1
|
||||||
|
|
||||||
self._constructReports(filename='/etc/sysctl.conf')
|
|
||||||
|
|
||||||
vulnerabilityFound = dict()
|
vulnerabilityFound = dict()
|
||||||
|
|
||||||
# I create an array which contains all flag we need to find
|
# 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.
|
# 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
|
# If the array is empty, no entry found for a flag, otherwise, we check the value
|
||||||
for obj in self._objects['sysctl']:
|
for obj in self._objects:
|
||||||
vulnerabilityFound[obj['flag']] = dict()
|
vulnerabilityFound[obj['flag']] = dict()
|
||||||
vulnerabilityFound[obj['flag']]['recommand_value'] = obj['value']
|
vulnerabilityFound[obj['flag']]['recommand_value'] = obj['value']
|
||||||
vulnerabilityFound[obj['flag']]['occurence'] = 0
|
vulnerabilityFound[obj['flag']]['occurence'] = 0
|
||||||
for item in obj:
|
for item in obj:
|
||||||
vulnerabilityFound[obj['flag']][item] = obj[item]
|
vulnerabilityFound[obj['flag']][item] = obj[item]
|
||||||
|
|
||||||
print("")
|
|
||||||
|
|
||||||
for line in lines:
|
for line in lines:
|
||||||
line = line.decode("utf-8")
|
line = line.decode("utf-8")
|
||||||
|
|
||||||
for obj in self._objects['sysctl']:
|
for obj in self._objects:
|
||||||
result = self._parsingFile(line, obj, vulnerabilityFound)
|
result = self._parsingFile(line, obj, vulnerabilityFound)
|
||||||
if result:
|
if result:
|
||||||
vulnerabilityFound[obj['flag']]['lineNumber'] = numLines
|
vulnerabilityFound[obj['flag']]['lineNumber'] = numLines
|
||||||
@ -53,26 +54,32 @@ class Parsing(ParsingBase):
|
|||||||
# And check if the flag is specified and need to put on the sysctl config
|
# And check if the flag is specified and need to put on the sysctl config
|
||||||
for entry in vulnerabilityFound:
|
for entry in vulnerabilityFound:
|
||||||
obj = vulnerabilityFound[entry]
|
obj = vulnerabilityFound[entry]
|
||||||
self._reports[entry]['result'] = dict()
|
vulnerabilityFound[entry]['result'] = dict()
|
||||||
if obj['occurence'] > 0:
|
if obj['occurence'] > 0:
|
||||||
#print(entry)
|
#print(entry)
|
||||||
#print(obj)
|
#print(obj)
|
||||||
if obj['current_value'] != obj['recommand_value']:
|
if obj['current_value'] != obj['recommand_value']:
|
||||||
self._reports[entry]['result']['result'] = "failed"
|
vulnerabilityFound[entry]['result']['result'] = "failed"
|
||||||
#self._reports[entry]['message'] = \
|
|
||||||
# f"You specify this value {obj['current_value']}" \
|
|
||||||
# ", you should use this value {obj['recommand_value']}"
|
|
||||||
else:
|
else:
|
||||||
self._reports[entry]['result']['result'] = "failed"
|
vulnerabilityFound[entry]['result']['result'] = "success"
|
||||||
else:
|
else:
|
||||||
# No find the flag, we recommand to enable it
|
# No find the flag, we recommand to enable it
|
||||||
self._reports[entry]['result']['result'] = "failed"
|
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
|
# We can generate the report
|
||||||
print(self._reports)
|
for sysctl in self._reports['file']['sysctl']:
|
||||||
print("")
|
#self._reports['file']['sysctl'][sysctl] = vulnerabilityFound[sysctl]
|
||||||
from json import dumps
|
self._reports['file']['sysctl'][sysctl] = objects[sysctl]
|
||||||
print(dumps(vulnerabilityFound, indent=4))
|
|
||||||
|
|
||||||
def _parsingFile(self, line, obj, vulnerabilityFound) -> bool:
|
def _parsingFile(self, line, obj, vulnerabilityFound) -> bool:
|
||||||
"""
|
"""
|
||||||
@ -94,7 +101,7 @@ class Parsing(ParsingBase):
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def _constructReports(self, filename):
|
def _constructReports(self):
|
||||||
"""
|
"""
|
||||||
Construct dictionary for result of the tests
|
Construct dictionary for result of the tests
|
||||||
Each entry contains:
|
Each entry contains:
|
||||||
@ -105,12 +112,19 @@ class Parsing(ParsingBase):
|
|||||||
- description: description of the vulnerability
|
- description: description of the vulnerability
|
||||||
- level: high, medium or low
|
- level: high, medium or low
|
||||||
"""
|
"""
|
||||||
self._reports['filename'] = filename
|
# For file
|
||||||
|
self._reports['file'] = dict()
|
||||||
|
self._reports['file']['filename'] = self._audit[0]['value']
|
||||||
|
self._reports['file']['sysctl'] = dict()
|
||||||
|
|
||||||
for sysctl in self._objects['sysctl']:
|
# For process
|
||||||
self._reports[sysctl['flag']] = dict()
|
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:
|
def getResults(self) -> dict:
|
||||||
result = dict()
|
return self._reports
|
||||||
|
|
||||||
return result
|
|
||||||
|
31
report.py
31
report.py
@ -12,23 +12,26 @@ def generateHtmlReport(data):
|
|||||||
f"<h1>Reports of {today}</h1>"
|
f"<h1>Reports of {today}</h1>"
|
||||||
|
|
||||||
body = str()
|
body = str()
|
||||||
for project in data['projects']:
|
# For sysctl
|
||||||
body += f"<h2>{project['name']}</h2>"
|
for entry in data['sysctl']:
|
||||||
|
body += f"<h2>Sysctl</h2>"
|
||||||
|
|
||||||
# For python
|
# For file
|
||||||
body += f"<h3>Python</h3>"
|
body += f"<h3>File</h3>"
|
||||||
for py in project['python']:
|
for f in data['sysctl']['file']:
|
||||||
body += f"<h4>{py['file']}</h4>"
|
body += f"<h4>{data['sysctl']['file']['filename']}</h4>"
|
||||||
for vul in py['vulnerabilities']:
|
for vul in data['sysctl']['file']['sysctl']:
|
||||||
body += f"<h5>{vul['name']}</h5>"
|
#print(data['sysctl']['file']['sysctl'][vul])
|
||||||
|
body += f"<h5>{vul}</h5>"
|
||||||
body += f"<p>"
|
body += f"<p>"
|
||||||
body += f"Results:<br />"
|
body += f"Results:<br />"
|
||||||
for result in vul['results']:
|
#for result in data['sysctl']['file']['sysctl'][vul]:
|
||||||
body += f"Line: {result['lineNumber']}<br />"
|
# print(result)
|
||||||
body += f"Line: {result['line']}<br />"
|
# body += f"Line: {result['lineNumber']}<br />"
|
||||||
body += f"Level: {result['level']}<br />"
|
# body += f"Line: {result['line']}<br />"
|
||||||
body += f"Description: {result['description']}<br /><br />"
|
# body += f"Level: {result['level']}<br />"
|
||||||
body += f"</p>"
|
# body += f"Description: {result['description']}<br /><br />"
|
||||||
|
#body += f"</p>"
|
||||||
|
|
||||||
html += body
|
html += body
|
||||||
#print(body)
|
#print(body)
|
||||||
|
1
reports/reports_2023_06_07.html
Normal file
1
reports/reports_2023_06_07.html
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user