Crash on local authentication
Hello,
I have some trouble with Burp-UI right now. Here is a bug report:
Bug summary
Unable to login: Internal server error
Burp
$ burp -v
burp-2.2.18
Sysinfo
$ bui-manage sysinfo
Python version: 3.8.5
Burp-UI version: 0.6.6 (stable)
OS: Linux:5.4.65-216 (posix)
Traceback (most recent call last):
File "/usr/local/bin/flask", line 8, in <module>
sys.exit(main())
File "/usr/local/lib/python3.8/dist-packages/flask/cli.py", line 513, in main
cli.main(args=args, prog_name=name)
File "/usr/local/lib/python3.8/dist-packages/flask/cli.py", line 380, in main
return AppGroup.main(self, *args, **kwargs)
File "/usr/lib/python3/dist-packages/click/core.py", line 717, in main
rv = self.invoke(ctx)
File "/usr/lib/python3/dist-packages/click/core.py", line 1137, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/usr/lib/python3/dist-packages/click/core.py", line 956, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/usr/lib/python3/dist-packages/click/core.py", line 555, in invoke
return callback(*args, **kwargs)
File "/usr/lib/python3/dist-packages/click/decorators.py", line 17, in new_func
return f(get_current_context(), *args, **kwargs)
File "/usr/local/lib/python3.8/dist-packages/flask/cli.py", line 257, in decorator
return __ctx.invoke(f, *args, **kwargs)
File "/usr/lib/python3/dist-packages/click/core.py", line 555, in invoke
return callback(*args, **kwargs)
File "/usr/local/lib/python3.8/dist-packages/burpui/cli.py", line 1068, in sysinfo
log('Distribution: {} {} {}'.format(*platform.dist()))
AttributeError: module 'platform' has no attribute 'dist'
(It's Ubuntu 20.04 on armhf, by the way)
Steps to reproduce
- Go to the login page
- Try to authenticate
- Authentication fail with a HTTP 500 Error
logs
Traceback (most recent call last)
File "/usr/local/lib/python3.8/dist-packages/flask/app.py", line 1997, in __call__
return self.wsgi_app(environ, start_response)
File "/usr/local/lib/python3.8/dist-packages/burpui/utils.py", line 358, in __call__
return self.wsgi_app(environ, start_response)
File "/usr/local/lib/python3.8/dist-packages/flask/app.py", line 1985, in wsgi_app
response = self.handle_exception(e)
File "/usr/local/lib/python3.8/dist-packages/flask_restplus/api.py", line 557, in error_router
return original_handler(e)
File "/usr/local/lib/python3.8/dist-packages/flask/app.py", line 1540, in handle_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python3.8/dist-packages/flask/_compat.py", line 33, in reraise
raise value
File "/usr/local/lib/python3.8/dist-packages/flask/app.py", line 1982, in wsgi_app
response = self.full_dispatch_request()
File "/usr/local/lib/python3.8/dist-packages/flask/app.py", line 1614, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/usr/local/lib/python3.8/dist-packages/flask_restplus/api.py", line 557, in error_router
return original_handler(e)
File "/usr/local/lib/python3.8/dist-packages/flask/app.py", line 1517, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python3.8/dist-packages/flask/_compat.py", line 33, in reraise
raise value
File "/usr/local/lib/python3.8/dist-packages/flask/app.py", line 1612, in full_dispatch_request
rv = self.dispatch_request()
File "/usr/local/lib/python3.8/dist-packages/flask/app.py", line 1598, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/usr/local/lib/python3.8/dist-packages/burpui/routes.py", line 500, in login
if user and user.is_active and user.login(form.password.data):
File "/usr/local/lib/python3.8/dist-packages/burpui/misc/auth/handler.py", line 306, in login
self.authenticated = self.real.login(passwd)
File "/usr/local/lib/python3.8/dist-packages/burpui/misc/auth/local.py", line 136, in login
self.authenticated = self.local.check(self.name, passwd)
File "/usr/local/lib/python3.8/dist-packages/burpui/misc/auth/local.py", line 89, in check
return authenticate(uid, passwd)
File "/usr/local/lib/python3.8/dist-packages/burpui/misc/auth/local.py", line 334, in authenticate
retval = PAM_START(service, username, pointer(conv), pointer(handle))
ctypes.ArgumentError: argument 1: <class 'TypeError'>: wrong type
Configuration
[Global]
# burp backend to load either one of 'burp1', 'burp2', 'parallel' or 'multi'.
# If you choose 'multi', you will have to declare at lease one 'Agent' section.
# If you choose 'parallel', you need to configure the [Parallel] section.
# If you choose either 'burp1' or 'burp2', you need to configure the [Burp]
# section.
# The [Burp] section is also used with the 'parallel' backend for the restoration
# process.
# You can also use whatever custom backend you like if it is located in the
# 'plugins' directory and if it implements the right interface.
backend = multi
# authentication plugin (mandatory)
# list the misc/auth directory to see the available backends
# to disable authentication you can set "auth = none"
# you can also chain multiple backends. Example: "auth = ldap,basic"
# the order will be respected unless you manually set a higher backend priority
auth = local
# acl plugin (chainable, see 'auth' plugin option)
# list misc/acl directory to see the available backends
# default is no ACL
acl = none
# audit logger plugin (chainable, see 'auth' plugin option)
# list the misc/audit directory to see the available backends
# default is no audit log
audit = basic
# list of paths to look for external plugins
plugins = none
prefix = /burp
[UI]
# refresh interval of the pages in seconds
refresh = 180
# refresh interval of the live-monitoring page in seconds
liverefresh = 5
# list of labels to ignore (you can use regex)
ignore_labels = "color:.*", "custom:.*"
# format label using sed-like syntax
format_labels = "s/^os:\s*//"
# default strip leading path value for file restorations
default_strip = 0
[Production]
# storage backend for session and cache
# may be either 'default' or 'redis'
storage = default
# session database to use
# may also be a backend url like: redis://localhost:6379/0
# if set to 'redis', the backend url defaults to:
# redis://<redis_host>:<redis_port>/0
# where <redis_host> is the host part, and <redis_port> is the port part of
# the below "redis" setting
session = default
# cache database to use
# may also be a backend url like: redis://localhost:6379/0
# if set to 'redis', the backend url defaults to:
# redis://<redis_host>:<redis_port>/1
# where <redis_host> is the host part, and <redis_port> is the port part of
# the below "redis" setting
cache = default
# redis server to connect to
redis = localhost:6379
# whether to use celery or not
# may also be a broker url like: redis://localhost:6379/0
# if set to "true", the broker url defaults to:
# redis://<redis_host>:<redis_port>/2
# where <redis_host> is the host part, and <redis_port> is the port part of
# the above "redis" setting
celery = false
# whether to rate limit the API or not
# may also be a redis url like: redis://localhost:6379/0
# if set to "true" or "redis" or "default", the url defaults to:
# redis://<redis_host>:<redis_port>/3
# where <redis_host> is the host part, and <redis_port> is the port part of
# the above "redis" setting
# Note: the limiter only applies to the API routes
limiter = false
# limiter ratio
# see https://flask-limiter.readthedocs.io/en/stable/#ratelimit-string
ratio = 60/minute
# database url to store some persistent data
# none or a connect string supported by SQLAlchemy:
# http://docs.sqlalchemy.org/en/latest/core/engines.html#database-urls
# example: sqlite:////var/lib/burpui/store.db
database = none
# you can change the prefix if you are behind a reverse-proxy under a custom
# root path. For example: /burpui
# You can also configure your reverse-proxy to announce the prefix through the
# 'X-Script-Name' header. In this case, the bellow prefix will be ignored in
# favour of the one announced by your reverse-proxy
prefix = /burp
# ProxyFix
# number of reverse-proxy to trust in order to retrieve some HTTP headers
# All the details can be found here:
# https://werkzeug.palletsprojects.com/en/0.15.x/middleware/proxy_fix/#module-werkzeug.middleware.proxy_fix
num_proxies = 0
# alternatively, you can specify your own ProxyFix args.
# The default is: "{'x_proto': {num_proxies}, 'x_for': {num_proxies}, 'x_host': {num_proxies}, 'x_prefix': {num_proxies}}"
# if num_proxies > 0, else it defaults to ProxyFix defaults
proxy_fix_args = "{'x_proto': {num_proxies}, 'x_for': {num_proxies}, 'x_host': {num_proxies}, 'x_prefix': {num_proxies}}"
[WebSocket]
## This section contains WebSocket server specific options.
# whether to enable websocket or not
enabled = true
# whether to embed the websocket server or not
# if set to "true", you should have only *one* gunicorn worker
# see here for details:
# https://flask-socketio.readthedocs.io/en/latest/#gunicorn-web-server
embedded = false
# what broker to use to interact between websocket servers
# may be a redis url like: redis://localhost:6379/0
# if set to "true" or "redis" or "default", the url defaults to:
# redis://<redis_host>:<redis_port>/4
# where <redis_host> is the host part, and <redis_port> is the port part of
# the above "redis" setting
# set this to none to disable the broker
broker = redis
# if you choose to run a dedicated websocket server (with embedded = false)
# you can specify here the websocket url. You'll need to double quote your
# string though.
# example:
# url = "document.domain + ':5001'"
url = none
# whether to enable verbose websocket server logs or not (for development)
debug = false
[Experimental]
## This section contains some experimental features that have not been deeply
## tested yet
# enable zip64 feature. Python doc says:
# « ZIP64 extensions are disabled by default because the default zip and unzip
# commands on Unix (the InfoZIP utilities) don’t support these extensions. »
zip64 = false
[Security]
## This section contains some security options. Make sure you understand the
## security implications before changing these.
# list of 'root' paths allowed when sourcing files in the configuration.
# Set this to 'none' if you don't want any restrictions, keeping in mind this
# can lead to accessing sensible files. Defaults to '/etc/burp'.
# Note: you can have several paths separated by comas.
# Example: /etc/burp,/etc/burp.d
includes = /etc/burp
# if files already included in config do not respect the above restriction, we
# prune them
enforce = false
# enable certificates revocation
revoke = true
# remember_cookie duration in days
cookietime = 14
# whether to use a secure cookie for https or not. If set to false, cookies
# won't have the 'secure' flag.
# This setting is only useful when HTTPS is detected
scookie = true
# application secret to secure cookies. If you don't set anything, the default
# value is 'random' which will generate a new secret after every restart of your
# application. You can also set it to 'none' although this is not recommended.
appsecret = random
# burp backend specific options
[Burp]
# burp status address (can only be '127.0.0.1' or '::1')
bhost = ::1
# burp status port
bport = 4972
# burp binary
burpbin = /usr/sbin/burp
# vss_strip binary
stripbin = /usr/sbin/vss_strip
# burp client configuration file used for the restoration
bconfcli = /etc/burp/burp.conf
# burp server configuration file used for the setting page
bconfsrv = /etc/burp/burp-server.conf
# temporary directory to use for restoration
tmpdir = /tmp/bui
# how many time to wait for the monitor to answer (in seconds)
timeout = 15
# since burp-2.1.10, timestamps have local offsets, if we detect a burp-server
# version greater than 2.1.10 we'll suppose every backup was made with that
# version. If this is not the case, you may end-up with wrongly computed backup
# dates in the clients overview. For that reason, you can enable the
# 'deep_inspection' option which will check every backup logs in order to
# find out which server version was used.
# The drawback is this process requires some extra work that may slow-down
# burp-ui.
deep_inspection = false
## ldapauth specific options
#[LDAP]
## Backend priority. Higher is first
#priority = 50
## LDAP host
#host = 127.0.0.1
## LDAP port
#port = 389
## Encryption type to LDAP server (none, ssl or tls)
## - try tls if unsure, otherwise ssl on port 636
#encryption = ssl
## specifies if the server certificate must be validated, values can be:
## - none (certificates are ignored)
## - optional (not required, but validated if provided)
## - required (required and validated)
#validate = none
## SSL or TLS version to use, can be one of the following:
## - SSLv2
## - SSLv3
## - SSLv23
## - TLSv1
## - TLSv1_1 (Available only with openssl version 1.0.1+, requires python 2.7.9 or higher)
#version = TLSv1
## the file containing the certificates of the certification authorities
#cafile = none
## Attribute to use when searching the LDAP repository
##searchattr = sAMAccountName
#searchattr = uid
## LDAP filter to find users in the LDAP repository
## - {0} will be replaced by the search attribute
## - {1} will be replaced by the login name
##filter = (&({0}={1})(burpui=1))
##filter = (&({0}={1})(|(userAccountControl=512)(userAccountControl=66048)))
## LDAP base (quotes are mandatory)
#base = "ou=users,dc=example,dc=com"
## Binddn to list existing users (quotes are mandatory)
#binddn = "cn=admin,dc=example,dc=com"
## Bindpw to list existing users
#bindpw = Sup3rS3cr3tPa$$w0rd
## basicauth specific options
## Note: in case you leave this section commented, the default login/password
## is admin/admin
#[BASIC]
## Backend priority. Higher is first
#priority = 100
#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 = 10
# List of local users allowed to login. If you don't set this setting, users
# with uid greater than limit will be able to login
#users = user1,user2
users = nigel,sandy
# Minimum uid that will be allowed to login
limit = 1000
## acl engine global options
#[ACL]
## Enable extended matching rules (enabled by default)
## If the rule is a string like 'user1 = desk*', it will match any client that
## matches 'desk*' no mater what agent it is attached to.
## If it is a coma separated list of strings like 'user1 = desk*,laptop*' it
## will match the first matching rule no mater what agent it is attached to.
## If it is a dict like:
## user1 = '{"agents": ["srv*", "www*"], "clients": ["desk*", "laptop*"]}'
## It will also validate against the agent name.
#extended = true
## If you don't explicitly specify ro/rw grants, what should we assume?
#assume_rw = true
## Enable 'legacy' behavior
## Since v0.6.0, if you don't specify the agents name explicitly, users will be
## granted on every agents where a client matches user's ACL. If you enable the
## 'legacy' behavior, you will need to specify the agents explicitly.
## Note: enabling this option will also disable the extended mode
#legacy = false
## The inheritance order maters, it means depending the order you choose,
## the ACL engine won't handle the grants the same way.
## By default, ACL inherited by groups will have lower priority, unless you
## choose otherwise
#inverse_inheritance = false
## If you specify agents and clients separately, should we link them implicitly?
## For instance, '{"agents": ["agent1", "agent2"], "clients": ["client1", "client2"]}'
## will become: '{"agents": {"agent1": ["client1", "client2"], "agent2": ["client1", "client2"]}}'
#implicit_link = true
## 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
## the same name
#[BASIC:ACL]
## Backend priority. Higher is first
#priority = 100
## List of administrators
#admin = user1,user2
## List of moderators. Users listed here will inherit the grants of the
## 'virtual' user '@moderator'
#+moderator = user5,user6
#@moderator = '{"agents":{"ro":["agent1"]}}'
## NOTE: if you are running single-agent mode, you should specify the ro/rw
## rights of the moderators using this special 'local' agent name:
## NOTE: this is the default when running single-agent mode if you don't
## specify anything else
##@moderator = '{"agents": {"rw": "local"}}'
## Please note the double-quotes and single-quotes on the following lines are
## mandatory!
## You can also overwrite the default behavior by specifying which clients a
## user can access
## Suppose you are running single-agent mode (the default), you only need to
## specify a list of clients a user can access:
#user3 = '{"clients": {"ro": ["prod*"], "rw": ["dev*", "test1"]}}'
## In case you are not in a single mode, you can also specify which clients
## a user can access on a specific Agent
#user4 = '{"agents": {"agent1": ["client6", "client7"], "agent2": ["client8"]}}'
## You can define read-only and/or read-write grants using:
#user5 = '{"agents": {"www*": {"ro": ["desk*"], "rw": ["desk1"]}}}'
## Finally, you can define groups using the syntax "@groupname" and adding
## members using "+groupname". Note: groups can inherit groups!
#@group1 = '{"agents": {"ro": ["*"]}}'
#@group2 = '{"clients": {"rw": ["dev*"]}}'
#+group1 = @group2
#+group2 = user5
## As a result, user5 will be granted the following rights:
## '{"ro": {"agents": ["*", "agent1"], "www*": ["desk*"]}, "rw": {"clients": ["dev*"], "www*": ["desk1"]}}
# If you set single to 'false', add at least one section like this per
# bui-agent
[Agent:Backup]
# bui-agent address
host = backup
# bui-agent port
port = 5001
# bui-agent password
password = ****redacted****
# enable SSL
ssl = true
#[Agent:agent2]
## bui-agent address
#host = 192.168.2.1
## bui-agent port
#port = 10000
## bui-agent password
#password = ytreza
## enable SSL
#ssl = true
Thanks