Add reproduction test for v1 admin authz param-duplication bypass#13
Open
markrmiller wants to merge 6 commits into
Open
Add reproduction test for v1 admin authz param-duplication bypass#13markrmiller wants to merge 6 commits into
markrmiller wants to merge 6 commits into
Conversation
Demonstrates that custom (params-based) RuleBasedAuthorization rules match with any-value semantics (Permission.load + context.getParams().getParams()) while the admin handlers execute on the first value (params.get -> arr[0]). Supplying a security-relevant param twice lets a decoy authorized value make a narrow permission govern the request while the handler runs a different, unauthorized value (e.g. RELOAD allowed_collection authorizes DELETE forbidden_collection). The test asserts current (vulnerable) behavior and so serves as a reproduction; once a fix lands, the bypass cases should assert FORBIDDEN. https://claude.ai/code/session_019x1K815brY4h1FHr2SgyKr
…ion read authz A search request's entry-node authorization is keyed on the URL/path collection, while distributed execution routes by the 'collection' request param (CloudReplicaSource), and a form-body 'collection' value is invisible to the entry-node check. This test demonstrates that the asymmetry does not leak data across collections: the fan-out shard sub-request is independently re-authorized against the original principal and denied (403). Guards that per-shard re-authorization control against regression. https://claude.ai/code/session_019x1K815brY4h1FHr2SgyKr
…ollection admin A user restricted by a custom params permission to a single harmless action (LIST) escalates to deleting arbitrary collections by supplying 'action' more than once: authorization matches the decoy LIST value (any-value semantics) while CollectionsHandler executes the first value (DELETE). Unlike distributed search, collection admin has no second authorization gate before Overseer execution, so the unauthorized DELETE actually runs. Covers both the URL-vs-form -body split and pure URL duplication. Also documents that duplicating 'name' (per the original hypothesis) instead breaks the DELETE because 'name' is consumed as a multi-value array, so the working exploit duplicates only 'action'. https://claude.ai/code/session_019x1K815brY4h1FHr2SgyKr
Probes whether naming an authorized collection alongside the target (comma-list in body/URL, triple duplication, target-first) can get the shard sub-request past the target node's authorization, exploiting that authorize() is any-of over the collection list. It cannot: a shard sub-request targets a specific core and is re-authorized against that core's own collection, and the forwarded 'collection' value travels in the sub-request body -- invisible to the URL-only params that build the authorized collection list at the target -- so the target never short-circuits on the authorized collection. https://claude.ai/code/session_019x1K815brY4h1FHr2SgyKr
V2HttpCall parses a JSON request body into a content stream, not into SolrParams;
the command is parsed only at execution time via getCommands(), after authorize().
So a custom RuleBasedAuthorization permission keyed on params:{name:...} cannot see
a name supplied in a V2 JSON command body. The test pins this with an A/B on
POST /____v2/collections: a guard rule keyed on params:{name:supersecret} denies
the request when name is in the query string, but is bypassed (collection created)
when the same name is in the JSON body.
https://claude.ai/code/session_019x1K815brY4h1FHr2SgyKr
…t-value params Per-shard re-authorization protects the 'collection' dimension because the receiving core re-derives the authorized collection from the core it serves. A custom rule keyed on any other first-value param (here q) gets no such protection: the shard sub-request carries the full multi-valued param, so the receiving core makes the same any-value decision and then executes the first value. Demonstrates a 'pubonly' role allowed only q=id:pubdoc retrieving the secret doc via q=id:secretdoc&q=id:pubdoc. https://claude.ai/code/session_019x1K815brY4h1FHr2SgyKr
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Demonstrates that custom (params-based) RuleBasedAuthorization rules match
with any-value semantics (Permission.load + context.getParams().getParams())
while the admin handlers execute on the first value (params.get -> arr[0]).
Supplying a security-relevant param twice lets a decoy authorized value make a
narrow permission govern the request while the handler runs a different,
unauthorized value (e.g. RELOAD allowed_collection authorizes DELETE
forbidden_collection).
The test asserts current (vulnerable) behavior and so serves as a
reproduction; once a fix lands, the bypass cases should assert FORBIDDEN.
https://claude.ai/code/session_019x1K815brY4h1FHr2SgyKr