Skip to content

Authentication

Johannes vom Dorp edited this page Mar 16, 2018 · 12 revisions

Using FACT with Authentication

Overview

  1. Concept
  2. Configuration
  3. Default Privileges
  4. Example Setup

1. Concept

By utilizing flask_security, a role based access control was added as an optional feature to secure the FACT GUI. The idea is to define a privilege to each functionality and link that privilege to a set of roles. E.g. let upload analysis and update analysis have the privilege submit. Then the endpoints /upload, /rest/firmware and all secondary paths require the submit privilege. To ease the amount of configuration, this privilege can be applied to multiple roles as well as one or none role.

The standard browser interface is given an additional login/logout tab to enter username/password. Additionally an api key is generated for each user which can be used in the Authorization header field of a http request to authenticate against the REST-API.

2. Configuration

The authentication feature is turned off by default to keep backwards compatibility as well as spare internal setups the unnecessary overhead. Turning it on is achieved by simply setting the authentication option in the config file to true. The authentication feature comes packaged with a user management tool src/manage_users.py that can create users and roles. Also it allows adding/removing roles to/from users and listing the api key for an existing user. A GUI based user management is not considered yet.

Adding privileges to a role can be achieved by changing the PRIVILEGES field in the src/security_switch.py script. This field is a dictionary mapping each privilege to a set of roles. The privilege of an endpoint is given to the roles_accepted decorator of the endpoint function. Thus, by changing the parameter of the endpoint, the privilege can be changed.

⚠️ Caution: Because of the shared ajax endpoints, the compare privilege, has to be at least as powerful as view_analysis, when the default privilege <> endpoint mapping is applied.

3. Default Privileges

As of now these privileges and roles are configured:

ROLES = ['superuser', 'senior_analyst', 'analyst', 'guest_analyst', 'guest']

PRIVILEGES = {
    'status':           ['superuser', 'senior_analyst', 'analyst', 'guest_analyst', 'guest'],
    'basic_search':     ['superuser', 'senior_analyst', 'analyst', 'guest_analyst'],
    'view_analysis':    ['superuser', 'senior_analyst', 'analyst', 'guest_analyst'],
    'comment':          ['superuser', 'senior_analyst', 'analyst'],
    'compare':          ['superuser', 'senior_analyst', 'analyst'],
    'advanced_search':  ['superuser', 'senior_analyst', 'analyst'],
    'pattern_search':   ['superuser', 'senior_analyst', 'analyst'],
    'submit_analysis':  ['superuser', 'senior_analyst'],
    'download':         ['superuser', 'senior_analyst'],
    'delete':           ['superuser']
}

The default privilege / endpoint mapping looks as follows:

{
    'view_analysis': [
       '/analysis/<uid>',
       '/analysis/<uid>/ro/<root_uid>',
       '/analysis/<uid>/<selected_analysis>',
       '/analysis/<uid>/<selected_analysis>/ro/<root_uid>',
       '/analysis/<uid>/<selected_analysis>/<root_uid>',
       '/ajax_tree/<uid>/<root_uid>',
       '/ajax_root/<uid>',
       '/rest/firmware/<uid>',
       '/rest/file_object/<uid>',
       '/rest/file_object',
       '/ajax_get_binary/<mime_type>/<uid>',
       '/ajax_get_binary/<type>/<uid>'
    ],
    'submit': [
       '/update-analysis/<uid>',
       '/compare',
       '/rest/firmware',
       '/upload'
    ],
    'compare': [
       '/database/browse_compare',
       '/compare/<compare_id>',
       '/rest/compare',
       '/rest/compare/<compare_id>',
       '/compare/ajax_tree/<compare_id>/<root_uid>/<uid>',
       '/compare/ajax_common_files/<compare_id>/<feature_id>/',
       '/comparison/add/<uid>',
       '/comparison/remove/<analysis_uid>/<compare_uid>',
       '/comparison/remove_all/<analysis_uid>'
    ],
    'pattern_search': [
       '/database/binary_search',
       '/database/database_binary_search_results.html'
    ],

    'advanced_search': [
       '/database/advanced_search'
    ], 
    'basic_search': [
       '/database/browse',
       '/database/search',
       '/database/quick_search'
    ],
    'download': [
       '/rest/binary/<uid>',
       '/download/<uid>',
       '/tar-download/<uid>',
       '/ida-download/<compare_id>',
       '/base64-download/<uid>/<section>/<expression_id>',
       '/hex-dump/<uid>'
    ],
    'comment': [
       '/comment/<uid>'
    ],
    'delete': [
       '/admin/delete_comment/<uid>/<timestamp>',
       '/admin/delete/<uid>',
       '/admin/re-do_analysis/<uid>'
    ],
    'status': [
       '/statistic',
       '/system_health',
       '/' 
    ]
}

Note: Only the /about route is accessible without authentication.

4. Example Setup

This example sets up FACT with the default privileges and roles along with two users admin and worker. The admin will be provided the superuser role while worker will be assigned to analyst.

After installing at least the fact frontend (./install.py -F) the path for the user database, defined in the main.cfg should exist. If another path is intended, the directory for this path is to be created before proceeding with the creation of users and roles.

On invokation ./src/manage_users.py will open a connection to the database specified in the given config file (default is the main.cfg). If the database does not yet exist, it will be created. After starting, the script will ask the user to specify an action (type help for a list of actions). We want to first create our roles: superuser and analyst.

  1. Type create_role and hit enter
  2. Type superuser and hit enter -- The role will then be created
  3. Type create_role again and hit enter
  4. Type analyst and hit enter -- The role will then be created as well

Now we want to create our users admin and worker:

  1. Type create_user and hit enter
  2. Type admin and hit enter
  3. Type your password - lets say you will choose the super secure password admin - and hit enter -- The user will then be created
  4. Type create_user again and hit enter
  5. Type worker and hit enter
  6. Type password again - this time we assume you chose worker - and hit enter -- The user will then be created as well

Finally we need to give our users the intended roles (admin:superuser & worker:analyst):

  1. Type add_role_to_user and hit enter
  2. Type admin and hit enter
  3. Type superuser and hit enter -- The role will be granted to the user
  4. Type add_role_to_user again and hit enter
  5. Type worker and hit enter
  6. Type analyst and hit enter -- The role will be granted to the user as well

Congratulations! You successfully initialized your users. If you need the API keys for your users you can also get them via the user management tool:

  1. Type get_apikey_for_user and hit enter
  2. Type admin and hit enter -- The key will be given on stdout
  3. Type get_apikey_for_user again and hit enter
  4. Type worker and hit enter -- Again the key will be given on stdout

Further users and roles can be created just like above. If actions are applied to none existing users/roles or a previously existing user/role should be created again, the tool will issue error messages. Users can be deleted. Roles can not be deleted.