burp-ui/burpui/misc/audit/handler.py
ziirish ec47a55131
improve audit logger
- Transparently log user details
- Add log origin
2018-08-14 18:12:25 +02:00

99 lines
3.5 KiB
Python

# -*- coding: utf8 -*-
import os
import inspect
from .interface import BUIaudit, BUIauditLogger as BUIauditLoggerInterface
from importlib import import_module
from collections import OrderedDict
from flask_login import current_user
class BUIauditLoader(BUIaudit):
"""See :class:`burpui.misc.audit.interface.BUIaudit`"""
def __init__(self, app=None):
"""See :func:`burpui.misc.audit.interface.BUIaudit.__init__`
:param app: Instance of the app we are running in
:type app: :class:`burpui.engines.server.BUIServer`
"""
self.app = app
backends = []
self.errors = {}
if self.app.audit_backends and 'none' not in self.app.audit_backends:
me, _ = os.path.splitext(os.path.basename(__file__))
back = self.app.audit_backends
for au in back:
if au == me:
self.app.logger.critical('Recursive import not permitted!')
continue
try:
(modpath, _) = __name__.rsplit('.', 1)
mod = import_module('.' + au, modpath)
obj = mod.BUIauditLoader(self.app)
backends.append(obj)
except:
import traceback
self.errors[au] = traceback.format_exc()
for name, plugin in self.app.plugin_manager.get_plugins_by_type('audit').items():
try:
obj = plugin.BUIauditLoader(self.app)
backends.append(obj)
except:
import traceback
self.errors[name] = traceback.format_exc()
backends.sort(key=lambda x: getattr(x, 'priority', -1), reverse=True)
if not backends and self.app.audit_backends and 'none' not in self.app.audit_backends:
raise ImportError(
'No backend found for \'{}\':\n{}'.format(self.app.audit_backends,
self.errors)
)
for name, err in self.errors.items():
self.app.logger.error(
'Unable to load module {}:\n{}'.format(repr(name), err)
)
self.backends = OrderedDict()
for obj in backends:
self.backends[obj.name] = obj
self._logger = BUIauditLogger(self)
@property
def logger(self) -> BUIauditLoggerInterface:
return self._logger
class BUIauditLogger(BUIauditLoggerInterface):
def __init__(self, loader):
self.loader = loader
def log(self, level, message, *args, **kwargs):
server_log = ''
if 'server' in kwargs:
server = kwargs['server']
del kwargs['server']
if server:
server_log = f' on {server}'
if current_user and not current_user.is_anonymous:
msg = f'{current_user} -> {message}{server_log}'
else:
msg = f'{message}{server_log}'
caller = ''
stack = inspect.stack()
exclude = [
'interface.py',
'handler.py',
]
for frame in stack:
if any([frame.filename.endswith(x) for x in exclude]):
continue
caller = f'{frame.function} [{frame.filename}:{frame.lineno}]'
break
if 'extra' in kwargs and isinstance(kwargs['extra'], dict):
kwargs['extra']['from'] = caller
else:
kwargs['extra'] = {
'from': caller
}
for back in self.loader.backends.values():
back.logger.log(level, msg, *args, **kwargs)