
PEACH
Un framework di isolamento del tenant
GET /resources/:resource_name/:id/:related_name/:related_id shows one record through its parent, for example /resources/users/42/orders/7. That route checked no policy: not the related resource's show?, not its policy scope, and not the parent's view_<association>?. A signed-in Avo user who could open a parent record could open every record associated with it, including records the related resource's policy denied them. has_one fields on show pages load their content through the same route.
This affects apps that authorize with a policy client: avo-authorization on Avo 4, avo-pro on Avo 3. Without one, Avo runs no policies, by design.
The route has lacked this check since avo 2.12.0.
Fixed in avo 4.3.4 and avo 3.33.2.
Avo 3 apps that use avo-pro or avo-advanced also need 3.33.2 of avo-pro, avo-advanced, avo-dashboards, avo-menu and avo-dynamic_filters, because they pin the avo version exactly. Run bundle update avo together with those gems.
The route now checks the parent's view_<association>?, as the association list already did, and the related record's show?, as the record's own page does. has_many records load through the related resource's policy scope. Commits: avo-hq/avo@8ea8476b4 (4.x), avo-hq/avo@be234d8d0 (3.x).
Avo's association "show" endpoint renders a related record's full detail view without performing any authorization check. The inherited authorize_base_action gate in BaseController is conditionally excluded for the AssociationsController, and the controller adds its own authorization callbacks for index, new/create, and destroy but not for show. As a result, any authenticated Avo user who can reach a parent record in their policy scope can view the full show page of its associated records, bypassing the related resource's show? policy. The endpoint is GET /resources/:resource_name/:id/:related_name/:related_id.
Avo enforces per-action authorization through a before_action :authorize_base_action declared in BaseController. That gate is disabled for the entire AssociationsController by a guard condition on the controller name. AssociationsController is expected to re-add authorization through action-specific callbacks, and it does so for index, new, create, and destroy, but the show action has no corresponding callback. No authorization is evaluated anywhere on the show path, and the related record itself is loaded through a raw ActiveRecord association rather than through a policy-scoped query, so the related resource's show? policy never runs.
# app/controllers/avo/base_controller.rb:14-15
# Don't run base authorizations for associations
before_action :authorize_base_action, except: [:preview, :search], if: -> { controller_name != "associations" }
# app/controllers/avo/associations_controller.rb:14-16
before_action :authorize_index_action, only: :index
before_action :authorize_attach_action, only: [:new, :create]
before_action :authorize_detach_action, only: :destroy
# (no authorize callback for :show)
# app/controllers/avo/associations_controller.rb:43 : Avo::AssociationsController#show
# app/controllers/avo/base_application_controller.rb:150-157 : set_related_record loads
# the related record via @related_resource.find_record params[:related_id],
# query: @record.send(association_name) (raw association, no policy scope)The prerequisite is an authenticated Avo session with a configured authorization provider (for example Pundit policies, the documented and expected production setup where explicit_authorization defaults to true). Within that setup, an attacker needs only scope access to a parent record, which is the normal baseline for any authenticated user (for example their own user record). From there they can request the show view of any record associated with that parent, even when the related resource's show? policy would otherwise deny access. The demonstrated capability is unauthorized read of all show-visible fields of the related record. The severity of the exposure depends on the sensitivity of fields configured on the related resource (for example tokens, financial fields, or personal data), since those fields are rendered in the show view. This is a read-only exposure; it does not by itself allow modification of data.
Preconditions:
- An Avo v4 application (>= 4.2.10) with an authorization provider active
(Pundit policies configured; explicit_authorization defaults to true).
- A low-privilege authenticated user "mallory".
- A resource (e.g. User) that mallory can see in scope (e.g. their own record,
id=42), which has an association (e.g. has_many :orders) to a resource whose
OrderPolicy#show? would deny mallory access to order id=7.Reproduction steps:
mallory.GET /admin/resources/orders/7 returns a Not Authorized response because OrderPolicy#show? is enforced on ResourcesController.mallory can access.GET /admin/resources/users/42/orders/7 HTTP/1.1
Host: target
Cookie: <mallory authenticated session>HTTP/1.1 200 OK
The full show page for Order #7 is rendered, including every show-visible
field, even though OrderPolicy#show? for mallory returns false. No
authorization check ran on the association show path.GET /resources/:resource_name/:id/:related_name/:related_id is registered for every Avo resource and dispatches to Avo::AssociationsController#show (config/routes/dynamic_routes.rb:39). An authenticated attacker reaches it; _authenticate! (app/controllers/avo/base_application_controller.rb:25) only verifies the session.resource_name, id, related_name, and related_id. The parent id must resolve within the user's policy scope (set_record, app/controllers/avo/base_application_controller.rb:139-148), which the attacker satisfies with a record they legitimately see, such as their own.set_related_record (app/controllers/avo/base_application_controller.rb:150-157) loads the related record via @related_resource.find_record params[:related_id], query: @record.send(association_name), a raw ActiveRecord association, so no policy scope is applied to the related record.app/controllers/avo/base_controller.rb:15), and no before_action authorizes the show action (app/controllers/avo/associations_controller.rb:14-16 cover only index, create, and destroy). No show? policy check runs.Avo::AssociationsController#show (app/controllers/avo/associations_controller.rb:43-49) reassigns @resource and @record to the related resource and record and calls super, reaching BaseController#show (app/controllers/avo/base_controller.rb:86-104), which renders the full show view.show? policy was meant to protect.The relevant protection is the per-action authorization gate that Avo enforces for ordinary resource controllers. For the AssociationsController this gate is removed by the controller_name != "associations" condition at app/controllers/avo/base_controller.rb:15, confirmed by the adjacent comment at line 14. The controller re-adds authorization only for index, new/create, and destroy (app/controllers/avo/associations_controller.rb:14-16); show has no replacement. A negative control confirms the asymmetry: requesting the same record directly through GET /resources/orders/7 routes to ResourcesController, where the gate fires (because controller_name is "orders") and OrderPolicy#show? is enforced, while the association route GET /resources/users/42/orders/7 renders the record without any check. The strongest counter-argument, that the parent record's policy scope substitutes for authorization, does not hold: the parent scope only constrains which parent the attacker starts from, and the related record is loaded through the raw association without any policy scope, so scope access to a parent does not imply permission to view its associated records. This is a missing authorization check in the current code, not an incomplete prior fix; no earlier advisory covers this controller or path.
rubygemsavo>= 4.2.10, <= 4.3.24.3.2 (RubyGems)show authorization and the controller-level exclusion are present in the v4 BaseController/AssociationsController introduced in commit 83a2c8c, first released as 4.2.10, and remain through the latest published release 4.3.2. The lower bound reflects the earliest v4.x release available for inspection; earlier v4.x releases (4.2.5 through 4.2.9) were published from a codebase not available in this checkout, so whether they are affected is not established.Enforce an authorization check on the association show action equivalent to the protection applied to ordinary resource show pages. Add a before_action for show that authorizes against the related resource's show? policy (mirroring how index, create, and destroy are handled), and load the related record through a policy-scoped query rather than the raw association so the related resource's scope is applied. The fix must cover the record actually rendered (the related record), not only the parent, and should preserve the existing behavior for the already-guarded actions.
Reported by zx.
Fonte: NVD
Valutazione gratuita delle vulnerabilità
Valuta le tue pratiche di sicurezza del cloud in 9 domini di sicurezza per stabilire un benchmark del tuo livello di rischio e identificare le lacune nelle tue difese.
Richiedi una demo personalizzata
"La migliore esperienza utente che abbia mai visto offre piena visibilità ai carichi di lavoro cloud."
"Wiz fornisce un unico pannello di controllo per vedere cosa sta succedendo nei nostri ambienti cloud."
"Sappiamo che se Wiz identifica qualcosa come critico, in realtà lo è."