First commit

This commit is contained in:
geoffrey 2023-06-04 21:26:27 +02:00
commit 96342a2b2c
13 changed files with 488 additions and 0 deletions

2
.gitignore vendored Normal file

@ -0,0 +1,2 @@
__pycache__/
__pycache__/**

36
main.py Normal file

@ -0,0 +1,36 @@
#!/usr/bin/env python
from argparse import ArgumentParser
from sysctl import Sysctl
def checkArguments():
args = ArgumentParser(description="Check Gitlab repositories")
args.add_argument('-a', '--audit', help="Kind of audit", choices=['system', 'application'])
return args.parse_args()
def main():
args = checkArguments()
# If audit is not specified
if args.audit is None:
print("Please, you must specify the audit type")
exit(1)
# Report
report = dict()
report['system'] = None
# Audit application
if args.audit == "application":
pass
# Audit system
if args.audit == "system":
sysctl = Sysctl()
sysctl.runAudit()
report['sysctl'] = sysctl.getReports()
if __name__ == "__main__":
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()

41
parsing.py Normal file

@ -0,0 +1,41 @@
import re
from json import dumps
class Parsing:
def __init__(self, objects, audit):
self._parsing = dict()
self._results = dict()
self._objects = objects
self._audit = audit
def runParsing(self):
for audit in self._audit:
if audit['audit'] == 'file':
with open(audit['value'], 'rb') as fdata:
self._parseFile(fdata)
def _parseFile(self, fdata):
data = fdata.read()
lines = data.splitlines()
for line in lines:
self._parsingFile(line, self._objects['sysctl'])
def _parsingFile(self, line, item) -> dict:
"""
This function parse the line and try to find the item in it
"""
res = None
line = line.decode("utf-8")
for entry in item:
groupLine = re.search(entry['item'], line)
if groupLine:
sLine = line.split('=')
return res
def getResults(self) -> dict:
result = dict()
return result

1
parsing/__init__.py Normal file

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

21
parsing/base.py Normal file

@ -0,0 +1,21 @@
import re
from json import dumps
class ParsingBase:
def __init__(self, objects, audit):
pass
def runParsing(self):
pass
def _parseFile(self, fdata):
pass
def _parsingFile(self, line, item) -> dict:
"""
This function parse the line and try to find the item in it
"""
pass
def getResults(self) -> dict:
pass

97
parsing/sysctl.py Normal file

@ -0,0 +1,97 @@
import re
from json import dumps
from parsing.base import ParsingBase
class Parsing(ParsingBase):
def __init__(self, objects, audit):
self._parsing = dict()
self._results = dict()
self._objects = objects
self._audit = audit
def runParsing(self):
for audit in self._audit:
if audit['audit'] == 'file':
with open(audit['value'], 'rb') as fdata:
self._parseFile(fdata)
if audit['audit'] == 'process':
pass
def _parseFile(self, fdata):
data = fdata.read()
lines = data.splitlines()
numLines = 1
self._constructResults(filename='/etc/sysctl.conf')
for line in lines:
line = line.decode("utf-8")
for obj in self._objects['sysctl']:
result = self._parsingFile(line, obj)
if len(result) == 0:
pass
# If the flag is found
else:
# And if the current value is not setted corectly for the vulnerability
print(result)
self._results[obj['flag']].append({
'lineNumber': numLines,
'value': obj['value'],
'audit': 'failed' # Or success
})
if result['value'] != result['current_value']:
print(f"You must change the value to {obj['value']} for fixing the vulnerabilities")
numLines += 1
print(self._results)
def _parsingFile(self, line, obj) -> dict:
"""
This function parse the line and try to find the item in it
"""
result = dict()
groupLine = re.search(obj['flag'], line)
if groupLine:
# Avoid the comment
if not line.startswith('#'):
sLine = line.split('=')
flag = sLine[0]
value = int(sLine[1].strip(''))
#print(sLine)
result['found'] = flag
result['current_value'] = value
result['value'] = obj['value']
if value != obj['value']:
print("Need to change the value")
print(sLine)
return result
def _constructResults(self, filename):
"""
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 vulnerabilities
- level: high, medium or low
"""
self._results['filename'] = filename
for sysctl in self._objects['sysctl']:
self._results[sysctl['flag']] = list()
print(self._results)
print("")
def getResults(self) -> dict:
result = dict()
return result

38
report.py Normal file

@ -0,0 +1,38 @@
#!/usr/bin/env python3
from datetime import datetime
def generateHtmlReport(data):
today = datetime.now().isoformat()[0:10].replace("-", "_")
html = "<!doctype html>" \
"<html>" \
"<head>" \
"</head>" \
"<body>" \
f"<h1>Reports of {today}</h1>"
body = str()
for project in data['projects']:
body += f"<h2>{project['name']}</h2>"
# For python
body += f"<h3>Python</h3>"
for py in project['python']:
body += f"<h4>{py['file']}</h4>"
for vul in py['vulnerabilities']:
body += f"<h5>{vul['name']}</h5>"
body += f"<p>"
body += f"Results:<br />"
for result in vul['results']:
body += f"Line: {result['lineNumber']}<br />"
body += f"Line: {result['line']}<br />"
body += f"Level: {result['level']}<br />"
body += f"Description: {result['description']}<br /><br />"
body += f"</p>"
html += body
#print(body)
html += "</body></html>"
with open(f"reports/reports_{today}.html", "w") as f:
f.write(html)

39
sysctl.py Normal file

@ -0,0 +1,39 @@
#!/usr/bin/env python3
from parsing.sysctl import Parsing
from vulnerabilities.system import system
from vulnerabilities.sysctl import sysctl
class Sysctl:
def __init__(self):
self._objects = dict()
self._reports = list()
self._audit = list()
self._audit.append({
'audit': 'file',
'value': '/etc/sysctl.conf',
})
self._audit.append({
'audit': 'process',
'value': 'sysctl -a',
})
self._sysctl()
self._parsing = Parsing(self._objects, self._audit)
def _sysctl(self):
self._objects['sysctl'] = sysctl()
def runAudit(self):
# Read /etc/sysctl.conf
self._parsing.runParsing()
self._reports.append(self._parsing.getResults())
# Run process sysctl
def getReports(self) -> list:
return self._reports

27
utils.py Normal file

@ -0,0 +1,27 @@
#!/usr/bin/env python3
import re
from subprocess import run
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 getKernelVersion():
"""
This function get the kernel version Linux
"""
kernelVers = run(['/usr/bin/uname', '-r'])
return kernelVers.stdout

33
vulnerabilities/calls.py Normal file

@ -0,0 +1,33 @@
#!/usr/bin/env python3
def calls() -> list:
calls = list()
# https://cwe.mitre.org/data/definitions/78.html
# For commoand injections
calls.append({
"call": "exec",
"description": "",
"level": "high"
})
calls.append({
"call": "chown",
"description": "",
"level": "high"
})
calls.append({
"call": "chmod",
"description": "",
"level": "high"
})
calls.append({
"call": "rsync",
"description": "",
"level": "high"
})
calls.append({
"call": "wrap_socket",
"description": "This functions is deprecated. You must use SSLContext.wrap_context",
"level": "high"
})
return calls

29
vulnerabilities/sysctl.py Normal file

@ -0,0 +1,29 @@
#!/usr/bin/env python3
def sysctl() -> list:
sysctl = list()
# https://access.redhat.com/security/sysctl/sysctl-2023-0179
sysctl.append({
"cve": "cve-2023-0179",
"description": "",
"flag": "kernel.unprivileged_userns_clone",
"value": 0,
"level": "medium",
"affectedSystem": ({
'linux': "Debian",
'release': 'buster',
'kernel': '4.19.249-2'
})
})
# Best practice from CIS
sysctl.append({
"cve": "",
"description": "Disable IPv4 forwarding",
"flag": "net.ipv4.conf.all.forwarding",
"value": 0,
"level": "medium"
})
return sysctl

@ -0,0 +1,6 @@
#!/usr/bin/env python3
def system() -> list:
system = list()
return system