Bug 1642872 - CVE-2019-3879 ovirt-engine: Missing permissions check in web ui allows a user with basic privileges to delete disks [rhev-m-4.3.0]
Summary: CVE-2019-3879 ovirt-engine: Missing permissions check in web ui allows a user...
Keywords:
Status: CLOSED ERRATA
Alias: None
Deadline: 2019-04-24
Product: Red Hat Enterprise Virtualization Manager
Classification: Red Hat
Component: ovirt-engine
Version: 4.2.6
Hardware: x86_64
OS: Linux
high
high
Target Milestone: ovirt-4.3.3
: 4.3.0
Assignee: Ravi Nori
QA Contact: Lucie Leistnerova
URL:
Whiteboard:
Depends On:
Blocks: CVE-2019-3879 1692380
TreeView+ depends on / blocked
 
Reported: 2018-10-25 09:08 UTC by Olimp Bockowski
Modified: 2020-05-18 13:23 UTC (History)
11 users (show)

Fixed In Version: ovirt-engine-4.3.2.1
Doc Type: No Doc Update
Doc Text:
Clone Of:
: 1692380 (view as bug list)
Environment:
Last Closed: 2019-05-08 12:38:43 UTC
oVirt Team: Infra
Target Upstream Version:
Embargoed:


Attachments (Terms of Use)
role (74.80 KB, image/png)
2018-11-16 16:56 UTC, Olimp Bockowski
no flags Details
permissions (4.58 KB, image/png)
2018-11-16 16:57 UTC, Olimp Bockowski
no flags Details
users (4.96 KB, image/png)
2018-11-16 16:57 UTC, Olimp Bockowski
no flags Details


Links
System ID Private Priority Status Summary Last Updated
Red Hat Product Errata RHEA-2019:1085 0 None None None 2019-05-08 12:39:03 UTC
oVirt gerrit 98153 0 master MERGED engine : Check command permissions for RunAsyncActionCommand 2020-10-30 22:01:46 UTC

Description Olimp Bockowski 2018-10-25 09:08:10 UTC
Description of problem:
It looks like a new role provides more permissions than it is expected. A new role having: "Reboot VM, Stop VM, Shut Down VM, Hibernate VM, Run VM, Change CD, Remote Log in" is able to delete a VM or its disk.

Version-Release number of selected component (if applicable):
4.2.6

How reproducible:
always

Steps to Reproduce:
1. create a new role, check everything from VM/Basic Operations
2. assing a new user with the new role
3. delete any V you wish

Actual results:
VM is deleted

Expected results:
it is not allowed

Comment 2 Andrej Krejcir 2018-11-06 15:13:42 UTC
I cannot reproduce this. What were the exact steps to reproduce?

I tried these steps:
1. Create a custom role, only with action groups in VM/Basic Operations
2. Create a new VM
3. Add permission to the VM for the user with the custom role.
4. Log into VM portal as the user
5. Try to remove the VM

The operation is not successful as expected. Error message: 

Failed to remove the VM
[User is not authorized to perform this action.]


Tested on: 4.2.8-0.0.master.20181101130712.git326ea78.el7

Comment 3 Ryan Barry 2018-11-13 16:03:45 UTC
Olimp, ping?

Comment 4 Olimp Bockowski 2018-11-16 16:55:29 UTC
I wasn't available, in the meantime, my colleague asked the customer, she replied:

"you may update the bug and let Andrej Krejcir know that is not about deleting VM. The user can delete the disk of VM."

However, it is very weird, because for me it is still the problem that I can do whatever. I haven't checked it thoroughly, just from Admin Portal and:

1. I created the role: bugtest (I am not sure which user I used for that, maybe it is curcial). Basic Operations only.
2. I removed myself (obockows LDAP user) from RHV using admin
3. I created a new permission obockows + bugtest role
4. on user list I have a different icon than on system permission: icon of admin instead of user (screenshot attached)
5. I can delete whatever

maybe I missed something? that's odd.

olimpb

Comment 5 Olimp Bockowski 2018-11-16 16:56:30 UTC
Created attachment 1506508 [details]
role

Comment 6 Olimp Bockowski 2018-11-16 16:57:05 UTC
Created attachment 1506509 [details]
permissions

Comment 7 Olimp Bockowski 2018-11-16 16:57:43 UTC
Created attachment 1506510 [details]
users

Comment 8 Marian Jankular 2018-11-30 11:23:51 UTC
Hello, 

is there any progress on this?
Were you able to reproduce deleting the disk of the vm already?

Marian

Comment 9 Ryan Barry 2018-11-30 11:30:38 UTC
This is actually a good question -- was the role created by the customer a user or admin? There's no logcollector in the case, and the screenshot is too cropped to see it either way

Comment 10 Andrej Krejcir 2018-12-03 11:39:21 UTC
I have tired the steps right now and I still cannot reproduce it.

The user cannot connect to admin UI, which is expected, because he does not have any admin role. In the VM portal, the Edit button is grayed out, so there is no way to delete a disk. Using the API to delete the disk is also not permitted:


DELETE ovirt-engine/api/disks/1f33970f-89fb-40fb-97e0-424c259b70f5

<fault>
    <detail>[User is not authorized to perform this action.]</detail>
    <reason>Operation Failed</reason>
</fault>


Can you check if the user has any other roles on any objects (Data Center, Cluster, Storage Domain, VM), that could permit deleting a disk?

Comment 11 Olimp Bockowski 2018-12-04 10:54:50 UTC
@Andrej -
1. have you tried to reproduce my case? e.g. I added a user as admin (using ldap as provider), then I deleted, I added user again with User Role - a new user was able to delete everything. Maybe the problem is that removing user, doesn't remove permission for containing elements? 

2. regardng your question:  ok I see we have to dig into log collector provided by the customer

Comment 12 Andrej Krejcir 2018-12-04 11:20:45 UTC
I tried it now, these steps:

1. Give a user 'test-user' the 'SuperUser' role in Administration -> Configure -> System Permissions
2. Log in as 'test-user' to Admin portal
3. Remove the 'test-user' from System Permissions
4. Try to add 'test-user' again, but an error is shown: 'Error while executing action: User is not authorized to perform this action.'

It makes sense. Once the test-user looses SuperUser permissions, he cannot add a user to system permissions.

Then I logged in as 'admin', added the 'test-user' with the test role to the system permissions. And still everything works as expected.

Comment 13 Olimp Bockowski 2018-12-04 11:24:07 UTC
ok thanks, we will check log collector and DB dump

Comment 14 Olimp Bockowski 2018-12-11 11:22:24 UTC
OK, I really put some effort into that:
ovirt-engine-4.2.7.5-0.1.el7ev.noarch with long history (maybe that's the problem some upgrade script didn't run well) 

table users:
              user_id                | name  |  surname  |           domain           | username | 
--------------------------------------+-------+-----------+----------------------------+----------
53d28cbf-c27e-494d-bfe9-e56c93185d0e | Olimp | Bockowski | ldap.corp.redhat.com-authz | obockows |

table permissions:

                  id                  |               role_id                |            ad_element_id             |              object_id               | object_type_id | creation_date 
--------------------------------------+--------------------------------------+--------------------------------------+--------------------------------------+----------------+---------------
 c47ab965-2c80-43d7-9766-6c9986199665 | 4d843123-3b20-4786-9d05-53b305644620 | 53d28cbf-c27e-494d-bfe9-e56c93185d0e | aaa00000-0000-0000-0000-123456789aaa |              1 |    1544525476


public enum VdcObjectType {
    ...
    System(1, "System"),
    ...

so it is remarkable we have on top - system

engine=# select * from roles where id='4d843123-3b20-4786-9d05-53b305644620';
                  id                  |  name   | description | is_readonly | role_type | allows_viewing_children | app_mode 
--------------------------------------+---------+-------------+-------------+-----------+-------------------------+----------
 4d843123-3b20-4786-9d05-53b305644620 | bugTest |             | f           |         2 | t                       |      255

bugTest role - User Role, it has only VM/Basic Operation - no way to delete


"Role is a set of one or several Action Groups. All roles are listed in roles table (Role class), link between roles and Action Groups - in roles_groups table."

select * from roles_groups WHERE role_id='4d843123-3b20-4786-9d05-53b305644620' ORDER BY action_group_id;
               role_id                | action_group_id 
--------------------------------------+-----------------
 4d843123-3b20-4786-9d05-53b305644620 |               5
 4d843123-3b20-4786-9d05-53b305644620 |               7
 4d843123-3b20-4786-9d05-53b305644620 |              17
 4d843123-3b20-4786-9d05-53b305644620 |              18
 4d843123-3b20-4786-9d05-53b305644620 |              19
 4d843123-3b20-4786-9d05-53b305644620 |              21
 4d843123-3b20-4786-9d05-53b305644620 |              22
 4d843123-3b20-4786-9d05-53b305644620 |            1300
(8 rows)

grep -P '\((5,|7,|17,|18,|19,|21,|22,|1300)' ./backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/ActionGroup.java
    REBOOT_VM(17, RoleType.USER, true, ApplicationMode.VirtOnly),
    STOP_VM(18, RoleType.USER, true, ApplicationMode.VirtOnly),
    SHUT_DOWN_VM(19, RoleType.USER, true, ApplicationMode.VirtOnly),
    HIBERNATE_VM(21, RoleType.USER, true, ApplicationMode.VirtOnly),
    RUN_VM(22, RoleType.USER, true, ApplicationMode.VirtOnly),
    CHANGE_VM_CD(5, RoleType.USER, true, ApplicationMode.VirtOnly),
    CONNECT_TO_VM(7, RoleType.USER, true, ApplicationMode.VirtOnly),
    LOGIN(1300, RoleType.USER, false),

===

I can _DELETE_ any VM with this user

Comment 15 Andrej Krejcir 2018-12-11 12:40:43 UTC
Thanks for the analysis.

Can you please also check if the user is part of any groups that have permission to delete a VM?
This is the SQL statement to get all permission objects for a specific user with roles that allow deleting a VM:

SELECT permissions.*
FROM permissions
  JOIN roles_groups ON permissions.role_id = roles_groups.role_id
WHERE roles_groups.action_group_id = 2    -- Action group id for DELETE_VM
  AND (permissions.ad_element_id = getGlobalIds('everyone')    -- permission is for user 'everyone'
    OR permissions.ad_element_id = '53d28cbf-c27e-494d-bfe9-e56c93185d0e'    -- permission is for this specific user
    OR permissions.ad_element_id IN (SELECT * FROM getUserAndGroupsById('53d28cbf-c27e-494d-bfe9-e56c93185d0e')));    -- permission is for any group that this user us part of

If this does not return any rows, than the user should not be able to delete a VM and there is a bug.

It also may be useful to get names of all groups the user is part of:

SELECT *
FROM ad_groups
WHERE ad_groups.id IN (SELECT * FROM getUserAndGroupsById('53d28cbf-c27e-494d-bfe9-e56c93185d0e'));

Comment 16 Olimp Bockowski 2018-12-14 14:20:13 UTC
@Andrej - thank you, so your query gives the record:

                  id                  |               role_id                |            ad_element_id             |              object_id               | object_type_id | creation_date 
--------------------------------------+--------------------------------------+--------------------------------------+--------------------------------------+----------------+---------------
 07471466-fde5-448e-bd9c-ce144b1face9 | 00000000-0000-0000-0000-000000000001 | eee00000-0000-0000-0000-123456789eee | aaa00000-0000-0000-0000-123456789aaa |              1 |    1533304087

and eee00000-0000-0000-0000-123456789eee is Everyone

                  id                  |            name             |           domain           | distinguishedname |             external_id              |    namespace     
--------------------------------------+-----------------------------+----------------------------+-------------------+--------------------------------------+------------------
 eee00000-0000-0000-0000-123456789eee | Everyone                    |                            |                   | eee00000-0000-0000-0000-123456789eee | *

and Eveyrone has SuperUser and of course, the user is part of that group only (taken using: SELECT * FROM ad_groupd HERE ad_groups.id IN (SELECT * FROM getUserAndGroupsById('53d28cbf-c27e-494d-bfe9-e56c93185d0e'));)

But I can't understand it, so please explain to me: Everyone looks name domain of admin (e.g. internal), so how it could be that user from ldap is part of that group? Or I am wrong?

BTW
I opened this BZ as something "wider" than a customer requested. If the above problem is clear, then we focus just on disks' permissions.
Thanks for your help!

Comment 17 Andrej Krejcir 2019-01-16 10:21:20 UTC
'Everyone' is a special hard-coded group that contains all users form all domains.

I will look through the code more, to see if there is a bug with the disks' permissions...

Comment 18 Ryan Barry 2019-01-21 14:53:30 UTC
Re-targeting to 4.3.1 since it is missing a patch, an acked blocker flag, or both

Comment 20 Andrej Krejcir 2019-01-24 15:28:29 UTC
The disks' permission checking seems to be fine.
I still cannot reproduce this bug.

Could you try running the same SQL query but for DELETE_DISK action group, and see if there are any groups the user is part of that can delete the disk?


SELECT permissions.*
FROM permissions
  JOIN roles_groups ON permissions.role_id = roles_groups.role_id
WHERE roles_groups.action_group_id = 1104    -- Action group id for DELETE_DISK
  AND (permissions.ad_element_id = getGlobalIds('everyone')    -- permission is for user 'everyone'
    OR permissions.ad_element_id = '53d28cbf-c27e-494d-bfe9-e56c93185d0e'    -- permission is for this specific user
    OR permissions.ad_element_id IN (SELECT * FROM getUserAndGroupsById('53d28cbf-c27e-494d-bfe9-e56c93185d0e')));    -- permission is for any group that this user us part of

Comment 21 Roman Hodain 2019-02-14 10:07:53 UTC
(In reply to Andrej Krejcir from comment #20)
> The disks' permission checking seems to be fine.
> I still cannot reproduce this bug.
> 
> Could you try running the same SQL query but for DELETE_DISK action group,
> and see if there are any groups the user is part of that can delete the disk?
> 
> 
> SELECT permissions.*
> FROM permissions
>   JOIN roles_groups ON permissions.role_id = roles_groups.role_id
> WHERE roles_groups.action_group_id = 1104    -- Action group id for
> DELETE_DISK
>   AND (permissions.ad_element_id = getGlobalIds('everyone')    -- permission
> is for user 'everyone'
>     OR permissions.ad_element_id = '53d28cbf-c27e-494d-bfe9-e56c93185d0e'   
> -- permission is for this specific user
>     OR permissions.ad_element_id IN (SELECT * FROM
> getUserAndGroupsById('53d28cbf-c27e-494d-bfe9-e56c93185d0e')));    --
> permission is for any group that this user us part of

Hi, 

I believe that the problem is not the permission, but the fact that RemoveDiskCommand is triggered as an internal command. In this case, the permission validation is skipped. I have set a reproducer to confirm and I can see the following with the debug logs enabled:

2019-02-14 10:02:46,245Z INFO  [org.ovirt.engine.core.bll.RunAsyncActionCommand] (default task-8) [7b372531] Running command: RunAsyncActionCommand(Action = RemoveDisk, ActionParameters = RemoveDiskParameters:{commandId='null', user='null', commandType='Unknown'}) internal: false.
2019-02-14 10:02:46,253Z DEBUG [org.ovirt.engine.core.bll.storage.disk.RemoveDiskCommand] (EE-ManagedThreadFactory-commandCoordinator-Thread-3) [347a0255-ca56-431b-8fa7-ee5a007f9548] Permission check skipped for internal action RemoveDisk.

Can you please check that?

Comment 22 Andrej Krejcir 2019-02-14 14:18:11 UTC
Thank you for the information. With it, I was able to reproduce it in my environment too.

The key is that deleting the disk is executed as an async REST call:
DELETE /ovirt-engine/api/disks/DISK_ID?async=true 

Which version of ovirt-web-ui are you using? 
I cannot see any way to delete a disk when logged in as the user to the VM portal.

Comment 23 Olimp Bockowski 2019-02-14 14:29:41 UTC
@Andrej - I asked Roman to find the problem, anyway, it was some time ago, but why you think we are talking about VM Portal? Account type admin has  VM / Basic Operations, so

Comment 24 Andrej Krejcir 2019-02-14 14:55:32 UTC
Because the problem happens when using the REST API, I assumed that the API is called from the VM portal. But it could also be called from a script.

Anyway, now we know how to reproduce it and where to start fixing it.

Comment 25 Roman Hodain 2019-02-15 08:36:57 UTC
(In reply to Andrej Krejcir from comment #22)
> Thank you for the information. With it, I was able to reproduce it in my
> environment too.
> 
> The key is that deleting the disk is executed as an async REST call:
> DELETE /ovirt-engine/api/disks/DISK_ID?async=true 
> 
> Which version of ovirt-web-ui are you using? 
> I cannot see any way to delete a disk when logged in as the user to the VM
> portal.

I use ovirt-web-ui-1.4.5-1.el7ev. The engine is the latest 4.2.8-async

Comment 28 Lucie Leistnerova 2019-03-21 17:21:49 UTC
Deleting disk without permissions with/without async=true failed. Async shows <status>failed</status> and engine log contains appropriate error.

verified in ovirt-engine-4.3.2.1-0.1.el7.noarch

Comment 31 Doran Moppert 2019-03-25 06:01:35 UTC
A change was made (new impact, public date, or CSAw status) to the security issue(s) blocked by this tracker, resulting in a new SLA deadline. This bug must now be resolved by 24-Apr-2019.

Refer to this bug's Description for information about how to resolve this bug.

Comment 34 errata-xmlrpc 2019-05-08 12:38:43 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory, and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://access.redhat.com/errata/RHEA-2019:1085


Note You need to log in before you can comment on or make changes to this bug.