[FOLIO-2565] Misleading Permission Set Configuration Created: 16/Apr/20  Updated: 13/Jul/21  Resolved: 04/May/20

Status: Closed
Project: FOLIO
Components: None
Affects versions: None
Fix versions: None

Type: Bug Priority: P2
Reporter: Jakub Skoczen Assignee: Craig McNally
Resolution: Done Votes: 0
Labels: platform-backlog, security
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original estimate: Not Specified

Issue links:
Blocks
blocks FOLIO-2524 Security Audit raised issues Open
Relates
relates to FOLIO-2583 Spike: Distributed configuration Open
relates to FOLIO-2607 Spike: Permissions migration Open
relates to FOLIO-2578 Misleading Permission Set Configurati... Closed
relates to OKAPI-839 SPIKE: consider migration of static p... Closed
Sprint: CP: sprint 87
Story Points: 2
Development Team: Core: Platform

 Description   

Impact

A user with seemingly basic privileges is able to obtain configuration information for various modules, notably credentials associated with the login-saml and smtp_server module. The user is able to send emails from the fse.hosting@ebsco.com email address using the credentials discovered.

Description

The Okapi system implements permissions by either assigning them to users, or to modules. Any user assigned a permission is also assigned the “subPermissions” of that permission, if any exist. This leads to issues where permissions grant access to more than their name implies.
For example, the “configuration.entries.collection.get” permission is assigned as a “subPermission” to several permissions such as “ui-calendar.view” and “ui-inventory-instance.view”.
Thus, anyone granted one of those permissions is also granted the “configuration.entries.collection.get” permission. This permission gives access to the /configurations/entries endpoint. The endpoint reveals configuration details, including credentials for a SMTP relay server, as well as
the value of the keystore.privatekey.password and keystore.password variables used by the login-saml module. NCC Group was able to use these credentials and configurations to send an email from the fse.hosting@ebsco.com address. Thus, any user who has seemingly benign permissions such as ui-calendar.view, is also able to view these configuration details and send emails from that address.
Additionally, the “view_perms” permission set, which implies read-only permissions, includes permissions that allow for creating, editing, and deleting various resources as well. Permis- sions that are granted include permissions to edit and remove orders, create and delete notes, and view all permissions within the “Inventory” module.

Repro steps

An example is provided below to demonstrate potentially problematic permissions. Note that any permission that has subPermissions may have this issue.
1. Issue the following HTTP request, replacing TOKEN with a valid JWT token for a user on the system.

curl -i -s -k -X $'GET' \
-H $'Host: okapi-bugfest.folio.ebsco.com' \ -H $'Accept: application/json' \
-H $'X-Okapi-Tenant: fs00001000' \
-H $'X-Okapi-Token: TOKEN ' \
$'https://okapi-bugfest.folio.ebsco.com/perms/permissions?query=displayName==% 22view_perms%22'

2. Note in the response that the “subPermissions”of this permission include permissions that allow users to edit, update, and create various resources.

Permissions should be carefully audited to ensure admin-like permissions do not get assigned as “subPermissions” to permissions whose names do not imply admin-like rights. For example, the “view_perms” permission set should be renamed or modified to not include permissions which grant create, edit, or delete functionality.

Acceptance criteria

  • Write a guidance document on best practices constructing permission sets and using module permissions to avoid escalating direct end-user permissions
  • provide a couple examples of permission sets that include permissions direct permissions beyond what logically should be provided directly to the user (NCC example is one, we need a couple more)

Split into continuation story:

  • walkthrough the proposal document with Tech Leads on the TL meeting
  • create Jira tickets for individual teams to perform verification of permission sets in the modules they are responsible for, according to the best practices


 Comments   
Comment by Julian Ladisch [ 21/Apr/20 ]

mod-kb-ebsco-java has it's own configuration API endpoint. It stores the password to the EBSCO Knowledge Base but removes the password from the GET request: https://github.com/folio-org/mod-kb-ebsco-java/blob/v3.4.0/src/main/java/org/folio/rest/impl/EholdingsConfigurationImpl.java#L59

Comment by Craig McNally [ 28/Apr/20 ]

There are a few parts to this...

1) Permission sets named inappropriately, e.g. something.view suggests it provides the ability to view something. It shouldn't have subPermissions that allow for put/post/delete. Here's an actual example:

{
  "permissionName": "ui-receiving.basic.view",
  "displayName": "Receiving: Basic view",
  "id": "5542bb26-9eff-4699-a7c5-6e6a049979d7",
  "tags": [],
  "subPermissions": [
    "module.receiving.enabled",
    "orders.item.get",
    "orders.pieces.item.post",
    "orders.pieces.item.put",
    "orders.po-lines.collection.get",
    "orders.titles.collection.get",
    "orders.titles.item.get",
    "ui-receiving.third-party-services"
  ],
  "childOf": [
    "ui-receiving.view"
  ],
  "grantedTo": [],
  "mutable": false,
  "visible": false,
  "dummy": false
}

The ERM modules use a naming convention that might be more appropriate for these types of permission set, e.g.

{
  "permissionName": "ui-erm-usage.view-create-edit",
  "displayName": "eUsage: Can view, create and edit usage data providers and COUNTER reports",
  "id": "ade748af-66b5-4584-a319-3cac20899241",
  "description": "Can view, create and edit usage data providers and COUNTER reports",
  "tags": [],
  "subPermissions": [
    "module.erm-usage.enabled",
    "usagedataproviders.collection.get",
    "usagedataproviders.item.get",
    "usagedataproviders.item.post",
    "usagedataproviders.item.put",
    "counterreports.collection.get",
    "counterreports.item.get",
    "counterreports.item.post",
    "counterreports.item.put",
    "aggregatorsettings.collection.get",
    "aggregatorsettings.item.get"
  ],
  "childOf": [],
  "grantedTo": [
    "fba0106d-e2ad-494e-8958-ce5b447ab2aa"
  ],
  "mutable": false,
  "visible": true,
  "dummy": false
}

2) Permission sets provided by module A provide subPermissions for module B. The most glaring example of this is the inclusion of mod-configuration properties in permission sets created by other modules...

$ curl $OKAPI/perms/permissions?length=99999 -H "X-Okapi-Token: $TOKEN" -w'\n' -s | jq '.permissions[] | select(.subPermissions[] | contains("configuration.entries"))' | grep permissionName 
  "permissionName": "ui-inventory.settings.hrid-handling",
  "permissionName": "ui-oai-pmh.edit",
  "permissionName": "module.licenses.enabled",
  "permissionName": "modperms.circulation.loans.anonymize",
  "permissionName": "modperms.circulation.override-renewal-by-barcode.post",
  "permissionName": "modperms.circulation.renew-by-barcode.post",
  "permissionName": "modperms.circulation.requests.item.move.post",
  "permissionName": "module.agreements.enabled",
  "permissionName": "modperms.circulation.renew-by-id.post",
  "permissionName": "ui-calendar.view",
  "permissionName": "modperms.circulation.requests.item.post",
  "permissionName": "modperms.circulation.override-check-out-by-barcode.post",
  "permissionName": "modperms.circulation.requests.item.put",
  "permissionName": "modperms.circulation.requests.instances.item.post",
  "permissionName": "modperms.circulation.check-out-by-barcode.post",
  "permissionName": "module.erm-usage.enabled",
  "permissionName": "module.erm-usage.enabled",
  "permissionName": "ui-finance.third-party-services",
  "permissionName": "modperms.orders.item.post",
  "permissionName": "modperms.orders.item.put",
  "permissionName": "settings.erm-usage.enabled",
  "permissionName": "settings.erm-usage.enabled",
  "permissionName": "settings.erm-usage.enabled",
  "permissionName": "ui-inventory.instance.view",
  "permissionName": "ui-invoice.third-party-services",
  "permissionName": "ui-oai-pmh.view",
  "permissionName": "ui-orders.third-party-services",
  "permissionName": "ui-organizations.third-party-services",
  "permissionName": "ui-receiving.third-party-services",
  "permissionName": "configuration.all",
  "permissionName": "configuration.all",
  "permissionName": "configuration.all",
  "permissionName": "configuration.all",
  "permissionName": "configuration.all",
  "permissionName": "ui-users.settings.customfields.view",
  "permissionName": "ui-requests.view",
  "permissionName": "ui-users.settings.customfields.edit",
  "permissionName": "ui-users.settings.customfields.edit",
  "permissionName": "ui-users.view",

This one can be categorized further...

  • In the case of backend modules, it's the module that's making the API call to mod-configuration there's no need give the user the permission, just use a module permission for that. I think this is generally what's happening. I should note that often module descriptors define a permission set that contains all of the module permissions for a given endpoint and then just use that in the endpoint handler's modulePermissions field. This might make it easier to read the module descriptor, but now we have a permission set that grants permissions to multiple modules, which could be assigned to a user, despite the apparent naming convention of modperms.*. I'm not sure if this is a big deal or not.
  • In the case of ui modules, it's a little bit trickier since there's no notion of a ui-module-permission. Calls from the ui are made solely with the user's permissions I think the best we can do here is limit these to permission sets which are for viewing/managing settings, e.g. "ui-users.settings.customfields.edit" but probably not "ui-users.view". If needed, we should create additional permission sets with appropriate names.

3) mod-configuration permissions are not very granular. Granting a user to "configuration.entries.collection.get" so they can view a handful of relevant entries means that they can now also view ALL entries, regardless of their relevance and/or sensitivity. For this reason:

  • Sensitive information should NEVER be stored in mod-configuration. SMTP credentials, RMAPI credentials, etc. should be stored behind their own endpoints which are protected with distinct permissions.
  • We might want to take a look at ways to make the permissions of this module more granular, perhaps something could be done using desiredPermissions / X-Okapi-Permissions? Though I'm not sure this is really doable or even worth it. I think I'm in favor of just moving away from mod-configuration all together (see below)
  • We should consider moving away from using mod-configuration in general. The cross-app nature of this module makes it difficult to deal with other things like sample/reference data... what if you want some reference data loaded into mod-configuration, but not all of it?
Comment by Craig McNally [ 28/Apr/20 ]

I've started a wiki page to capture the proposed guidelines: https://folio-org.atlassian.net/wiki/display/FOLIJET/Proposed+Permission+Set+Guidelines

Comment by Zak Burke [ 28/Apr/20 ]

The mod-configuration issue is especially sticky IMHO as we don't have a way to segregate permissions based on user or module even though the permissions themselves are split out that way. Huh? It's like this: you can't grant users permission to read or write some configuration data without granting them permission to read or write all configuration data, regardless of module or userId. That seems ... unfortunate.

Comment by Craig McNally [ 04/May/20 ]

Closing this per conversation with Jakub Skoczen. See linked tickets for follow-on work

Generated at Thu Feb 08 23:21:35 UTC 2024 using Jira 1001.0.0-SNAPSHOT#100246-sha1:7a5c50119eb0633d306e14180817ddef5e80c75d.