Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Page MenuHomePhabricator

Non-checkuser could get Checkuser data through SQL queries using process of elimination
Closed, InvalidPublicSecurity

Description

Problem:
Technically, after the actor and comment SQL table migration of the Checkuser tables are done T233004, an non-Checkuser could query the actor table, remove everything mentioned in the revision table and abusefilter tables and come pretty close to get an list over users that are only in Checkuser. The same applies to the comment table.

Also, migrating comments from Checkuser to the comments table also makes a lot of information public that would be in the checkuser log, which an non-checkuser does not normally have access to. If I visit Special:Log on an WMF wiki while logged out, I do not see the checkuser log, so, I should not see parts of it through the comment table.

Personally, I think the comment table migration has a worse effect.

Added Dreamy Jazz to the task since he has been working on said migration. I am also aware that he has an NDA through being an CheckUser, so that should be fine. Would not have done so otherwise.

Fix:
Is this an security or privacy risk ? If so, it might be better to have an separate comment (and actor?) table for CheckUser that would be private.

Details

Risk Rating
Informational
Author Affiliation
Wikimedia Communities

Event Timeline

Adding Zabe too.

You raise a good point, however, this is also the case for private logs that are stored in the logging table such as suppression. Also this would be the case for any revision deleted edit summaries. This may have been previously discussed for these two current examples.

Mitigating things:

  • The existence of an actor row not associated with a revision, public log or abuse filter entry is not possible for accounts. This is because a public log entry is generated when creating the account. For IPs, I'm not sure the existence of an actor row is a big deal. All it imparts is that said IP made some action and if filtered down to only being caused by something stored in CheckUser tables only lets a person know that some activity has happened on that IP

The actor and comment table in the public wiki replicas are filtered.

For actor the filter is defined through

actor:
  source: actor
  view: select actor_id, actor_user, actor_name
  where: >
    exists( select 1 from user where user_id = actor_user )
    AND (SELECT 1 from ipblocks where ipb_auto=0 AND ipb_deleted=1 AND ipb_user=actor_user) is NULL
    OR exists( select 1 from archive where ar_actor = actor_id AND ar_deleted&4 = 0 )
    OR exists( select 1 from ipblocks where ipb_by_actor = actor_id AND ipb_deleted=0 )
    OR exists( select 1 from image where img_actor = actor_id )
    OR exists( select 1 from oldimage where oi_actor = actor_id AND oi_deleted&4 = 0 )
    OR exists( select 1 from filearchive where fa_actor = actor_id AND fa_deleted&4 = 0 )
    OR exists( select 1 from recentchanges where rc_actor = actor_id AND rc_deleted&4 = 0 )
    OR exists( select 1 from logging where log_actor = actor_id AND log_deleted&4 = 0 AND $INSERTED_EXPR$ )
    OR exists( select 1 from revision WHERE rev_actor = actor_id AND rev_deleted&4 = 0 )
  logging_where:
    *allowed_logtypes

from https://gerrit.wikimedia.org/r/plugins/gitiles/operations/puppet/+/refs/heads/production/modules/profile/templates/wmcs/db/wikireplicas/maintain-views.yaml#252.
And for comment the filter is defined through

comment:
  source: comment
  view: >
    select comment_id, comment_hash, comment_text, comment_data
  where: >
    exists( select 1 from image where img_description_id = comment_id )
    OR exists( select 1 from filearchive where fa_deleted_reason_id = comment_id )
    OR exists( select 1 from filearchive where fa_description_id = comment_id AND fa_deleted&2 = 0 )
    OR exists( select 1 from ipblocks where ipb_reason_id = comment_id and ipb_deleted = 0)
    OR exists( select 1 from oldimage where oi_description_id = comment_id AND oi_deleted&2 = 0 )
    OR exists( select 1 from protected_titles where pt_reason_id = comment_id )
    OR exists( select 1 from recentchanges where rc_comment_id = comment_id AND rc_deleted&2 = 0 )
    OR exists( select 1 from revision JOIN revision_comment_temp ON(revcomment_rev = rev_id) where revcomment_comment_id = comment_id AND rev_deleted&2 = 0 )
    OR exists( select 1 from logging where log_comment_id = comment_id AND log_deleted&2 = 0 AND $INSERTED_EXPR$ )
  logging_where:
    *allowed_logtypes

from https://gerrit.wikimedia.org/r/plugins/gitiles/operations/puppet/+/refs/heads/production/modules/profile/templates/wmcs/db/wikireplicas/maintain-views.yaml#358.

Thus, in the tables you can only see things that are visible through another public table and no data is leaked.

However, of course, you should keep two things in mind:

  1. these filters may not be complete/contain errors (however, the filter here seems to me to be complete).
  2. you can see that hidden data exists due to the lack of autoincrement id's, however I don't think this is a real problem.

(Posted before I saw the above - removing as explained above).

...
Thus, in the tables you can only see things that are visible through another public table and no data is leaked.

However, of course, you should keep two things in mind:

  1. these filters may not be complete/contain errors (however, the filter here seems to me to be complete).
  2. you can see that hidden data exists due to the lack of autoincrement id's, however I don't think this is a real problem.

Thanks for the good explanation.

If we've found actual leaks within the replicas or MediaWiki UIs / APIs, then addressing those specific issues would certainly be actionable here. But given the discussion above, it doesn't sound like that's the case? So this task can likely be resolved as invalid?

Yep, as far as I can see, there is no leak here.

sbassett triaged this task as Lowest priority.
sbassett edited projects, added SecTeam-Processed; removed Security-Team.
sbassett changed the visibility from "Custom Policy" to "Public (No Login Required)".
sbassett changed the edit policy from "Custom Policy" to "All Users".
sbassett changed Risk Rating from N/A to Informational.