[wp-trac] [WordPress Trac] #49641: Clarify what happens when meta_value is `''` in get_users like functions.
WordPress Trac
noreply at wordpress.org
Fri Mar 13 17:13:41 UTC 2020
#49641: Clarify what happens when meta_value is `''` in get_users like functions.
-------------------------+-------------------------------------
Reporter: growthwp | Owner: (none)
Type: enhancement | Status: new
Priority: normal | Milestone: Awaiting Review
Component: Users | Version:
Severity: normal | Resolution:
Keywords: needs-docs | Focuses: docs, coding-standards
-------------------------+-------------------------------------
Changes (by SergeyBiryukov):
* keywords: needs-dev-note => needs-docs
* component: Query => Users
Old description:
> Because I didn't realize that doing this query:
>
> $all_user_ids = get_users([
> 'fields' => 'id',
> 'meta_key' => 'secret_access_key',
> 'meta_compare' => '=',
> 'meta_value' => $dynamic_value_from_frontend
> ]);
>
> Given the credibility, history & robustness of `get_users`, which entered
> under the hood of "that thing just works, don't doubt it", if
> {{{$dynamic_value_from_frontned}}} were to be just a mere`''`, instead of
> giving me an empty list of no users, **the query would return a list of
> all users.** What happens when you rely on this list for mission-critical
> things? The worst.
>
> In my case, this list was very crucial for allowing access to customer
> websites, based on a secret string only the developers, us, know, we are
> able to access these sites and inherit the identity of our customer
> (mostly admin accounts). The way we achieve this is we attach that secret
> phrase to their `user_meta` and as you can see, we attempt to hit an
> endpoint that looks at all the users and returns us with the one that
> matches the string we provided.
>
> Unfortunately, as I've said before, because our assumption, as well as
> our partners' and personal friends, some of whom are veterans in the
> industry, was that `get_users` would forfeit completely if not given a
> key at all, instead, it just simply decides to ignore the field
> completely and retrieve based on the key alone.
>
> The more interesting fact is that if we set the `meta_value` to `False`,
> it actually does the check and doesn't return any users.
>
> Here's a PoC: https://pastebin.com/vfaVuRp0
>
> Please make it clear that a `meta_value` that equals to `''` is not the
> same as it being `False` and that the system defaults to just using the
> key, skipping all checks. The desired behavior should be:
>
> 1. When the `meta_value` is missing altogether, it means we're searching
> just for key.
> 2. When the `meta_value` is `''`, it should be treated as a value and
> searched against.
> 3. When the `meta_value` is `False`, it should be treated as a value and
> searched against.
>
> I do recognize that it's probably impossible to go back and change this
> and so, for me at least, it's even more reason to push this very
> important note to the front.
>
> Please mention this in either the comments for `get_users`, in the
> codebase itself or make a phpcs rule for this. In other words, please
> specify that you must ensure the input for the `meta_value` is properly
> checked for before actually being used due to this exact case.
>
> Thank you.
>
> ----
>
> In our case, it would've been a disaster if we didn't fuzz around. While
> I completely understand it's us that should make sure whatever is passed
> is proper, I believe the community is not aware of this edge case not due
> to bad coding practices but simply due to the need to implement dynamic
> queries like this being very rare and as such, overlooked.
>
> We've also notified 4 vendors, one of which is perhaps the biggest in
> terms of reach about a potential issue with dynamic query building like
> we had. In the case of a membership plugin that seemed to have all
> security checks in place, as we did, it resulted in certain users being
> given access to another user's property.
New description:
Because I didn't realize that doing this query:
{{{
$all_user_ids = get_users([
'fields' => 'id',
'meta_key' => 'secret_access_key',
'meta_compare' => '=',
'meta_value' => $dynamic_value_from_frontend
]);
}}}
Given the credibility, history & robustness of `get_users`, which entered
under the hood of "that thing just works, don't doubt it", if
{{{$dynamic_value_from_frontned}}} were to be just a mere`''`, instead of
giving me an empty list of no users, **the query would return a list of
all users.** What happens when you rely on this list for mission-critical
things? The worst.
In my case, this list was very crucial for allowing access to customer
websites, based on a secret string only the developers, us, know, we are
able to access these sites and inherit the identity of our customer
(mostly admin accounts). The way we achieve this is we attach that secret
phrase to their `user_meta` and as you can see, we attempt to hit an
endpoint that looks at all the users and returns us with the one that
matches the string we provided.
Unfortunately, as I've said before, because our assumption, as well as our
partners' and personal friends, some of whom are veterans in the industry,
was that `get_users` would forfeit completely if not given a key at all,
instead, it just simply decides to ignore the field completely and
retrieve based on the key alone.
The more interesting fact is that if we set the `meta_value` to `False`,
it actually does the check and doesn't return any users.
Here's a PoC: https://pastebin.com/vfaVuRp0
Please make it clear that a `meta_value` that equals to `''` is not the
same as it being `False` and that the system defaults to just using the
key, skipping all checks. The desired behavior should be:
1. When the `meta_value` is missing altogether, it means we're searching
just for key.
2. When the `meta_value` is `''`, it should be treated as a value and
searched against.
3. When the `meta_value` is `False`, it should be treated as a value and
searched against.
I do recognize that it's probably impossible to go back and change this
and so, for me at least, it's even more reason to push this very important
note to the front.
Please mention this in either the comments for `get_users`, in the
codebase itself or make a phpcs rule for this. In other words, please
specify that you must ensure the input for the `meta_value` is properly
checked for before actually being used due to this exact case.
Thank you.
----
In our case, it would've been a disaster if we didn't fuzz around. While I
completely understand it's us that should make sure whatever is passed is
proper, I believe the community is not aware of this edge case not due to
bad coding practices but simply due to the need to implement dynamic
queries like this being very rare and as such, overlooked.
We've also notified 4 vendors, one of which is perhaps the biggest in
terms of reach about a potential issue with dynamic query building like we
had. In the case of a membership plugin that seemed to have all security
checks in place, as we did, it resulted in certain users being given
access to another user's property.
--
--
Ticket URL: <https://core.trac.wordpress.org/ticket/49641#comment:1>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list