From f568d0137d97f91dbaafae62d1cfd109bba41880 Mon Sep 17 00:00:00 2001 From: ziirish Date: Thu, 16 Jun 2016 14:07:02 +0200 Subject: [PATCH] Add new local authentication backend thanks to @nhathaway (closes #130) --- CHANGELOG.rst | 5 +- CONTRIBUTORS | 1 + burpui/misc/auth/local.py | 118 +++++++++++++++++++++++++++++ docs/requirements.rst | 11 +++ setup.py | 1 + share/burpui/etc/burpui.sample.cfg | 10 +++ 6 files changed, 144 insertions(+), 2 deletions(-) create mode 100644 burpui/misc/auth/local.py diff --git a/CHANGELOG.rst b/CHANGELOG.rst index d90de277..b4fd2d09 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,9 +4,10 @@ Changelog Current ------- -- **BREAKING**: New configuration file format to allow further improvements (The conversion is automatic) -- **BREAKING**: Passwords are now *salted* for the *BASIC* authentication backend +- **BREAKING**: New configuration file format to allow further improvements (The conversion is automatic, but LDAP settings might need some attention) +- **BREAKING**: Passwords are now *salted* for the *BASIC* authentication backend (The conversion is automatic too) - Add: `client certificate revocation `_ +- Add: new `local authentication backend `_ - Fix: issue `#134 `_ - Fix: issue `#135 `_ - `Full changelog `__ diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 95813631..aa348adc 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -4,6 +4,7 @@ Sorted by surname (or nickname). bedaes Wade Fitzpatrick +Nigel Hathaway Graham Keeling (main author of Burp) larsen0815 Benjamin SANS (main author) diff --git a/burpui/misc/auth/local.py b/burpui/misc/auth/local.py new file mode 100644 index 00000000..89a621c3 --- /dev/null +++ b/burpui/misc/auth/local.py @@ -0,0 +1,118 @@ +# -*- coding: utf8 -*- +import pam + +from .interface import BUIhandler, BUIuser, BUIloader + + +class LocalLoader(BUIloader): + """The :class:`burpui.misc.auth.local.LocalLoader` class loads the *Local* + users. + """ + section = name = 'LOCAL' + + def __init__(self, app=None, handler=None): + """:func:`burpui.misc.auth.Local.localLoader.__init__` loads users from + the configuration file. + + :param app: Instance of the app we are running in + :type app: :class:`burpui.server.BUIServer` + """ + self.app = app + self.users = None + conf = self.app.conf + if self.section in conf.options: + # Maybe the handler argument is None, maybe the 'priority' + # option is missing. We don't care. + try: + handler.priority = conf.safe_get( + 'priority', + 'integer', + section=self.section + ) or 0 + except: + pass + users = conf.safe_get( + 'users', + cast='force_list', + section=self.section + ) + if users != [None]: + self.users = users + self.logger.debug('Local users: ' + str(self.users)) + + def fetch(self, uid=None): + """:func:`burpui.misc.auth.local.LocalLoader.fetch` searches for a user + in the configuration. + + :param uid: User to search for + :type uid: str + + :returns: The given UID if the user exists or None + """ + if self.users is None or uid in self.users: + return uid + + return None + + def check(self, uid=None, passwd=None): + """:func:`burpui.misc.auth.local.LocalLoader.check` verifies if the + given password matches the given user settings. + + :param uid: User to authenticate + :type uid: str + + :param passwd: Password + :type passwd: str + + :returns: True if there is a match, otherwise False + """ + if self.users is None or uid in self.users: + return pam.authenticate(uid, passwd, 'other') + + return False + + +class UserHandler(BUIhandler): + """See :class:`burpui.misc.auth.interface.BUIhandler`""" + def __init__(self, app=None, auth=None): + """See :func:`burpui.misc.auth.interface.BUIhandler.__init__`""" + self.local = LocalLoader(app, self) + self.users = {} + + def user(self, name=None): + """See :func:`burpui.misc.auth.interface.BUIhandler.user`""" + if name not in self.users: + self.users[name] = LocalUser(self.local, name) + return self.users[name] + + +class LocalUser(BUIuser): + """See :class:`burpui.misc.auth.interface.BUIuser`""" + def __init__(self, local=None, name=None): + self.active = False + self.authenticated = False + self.local = local + self.name = name + self.id = None + + res = self.local.fetch(self.name) + + if res: + self.id = res + self.active = True + + def login(self, passwd=None): + """See :func:`burpui.misc.auth.interface.BUIuser.login`""" + self.authenticated = self.local.check(self.name, passwd) + return self.authenticated + + @property + def is_active(self): # pragma: no cover + return self.active + + @property + def is_authenticated(self): # pragma: no cover + return self.authenticated + + def get_id(self): + return self.id diff --git a/docs/requirements.rst b/docs/requirements.rst index 657eb4cc..233ead0f 100644 --- a/docs/requirements.rst +++ b/docs/requirements.rst @@ -39,6 +39,17 @@ them using the following command: pip install "burp-ui[ldap_authentication]" +Local +----- + +For Local authentication (optional), we need extra dependencies as well. You can +install them using the following command: + +:: + + pip install "burpui[local_authentication]" + + SSL --- diff --git a/setup.py b/setup.py index 7d770b5b..4e178f3f 100755 --- a/setup.py +++ b/setup.py @@ -226,6 +226,7 @@ setup( extras_require={ 'ssl': ['pyOpenSSL'], 'ldap_authentication': ['ldap3'], + 'local_authentication': ['pam'], 'extra': ['ujson'], 'gunicorn': ['gevent'], 'gunicorn-extra': ['redis', 'Flask-Session'], diff --git a/share/burpui/etc/burpui.sample.cfg b/share/burpui/etc/burpui.sample.cfg index 885a0c66..c0ff8b0e 100644 --- a/share/burpui/etc/burpui.sample.cfg +++ b/share/burpui/etc/burpui.sample.cfg @@ -165,6 +165,16 @@ zip64 = false #admin = password #user1 = otherpassword +## localauth specific options +## Note: if not running as root, then burp-ui must be run as group 'shadow' to +## allow PAM to work +#[LOCAL] +## Backend priority. Higher is first +#priority: 3 +## List of local users allowed to login. If you don't set this setting, every +## local user will be able to login +#users: user1,user2 + ## basicacl specific options ## Note: in case you leave this section commented, the user 'admin' will have ## access to all clients whereas other users will only see the client that have