Red Hat Bugzilla – Bug 1263741
CVE-2015-5233 - reports show/destroy not restricted by host authorization
Last modified: 2017-02-23 14:46:22 EST
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.
Created from redmine issue http://projects.theforeman.org/issues/11579
Upstream bug assigned to dlobatog@redhat.com
Moving to POST since upstream bug http://projects.theforeman.org/issues/11579 has been closed ------------- Daniel Lobato Garcia Applied in changeset commit:293036dfa71ae70624663647f1ef70798bf53d3e.
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?
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..)
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)
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
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