Bug 1263741 - CVE-2015-5233 - reports show/destroy not restricted by host authorization
CVE-2015-5233 - reports show/destroy not restricted by host authorization
Status: CLOSED ERRATA
Product: Red Hat Satellite 6
Classification: Red Hat
Component: Security (Show other bugs)
6.0.4
Unspecified Unspecified
unspecified Severity high (vote)
: 6.1.5
: --
Assigned To: Daniel Lobato Garcia
Kedar Bidarkar
http://projects.theforeman.org/issues...
: Triaged
Depends On:
Blocks: CVE-2015-5233
  Show dependency treegraph
 
Reported: 2015-09-16 10:52 EDT by Bryan Kearney
Modified: 2017-02-23 14:46 EST (History)
6 users (show)

See Also:
Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Environment:
Last Closed: 2015-12-15 04:19:41 EST
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
CRM:
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---


Attachments (Terms of Use)


External Trackers
Tracker ID Priority Status Summary Last Updated
Foreman Issue Tracker 11579 None None None 2016-04-22 11:55 EDT

  None (edit)
Description Bryan Kearney 2015-09-16 10:52:03 EDT
Foreman 1.5.0 or higher are vulnerable to an authorization issue that allows users to view and delete reports for hosts that they don't have access to.

Reports (from tools such as Puppet) are stored in Foreman and associated to the host they came from.  Users can be granted permissions to view and/or destroy reports, and also separate permissions to view certain hosts.  The UI and API only list reports where the user has permission to view both reports and the host it was from.

The security issue is that both the show and destroy actions for viewing and deleting individual reports do not limit access to the hosts that the user has permission to view.  A user with permission to view or destroy reports can do so for any host if they know the ID, or can easily view the last report for a given host.

Thanks to Daniel Lobato Garcia of Red Hat for reporting this to foreman-security@googlegroups.com.
Comment 1 Bryan Kearney 2015-09-16 10:52:04 EDT
Created from redmine issue http://projects.theforeman.org/issues/11579
Comment 2 Bryan Kearney 2015-09-16 10:52:06 EDT
Upstream bug assigned to dlobatog@redhat.com
Comment 3 Bryan Kearney 2015-09-16 10:58:26 EDT
Moving to POST since upstream bug http://projects.theforeman.org/issues/11579 has been closed
-------------
Daniel Lobato Garcia
Applied in changeset commit:293036dfa71ae70624663647f1ef70798bf53d3e.
Comment 6 Corey Welton 2015-11-04 16:03:07 EST
We are not sure if we have fully tested this and/or if we are seeing what we expect.

If we create a role with view_ and destroy_report roles, and 'where host != $hostname', we can still view report for said host, albeit it doesn't appear we can delete reports.

If we create a role with view_ and destroy_report roles, and put user in a different group than the group which owns $hostname, and try to visit the URL which would take user to role, we get content headers for a table but no content.

Ergo: 

* for the first scenario, explicitly excluding a host we manage to still view reports, albeit apparently not delete them.

* for the second scenario, it does appear that we're unable to view (or delete) reports where user is blocked, on an organizational level, from otherwise interacting with a host/its reports.


Are we on the right track here?  Have we tested this and found remaining deficiencies, or are we not testing the right thing(s) in either scenario?
Comment 8 Daniel Lobato Garcia 2015-11-09 03:10:03 EST
Hi Corey, I think you're testing a different thing. The original bug had to do with two sets of permissions, 'view_hosts' and 'view_reports', with "unlimited"
 filter. If you can view a host through 'view_hosts' and you have the `view_reports` permission you should be able to see reports. If you have 'view_reports' but 'view_hosts' only enabled for certain hosts, due to a filter, organization, etc.. you should only view reports for hosts in the limited filter. This last point is what the CVE is about.

> If we create a role with view_ and destroy_report roles, and 'where host !=
> $hostname', we can still view report for said host, albeit it doesn't appear
> we can delete reports.

Sounds like a bug, mind to submit it to foreman-security@googlegroups.com. It's a different bug that has to do with the Report filters, the original one was about Host filters.

> 
> If we create a role with view_ and destroy_report roles, and put user in a
> different group than the group which owns $hostname, and try to visit the
> URL which would take user to role, we get content headers for a table but no
> content.

Different bug, file it through http://projects.theforeman.org/issues/ , sounds like an usability problem, not a security issue

> Are we on the right track here?  Have we tested this and found remaining
> deficiencies, or are we not testing the right thing(s) in either scenario?

Please see this comment http://projects.theforeman.org/issues/11579#note-1 to understand what to test. Just create a 'view_reports' permission, then a 'view_hosts' permission with limited access, and try to break it as mentioned in the bug (providing an ID, checking the last report..)
Comment 13 Kedar Bidarkar 2015-11-12 05:16:42 EST
I had earlier tried it with 'hostgroup' itself, but while updating , may be just updated without the actual exact name of the filter and used 'host_groups'.

I tried filtering using many other entities, but face the same issue as mentioned earlier.

when filtered with content_source filter , I get the below issue.

2015-11-12 04:44:22 [I] Processing by ReportsController#index as HTML
2015-11-12 04:44:22 [I]   Parameters: {"search"=>"eventful = true"}
2015-11-12 04:44:22 [I]   Rendered reports/_list.html.erb (9.6ms)
2015-11-12 04:44:22 [I]   Rendered reports/index.html.erb within layouts/application (10.3ms)
2015-11-12 04:44:22 [W] Operation FAILED: PGError: ERROR:  missing FROM-clause entry for table "smart_proxies"
LINE 1: ...2) AND "hosts"."type" IN ('Host::Managed') AND ((("smart_pro...
                                                             ^
: SELECT  "reports"."id" AS t0_r0, "reports"."host_id" AS t0_r1, "reports"."reported_at" AS t0_r2, "reports"."created_at" AS t0_r3, "reports"."updated_at" AS t0_r4, "reports"."status" AS t0_r5, "reports"."metrics" AS t0_r6, "hosts"."id" AS t1_r0, "hosts"."name" AS t1_r1, "hosts"."ip" AS t1_r2, "hosts"."last_compile" AS t1_r3, "hosts"."last_freshcheck" AS t1_r4, "hosts"."last_report" AS t1_r5, "hosts"."updated_at" AS t1_r6, "hosts"."source_file_id" AS t1_r7, "hosts"."created_at" AS t1_r8, "hosts"."mac" AS t1_r9, "hosts"."root_pass" AS t1_r10, "hosts"."serial" AS t1_r11, "hosts"."puppet_status" AS t1_r12, "hosts"."domain_id" AS t1_r13, "hosts"."architecture_id" AS t1_r14, "hosts"."operatingsystem_id" AS t1_r15, "hosts"."environment_id" AS t1_r16, "hosts"."subnet_id" AS t1_r17, "hosts"."ptable_id" AS t1_r18, "hosts"."medium_id" AS t1_r19, "hosts"."build" AS t1_r20, "hosts"."comment" AS t1_r21, "hosts"."disk" AS t1_r22, "hosts"."installed_at" AS t1_r23, "hosts"."model_id" AS t1_r24, "hosts"."hostgroup_id" AS t1_r25, "hosts"."owner_id" AS t1_r26, "hosts"."owner_type" AS t1_r27, "hosts"."enabled" AS t1_r28, "hosts"."puppet_ca_proxy_id" AS t1_r29, "hosts"."managed" AS t1_r30, "hosts"."use_image" AS t1_r31, "hosts"."image_file" AS t1_r32, "hosts"."uuid" AS t1_r33, "hosts"."compute_resource_id" AS t1_r34, "hosts"."puppet_proxy_id" AS t1_r35, "hosts"."certname" AS t1_r36, "hosts"."image_id" AS t1_r37, "hosts"."organization_id" AS t1_r38, "hosts"."location_id" AS t1_r39, "hosts"."type" AS t1_r40, "hosts"."otp" AS t1_r41, "hosts"."realm_id" AS t1_r42, "hosts"."compute_profile_id" AS t1_r43, "hosts"."provision_method" AS t1_r44, "hosts"."content_source_id" AS t1_r45, "hosts"."primary_interface" AS t1_r46, "hosts"."grub_pass" AS t1_r47, "hosts"."discovery_rule_id" AS t1_r48, "hosts"."content_view_id" AS t1_r49, "hosts"."lifecycle_environment_id" AS t1_r50 FROM "reports" LEFT OUTER JOIN "hosts" ON "hosts"."id" = "reports"."host_id" AND "hosts"."type" IN ('Host::Managed') WHERE "reports"."host_id" IN (SELECT "hosts"."id" FROM "hosts"  WHERE "hosts"."organization_id" IN (1) AND "hosts"."location_id" IN (2) AND "hosts"."type" IN ('Host::Managed') AND ((("smart_proxies"."name" = 'xyz-sat6.redhat.com') AND ("hosts"."organization_id" = '1') AND ("hosts"."location_id" = '2'))) ORDER BY "hosts"."name" ASC NULLS FIRST ) AND (((("reports"."status" >> 0 & 16777215) > 0))) ORDER BY "reports"."reported_at" DESC NULLS LAST  LIMIT 20 OFFSET 0
2015-11-12 04:44:22 [I]   Rendered common/500.html.erb within layouts/application (6.4ms)
2015-11-12 04:44:22 [I]   Rendered layouts/base.html.erb (1.5ms)
2015-11-12 04:44:22 [I] Completed 500 Internal Server Error in 264ms (Views: 10.7ms | ActiveRecord: 1.2ms)
Comment 20 Kedar Bidarkar 2015-12-01 06:30:37 EST
Tested with 'view_hosts' only enabled for certain hosts and the limited filter with which tested for are:

a) host-group
b) organization
c) domain
d) arch
e) environment

 only view reports for these hosts were visible.

VERIFIED with Satellite-6.1.0-RHEL-6-20151125.0
Comment 22 errata-xmlrpc 2015-12-15 04:19:41 EST
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/RHSA-2015:2622

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