Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Respect user enumeration settings in user status lists #27879

Closed
wants to merge 1 commit into from

Conversation

mejo-
Copy link
Member

@mejo- mejo- commented Jul 8, 2021

The functions to find user statuses listed didn't respect user
enumeration settings (shareapi_allow_share_dialog_user_enumeration
and shareapi_restrict_user_enumeration_to_group core app settings).

Fixes: #27122

@mejo- mejo- force-pushed the fix/user_status_enumeration branch 4 times, most recently from 9ded77f to 260b3ed Compare July 8, 2021 17:12
@mejo- mejo- requested a review from PVince81 July 8, 2021 17:13
@mejo- mejo- force-pushed the fix/user_status_enumeration branch from 260b3ed to 8b50919 Compare July 8, 2021 17:17
@mejo-
Copy link
Member Author

mejo- commented Jul 8, 2021

As mentioned in issue #27122, I'd prefer to remove the route Statuses#findAll and statusService->findAll() altogether. But in order to be the least intrusive, for now this PR only implements the second part of my suggested fix:

Make statusService->findAllRecentStatusChanges return an empty array if config option shareapi_allow_share_dialog_user_enumeration is disabled.

Please let me know what you think about removing the findAll routes and functions.

@mejo- mejo- added 3. to review Waiting for reviews privacy security labels Jul 8, 2021
@szaimen szaimen added this to the Nextcloud 23 milestone Jul 8, 2021
@nickvergessen
Copy link
Member

From my POV this is not enumeration. You can not start to type a name and find the users. but of course since the limit and offset are controlled, you can still create a user list, so sounds good.

But if shareapi_restrict_user_enumeration_to_phone or shareapi_restrict_user_enumeration_to_group is enabled we should return those users I think. Maybe

if ($this->shareWithGroupOnly || $this->shareeEnumerationInGroupOnly) {
// Search in all the groups this user is part of
foreach ($currentUserGroups as $userGroupId) {
$usersInGroup = $this->groupManager->displayNamesInGroup($userGroupId, $search, $limit, $offset);
foreach ($usersInGroup as $userId => $displayName) {
$userId = (string) $userId;
$user = $this->userManager->get($userId);
if (!$user->isEnabled()) {
// Ignore disabled users
continue;
}
$users[$userId] = $user;
}
if (count($usersInGroup) >= $limit) {
$hasMoreResults = true;
}
}
if (!$this->shareWithGroupOnly && $this->shareeEnumerationPhone) {
$usersTmp = $this->userManager->searchKnownUsersByDisplayName($currentUserId, $search, $limit, $offset);
if (!empty($usersTmp)) {
foreach ($usersTmp as $user) {
if ($user->isEnabled()) { // Don't keep deactivated users
$users[$user->getUID()] = $user;
}
}
uasort($users, function ($a, $b) {
/**
* @var \OC\User\User $a
* @var \OC\User\User $b
*/
return strcasecmp($a->getDisplayName(), $b->getDisplayName());
});
}
}
can give you some inspiration

@mejo-
Copy link
Member Author

mejo- commented Jul 15, 2021

From my POV this is not enumeration. You can not start to type a name and find the users. but of course since the limit and offset are controlled, you can still create a user list, so sounds good.

You're right, strictly speaking it's not enumeration. But with the Statuses#findAll route, you can simply get a list of all users on the instance, which is even worse than enumeration 😉 And as you said, by controlling limits and offsets, it's possible to get all users even with the Statuses#find route.

@mejo-
Copy link
Member Author

mejo- commented Jul 15, 2021

But if shareapi_restrict_user_enumeration_to_phone or shareapi_restrict_user_enumeration_to_group is enabled we should return those users I think.

If I understand it correctly, then this would be further limitations to if shareapi_allow_share_dialog_user_enumeration is enabled, right? If shareapi_allow_share_dialog_user_enumeration is disabled, then it's not possible to select those two options you mentioned. So my understanding is that they're there to limit the scope of user enumeration in case it's enabled in general.

So far, this PR is about fixing the user_status API to respect admins choice to disable user enumeration altogether.

Would you prefer to implement support for shareapi_restrict_user_enumeration_to_phone and shareapi_restrict_user_enumeration_to_group in this PR as well? If you want me to, I could certainly look into it. But it would increase scope and complexibility of this PR a lot 😉

@nickvergessen
Copy link
Member

So my understanding is that they're there to limit the scope of user enumeration in case it's enabled in general.

Yeah, you are right. My head tricked me thinking it was the other way around.

Would you prefer to implement support for shareapi_restrict_user_enumeration_to_phone and shareapi_restrict_user_enumeration_to_group in this PR as well? If you want me to, I could certainly look into it. But it would increase scope and complexibility of this PR a lot wink

Yes, because either we say the setting does influence it, then the further settings should too, or not then we don't need this PR or a follow up.

@mejo- mejo- force-pushed the fix/user_status_enumeration branch from 8b50919 to 393721d Compare July 28, 2021 14:19
@mejo- mejo- changed the title Return empty user status list if user enumeration is disabled (Fixes: #27122) Respect user enumeration settings in user status lists Jul 28, 2021
@mejo- mejo- force-pushed the fix/user_status_enumeration branch 3 times, most recently from 24952d4 to 6ef3218 Compare July 28, 2021 21:20
@mejo-
Copy link
Member Author

mejo- commented Jul 28, 2021

So I took a deeper look now and changed the logic to respect both shareapi_allow_share_dialog_user_enumeration and shareapi_restrict_user_enumeration_to_group as suggested by @nickvergessen 😊

As far as I understand, shareapi_restrict_user_enumeration_to_phone is not relevant here as it's only about limiting partial matches for particular user names.

@mejo- mejo- force-pushed the fix/user_status_enumeration branch 4 times, most recently from f048df1 to bb3e7e1 Compare July 30, 2021 22:27
@mejo-
Copy link
Member Author

mejo- commented Jul 30, 2021

Now all tests are passing again. Sorry, the last days CI had some hickups and I didn't spot that the drone check didn't pass due to errors in the unit tests.

@mejo- mejo- requested review from julien-nc, szaimen and icewind1991 and removed request for nickvergessen August 3, 2021 10:07
@mejo-
Copy link
Member Author

mejo- commented Aug 10, 2021

Mh, any chance to get a review here 😊

@nickvergessen
Copy link
Member

As far as I understand, shareapi_restrict_user_enumeration_to_phone is not relevant here as it's only about limiting partial matches for particular user names.

Well so it should also be respected if possible.

Basically if:

  • shareapi_allow_share_dialog_user_enumeration: yes
  • shareapi_restrict_user_enumeration_to_group: no
  • shareapi_restrict_user_enumeration_to_phone: yes

you should only see users which you have the phone number matched.
But I would be okay to ignore it for now and fix this in a follow up as it increases complexity a lot.

@szaimen szaimen added 2. developing Work in progress and removed 3. to review Waiting for reviews labels Aug 31, 2021
@mejo-
Copy link
Member Author

mejo- commented Sep 7, 2021

But I would be okay to ignore it for now and fix this in a follow up as it increases complexity a lot.

@nickvergessen thanks for your feedback 😊

So are you ok with the PR as is or do you see the need for further changes/improvements?

}
}

return $usersByGroups;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this does not scale. We need to do it in another way. In worst case someone is in hundreds of (automated) groups, you run hundreds of queries to generate the user list to then later know that they don't even have a status set or something. Can't we do it similar to lib/private/Collaboration/Collaborators/UserPlugin.php and first get the recent user statuses and then filter out the results?
Basically get the status of 100 people, then filter out, if less than the requested users remain retry

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mhhh, you certainly have an argument here 😬

But I'm unsure whether the other way around scales better: It's rather unlikely that the desired 8 users from shared groups with recent status changes are amongh the first 100. So in many cases we'll end up iterating over all users with recent status changes. And for each user we have to check whether they're in a shared group.

So I see two approaches and I'm not sure which one scales better:

  • Iterate over all usergroups and their members, return a list of users. Filter the search for user statuses by this list of users.
  • Iterate over most users with recent status changes. For some/many of them, check whether we're in a shared group.

@nickvergessen you're way more experienced, so I'd trust you on what scales better on common setups/instances.

Besides: I'm not sure what you mean with your reference to lib/private/Collaboration/Collaborators/UserPlugin.php. I mostly copied its implementation to search for users from shared groups. Looking at lib/private/Collaboration/Collaborators/UserPlugin.php#L98-L115, it iterates over all members of all groups that the user is member of just like the implementation in this PR, no? Maybe I miss something :grimaced:

@skjnldsv skjnldsv mentioned this pull request Oct 13, 2021
So far, the functions to find user statuses listed didn't respect user
enumeration settings (`shareapi_allow_share_dialog_user_enumeration`
and `shareapi_restrict_user_enumeration_to_group` core app settings).

Fixes: #27122

Signed-off-by: Jonas Meurer <jonas@freesources.org>
@mejo- mejo- force-pushed the fix/user_status_enumeration branch from bb3e7e1 to 80d472d Compare October 15, 2021 10:48
mejo- added a commit that referenced this pull request Oct 15, 2021
So far, the functions to find user statuses listed didn't respect user
enumeration settings (`shareapi_allow_share_dialog_user_enumeration`
and `shareapi_restrict_user_enumeration_to_group` core app settings).

Fix this privacy issue by returning an empty list in case
`shareapi_allow_share_dialog_user_enumeration` is unset or
`shareapi_restrict_user_enumeration_to_group` is set.

In the long run, we might want to return users from common groups if
`shareapi_restrict_user_enumeration_to_group` is set. It's complicated
to implement this in a way that scales, though. See the discussion at
#27879 (review)
for details.

Also, don't register the user_status dashboard widget at all if
`shareapi_allow_share_dialog_user_enumeration` is unset or
`shareapi_restrict_user_enumeration_to_group` is set.

Fixes: #27122

Signed-off-by: Jonas Meurer <jonas@freesources.org>
mejo- added a commit that referenced this pull request Oct 15, 2021
So far, the functions to find user statuses listed didn't respect user
enumeration settings (`shareapi_allow_share_dialog_user_enumeration`
and `shareapi_restrict_user_enumeration_to_group` core app settings).

Fix this privacy issue by returning an empty list in case
`shareapi_allow_share_dialog_user_enumeration` is unset or
`shareapi_restrict_user_enumeration_to_group` is set.

In the long run, we might want to return users from common groups if
`shareapi_restrict_user_enumeration_to_group` is set. It's complicated
to implement this in a way that scales, though. See the discussion at
#27879 (review)
for details.

Also, don't register the user_status dashboard widget at all if
`shareapi_allow_share_dialog_user_enumeration` is unset or
`shareapi_restrict_user_enumeration_to_group` is set.

Fixes: #27122

Signed-off-by: Jonas Meurer <jonas@freesources.org>
@mejo-
Copy link
Member Author

mejo- commented Oct 15, 2021

After further discussion with @nickvergessen, we'll go with a more drastic and simpler approach that fixes the privacy issue first. See #29260.

@mejo- mejo- closed this Oct 15, 2021
mejo- added a commit that referenced this pull request Oct 16, 2021
So far, the functions to find user statuses listed didn't respect user
enumeration settings (`shareapi_allow_share_dialog_user_enumeration`
and `shareapi_restrict_user_enumeration_to_group` core app settings).

Fix this privacy issue by returning an empty list in case
`shareapi_allow_share_dialog_user_enumeration` is unset or
`shareapi_restrict_user_enumeration_to_group` is set.

In the long run, we might want to return users from common groups if
`shareapi_restrict_user_enumeration_to_group` is set. It's complicated
to implement this in a way that scales, though. See the discussion at
#27879 (review)
for details.

Also, don't register the user_status dashboard widget at all if
`shareapi_allow_share_dialog_user_enumeration` is unset or
`shareapi_restrict_user_enumeration_to_group` is set.

Fixes: #27122

Signed-off-by: Jonas Meurer <jonas@freesources.org>
@ChristophWurst ChristophWurst deleted the fix/user_status_enumeration branch October 18, 2021 08:00
mejo- added a commit that referenced this pull request Oct 19, 2021
So far, the functions to find user statuses listed didn't respect user
enumeration settings (`shareapi_allow_share_dialog_user_enumeration`
and `shareapi_restrict_user_enumeration_to_group` core app settings).

Fix this privacy issue by returning an empty list in case
`shareapi_allow_share_dialog_user_enumeration` is unset or
`shareapi_restrict_user_enumeration_to_group` is set.

In the long run, we might want to return users from common groups if
`shareapi_restrict_user_enumeration_to_group` is set. It's complicated
to implement this in a way that scales, though. See the discussion at
#27879 (review)
for details.

Also, don't register the user_status dashboard widget at all if
`shareapi_allow_share_dialog_user_enumeration` is unset or
`shareapi_restrict_user_enumeration_to_group` is set.

Fixes: #27122

Signed-off-by: Jonas Meurer <jonas@freesources.org>
mejo- added a commit that referenced this pull request Oct 20, 2021
So far, the functions to find user statuses listed didn't respect user
enumeration settings (`shareapi_allow_share_dialog_user_enumeration`
and `shareapi_restrict_user_enumeration_to_group` core app settings).

Fix this privacy issue by returning an empty list in case
`shareapi_allow_share_dialog_user_enumeration` is unset or
`shareapi_restrict_user_enumeration_to_group` is set.

In the long run, we might want to return users from common groups if
`shareapi_restrict_user_enumeration_to_group` is set. It's complicated
to implement this in a way that scales, though. See the discussion at
#27879 (review)
for details.

Also, don't register the user_status dashboard widget at all if
`shareapi_allow_share_dialog_user_enumeration` is unset or
`shareapi_restrict_user_enumeration_to_group` is set.

Fixes: #27122

Signed-off-by: Jonas Meurer <jonas@freesources.org>
mejo- added a commit that referenced this pull request Oct 25, 2021
So far, the functions to find user statuses listed didn't respect user
enumeration settings (`shareapi_allow_share_dialog_user_enumeration`
and `shareapi_restrict_user_enumeration_to_group` core app settings).

Fix this privacy issue by returning an empty list in case
`shareapi_allow_share_dialog_user_enumeration` is unset or
`shareapi_restrict_user_enumeration_to_group` is set.

In the long run, we might want to return users from common groups if
`shareapi_restrict_user_enumeration_to_group` is set. It's complicated
to implement this in a way that scales, though. See the discussion at
#27879 (review)
for details.

Also, don't register the user_status dashboard widget at all if
`shareapi_allow_share_dialog_user_enumeration` is unset or
`shareapi_restrict_user_enumeration_to_group` is set.

Fixes: #27122

Signed-off-by: Jonas Meurer <jonas@freesources.org>
mejo- added a commit that referenced this pull request Oct 25, 2021
So far, the functions to find user statuses listed didn't respect user
enumeration settings (`shareapi_allow_share_dialog_user_enumeration`
and `shareapi_restrict_user_enumeration_to_group` core app settings).

Fix this privacy issue by returning an empty list in case
`shareapi_allow_share_dialog_user_enumeration` is unset or
`shareapi_restrict_user_enumeration_to_group` is set.

In the long run, we might want to return users from common groups if
`shareapi_restrict_user_enumeration_to_group` is set. It's complicated
to implement this in a way that scales, though. See the discussion at
#27879 (review)
for details.

Also, don't register the user_status dashboard widget at all if
`shareapi_allow_share_dialog_user_enumeration` is unset or
`shareapi_restrict_user_enumeration_to_group` is set.

Fixes: #27122

Signed-off-by: Jonas Meurer <jonas@freesources.org>
mejo- added a commit that referenced this pull request Oct 25, 2021
So far, the functions to find user statuses listed didn't respect user
enumeration settings (`shareapi_allow_share_dialog_user_enumeration`
and `shareapi_restrict_user_enumeration_to_group` core app settings).

Fix this privacy issue by returning an empty list in case
`shareapi_allow_share_dialog_user_enumeration` is unset or
`shareapi_restrict_user_enumeration_to_group` is set.

In the long run, we might want to return users from common groups if
`shareapi_restrict_user_enumeration_to_group` is set. It's complicated
to implement this in a way that scales, though. See the discussion at
#27879 (review)
for details.

Also, don't register the user_status dashboard widget at all if
`shareapi_allow_share_dialog_user_enumeration` is unset or
`shareapi_restrict_user_enumeration_to_group` is set.

Fixes: #27122

Signed-off-by: Jonas Meurer <jonas@freesources.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

user_status "last statuses" widget leaks account names
3 participants