Browse Source

initial commit

main
Krenz Simon 6 months ago
parent
commit
4e5da6d43b
Signed by: simon.krenz GPG Key ID: 7C31567E0836428D
  1. 141
      modules/.gitignore
  2. 0
      modules/__init__.py
  3. 23
      modules/constant.py-example
  4. 145
      modules/helper.py
  5. 185
      modules/openvas.py
  6. 2
      requirements.txt
  7. 42
      run.py

141
modules/.gitignore

@ -0,0 +1,141 @@
# ---> Python
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
constant.py

0
modules/__init__.py

23
modules/constant.py-example

@ -0,0 +1,23 @@
# ENABLE DEBUG
DEBUG = False
# API URL
OPENVAS_API_URL = ""
OPENVAS_API_PORT = ""
# CREADENTIALS
OPENVAS_BASIC_AUTH_USER = ""
OPENVAS_BASIC_AUTH_PASS = ""
OPENVAS_USERNAME = ""
OPENVAS_PASSWORD = ""
# HEADERS
HEADER_ACCEPT = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"
HEADER_ACCEPT_ENCODING = "gzip, deflate, br"
HEADER_ACCEPT_LANGUAGE = "en-US,en;q=0.8"
HEADER_CACHE_CONTROL = "max-age=0"
HEADER_CONNECTION = "keep-alive"
HEADER_CONTENT_TYPE = "application/x-www-form-urlencoded"
HEADER_USER_AGENT = "OpenVAS Zammad API connector"
HEADER_X_REQUESTED_WITH = "XMLHttpRequest"

145
modules/helper.py

@ -0,0 +1,145 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# openvas.py
#
# Copyright (c) 2021 Simon Krenz
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; Applies version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
__version__ = '0.1'
__author__ = 'Simon Krenz'
from . import constant
import http.client
import logging
import requests
from requests.auth import HTTPBasicAuth
from requests.exceptions import HTTPError
class Helper:
def __init__(self):
self.logger = logging.getLogger('Helper_Class')
self.logger.propagate = True
if constant.DEBUG:
self.logger.setLevel(logging.DEBUG)
def _get_request(self, url: str, basic_auth: bool, params=dict(), headers=dict(), cookies=dict()):
"""Will send a GET request to the url parameter.
:param url: the url where the request should go to
:type url: str
:param basic_auth: whether basic auth should be used or not
:type basic_auth: bool
:param params: parameters which should be used for GET request
:type params: dict
:param headers: the header which should be used
:type headers: dict
:returns: the content of the response
:rtype: object
"""
if constant.DEBUG:
http.client.HTTPConnection.debuglevel = 1
try:
if params:
if basic_auth:
r = requests.get(
url,
cookies=cookies,
headers=headers,
params=params,
auth=HTTPBasicAuth(
constant.OPENVAS_BASIC_AUTH_USER,
constant.OPENVAS_BASIC_AUTH_PASS
)
)
else:
r = requests.get(
url,
cookies=cookies,
headers=headers,
params=params,
)
else:
if basic_auth:
r = requests.get(
url,
cookies=cookies,
headers=headers,
auth=HTTPBasicAuth(
constant.OPENVAS_BASIC_AUTH_USER,
constant.OPENVAS_BASIC_AUTH_PASS
)
)
else:
r = requests.get(
url,
cookies=cookies,
headers=headers,
)
r.raise_for_status()
except HTTPError as http_err:
print(f'HTTP error occurred: {http_err}')
except Exception as err:
print(f'Other error occured: {err}')
else:
return r
def _post_request(self, url: str, basic_auth: bool, data=dict(), headers=dict()):
"""Will send a POST request to the url parameter.
:param url: the url where the request should go to
:type url: str
:param basic_auth: whether basic auth should be used or not
:type basic_auth: bool
:param data: the data which should be send via POST
:type data: dict
:param headers: the header which should be used
:type headers: dict
:returns: the content of the response
:rtype: object
"""
if constant.DEBUG:
http.client.HTTPConnection.debuglevel = 1
try:
if basic_auth:
r = requests.post(
url,
headers=headers,
data=data,
auth=HTTPBasicAuth(
constant.OPENVAS_BASIC_AUTH_USER,
constant.OPENVAS_BASIC_AUTH_PASS
)
)
else:
r = requests.post(
url,
headers=headers,
data=data,
)
r.raise_for_status()
except HTTPError as http_err:
print(f'HTTP error occurred: {http_err}')
except Exception as err:
print(f'Other error occured: {err}')
else:
return r

185
modules/openvas.py

@ -0,0 +1,185 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# openvas.py
#
# Copyright (c) 2021 Simon Krenz
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; Applies version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
__version__ = '0.1'
__author__ = 'Simon Krenz'
from .helper import Helper
from . import constant
from bs4 import BeautifulSoup
import logging
class OpenVAS:
def __init__(self,
hostname=None,
port=None,
basic_auth_user=None,
basic_auth_pass=None,
username=None,
password=None):
self.logger = logging.getLogger('OpenVAS_API')
if constant.DEBUG:
self.logger.setLevel(logging.DEBUG)
if basic_auth_user is None or basic_auth_pass is None:
raise Exception('[ERROR] Missing basic auth username or password.')
if username is None or password is None:
raise Exception('[ERROR] Missing username or password.')
self.basename = hostname
self.baseurl = f"https://{hostname}:{port}"
self.basic_auth = True
self.basic_auth_user = basic_auth_user
self.basic_auth_pass = basic_auth_pass
self.username = username
self.password = password
self.helper = Helper()
self.xml_reports = dict()
self.headers = {
'Accept': constant.HEADER_ACCEPT,
'Accept-Encoding': constant.HEADER_ACCEPT_ENCODING,
'Accept-Language': constant.HEADER_ACCEPT_LANGUAGE,
'Cache-Control': constant.HEADER_CACHE_CONTROL,
'Connection': constant.HEADER_CONNECTION,
'Content-Type': constant.HEADER_CONTENT_TYPE,
'User-Agent': constant.HEADER_USER_AGENT,
'X-Requested-With': constant.HEADER_X_REQUESTED_WITH,
}
self.login()
self._get_report_format_ids()
def _login_token(self):
"""Get the OpenVAS auth token and cookies and sets them to self
:returns: self.token and self.cookies
"""
data = {
'cmd': 'login',
'login': self.username,
'password': self.password,
}
token = self.helper._post_request(
self.basename,
self.basic_auth,
data,
self.headers)
if token.status_code == 200:
xml_response = BeautifulSoup(token.content, 'lxml')
self.token = xml_response.find('token').get_text()
self.cookies = token.cookies.get_dict()
else:
raise Exception('[FAIL] Could not login to OpenVAS')
def login(self):
"""Calls _login_token to set auth token and cookies
"""
r = self._login_token()
def _get_report_format_ids(self):
"""Retrieves existent report formats.
"""
self.logger.info('[INFO] Retrieving all available OpenVAS report formats...')
params = {
'cmd': 'get_report_formats',
'token': self.token,
}
url = self.basename + "/gmp"
r = self.helper._get_request(
url,
self.basic_auth,
params,
self.headers,
self.cookies)
if r.status_code == 200:
xml_response = BeautifulSoup(r.content, 'lxml')
formats_xml = xml_response.find_all('report_format')
for report in formats_xml:
if report.findChild('name', recursive=False).text == 'XML':
self.xml_report_id = report.get('id')
if report.findChild('name', recursive=False).text == 'CSV Results':
self.csv_report_id = report.get('id')
else:
raise Exception('[FAIL] Could not get report formats from OpenVAS')
print(self.csv_report_id)
def get_xml_reports(self):
"""Retrieves all existent XML based reports and lists them
"""
self.logger.info('[INFO] Retrieving all existing OpenVAS reports...')
params = {
'cmd': 'get_reports',
'token': self.token,
'details': 0,
'filter': 'sort-reverse=date first=1 rows=10'
}
url = self.basename + "/gmp"
r = self.helper._get_request(
url,
self.basic_auth,
params,
self.headers,
self.cookies)
if r.status_code == 200:
xml_response = BeautifulSoup(r.content, 'lxml')
reports_xml = xml_response.find_all('report', {
'extension':'xml',
'format_id': self.xml_report_id})
for report in reports_xml:
self.xml_reports[report.get('id')] = dict()
self.xml_reports[report.get('id')] = {
'name': report.findChild('name', recursive=False).get_text(),
'hosts': report.findChild('hosts').get_text(),
'vulns': report.findChild('vulns').get_text(),
'high': report.findChild('hole').findChild('full').get_text(),
'medium': report.findChild('warning').findChild('full').get_text(),
'low': report.findChild('info').findChild('full').get_text(),
'log': report.findChild('log').findChild('full').get_text(),
'severity': report.findChild('severity').findChild('full').get_text(),
}
else:
raise Exception('[FAIL] Could not get reports from OpenVAS')
def get_report(self, report_id: str):
"""Retrieves a specific report by id
"""
self.logger.info(f'[INFO] Retrieving OpenVAS report {report_id}...')
params = {
'cmd': 'get_report',
'token': self.token,
'report_id': report_id,
'filter': 'apply_overrides=0 min_qod=70 autofp=0 levels=hml first=1 rows=0 sort-reverse=severity',
'ignore_pagination': 1,
'report_format_id': self.csv_report_id,
'submit': 'Download',
}

2
requirements.txt

@ -0,0 +1,2 @@
bs4
requests

42
run.py

@ -0,0 +1,42 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# openvas.py
#
# Copyright (c) 2021 Simon Krenz
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; Applies version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
__version__ = '0.1'
__author__ = 'Simon Krenz'
from modules.openvas import OpenVAS
import modules.constant as constant
def main():
"""The main function
"""
openvas = OpenVAS(
constant.OPENVAS_API_URL,
constant.OPENVAS_API_PORT,
constant.OPENVAS_BASIC_AUTH_USER,
constant.OPENVAS_BASIC_AUTH_PASS,
constant.OPENVAS_USERNAME,
constant.OPENVAS_PASSWORD)
openvas.get_xml_reports()
if __name__ == "__main__":
main()
Loading…
Cancel
Save