Closed Bug 824399 (CVE-2013-0786) Opened 12 years ago Closed 11 years ago

[SECURITY] build_subselect() leaks the existence of products and components you cannot access

Categories

(Bugzilla :: Query/Bug List, defect)

2.17.1
defect
Not set
normal

Tracking

()

RESOLVED FIXED
Bugzilla 3.6

People

(Reporter: LpSolit, Assigned: mail)

References

Details

(Whiteboard: [doesn't affect the 4.2 branch])

Attachments

(3 files, 4 obsolete files)

In Bugzilla 2.17.1 (bug 179960), Bugzilla::Search::build_subselect() was introduced to improve performance when querying products and components. Its job is to run the subselect itself and return the corresponding product/component IDs. But by doing this, it leaks the existence of products and components you cannot see.

If you try to directly access a product you cannot see, Bugzilla will throw an error of the form "either this product doesn't exist, or you don't have access to it". This means you have no way to know if this product exists, as expected. But when running queries, build_subselect() will return 1=2 if the product doesn't exist at all, else it will return the product ID. So you can use this trick to determine if a product doesn't exist at all, or exists but you are not allowed to access it.

Bugzilla 2.17.1 to 4.0.x are affected (due to bug 179960), then 4.1.1 to 4.4rc1 are not affected (due to bug 579568), and 4.4rc1+ to 4.5 are affected again (due to bug 780820). As we didn't release 4.4rc2 or 4.5.1 yet, only the 3.6.x and 4.0.x releases are affected by this issue.

There is a clear performance by running the subselects in build_subselect() itself and returning the IDs only, so we certainly don't want to revert that. So I have no idea how to fix this issue. The only way would be to disable the debug mode entirely, but that's too useful to be disabled.
f****
Group: bugzilla-security
Given bug 824262 is affected by the same issue (albeit not a security one) maybe the best option (for fixing both bugs) is have a new column in fielddefs (or hardcoded in Search.pm) whether to pre-compute sub selects or not) 

e.g. change the if statement in https://bug824262.bugzilla.mozilla.org/attachment.cgi?id=695242
No, because if we return subselects for products and components instead of returning the hardcoded list of IDs, the perf penalty is huge again. So from a performance point of view, it makes total sense to execute the subselects ourselves for products and components.

As I said in comment 0, maybe disabling the debug mode for non-admins (or some other group) is the only viable way to fix this issue.
Would it be possible to have the context of "visible products" specified as a condition to the subselect when generating queries?  That would solve the problem, too.
(In reply to Dave Miller from comment #4)
> Would it be possible to have the context of "visible products" specified as
> a condition to the subselect when generating queries?  That would solve the
> problem, too.

We cannot rely on the caller to think about security when calling Bugzilla::Search. As discussed on IRC, I'm not a fan to have build_subselect() add additional criteria itself when talking about products or components, because this means joining the group_control_map and the user_group_map tables, making the whole thing slower again. As we already filter bugs the user can see, this would mean doing security checks twice (more or less, because a product can be visible while a bug in this product is restricted to a group you don't belong to).

Honestly, 99% of users don't even know about this debug mode in buglist.cgi, and the remaining 1% is mostly developers. Developers usually test stuff on their own local test installation, where they are admins. So I would be in favor to restrict the debug mode to members of the admin group only. I don't want to regress performance of Bugzilla::Search because a few users may want to play with the debug mode to try to collect some info about products or components + other fields we may not think about (I guess group names have the same problem, ditto for target milestones and versions).

Moreover, it's reasonable to assume that on some installations which have their own (additional) code to get bugs, the content of the generated SQL query may reveal confidential data that admins wouldn't want to make public.
> So I would be in favor to restrict the debug mode to members of the admin group only.

this sounds like the best approach to me.

instead of hardcoding the admin group, it would be useful to have the group configurable so sites can choose to bless debug abilities onto trusted users without giving them full admin.
(In reply to Byron Jones ‹:glob› from comment #6)
> instead of hardcoding the admin group, it would be useful to have the group
> configurable so sites can choose to bless debug abilities onto trusted users
> without giving them full admin.

+1

Is anyone working on fixing this? If not, I'm happy to give this a crack on Monday (AEST).

One question though, should the group name by configured in the data/params file, like the insidergroup value is (default value: admin), or should I automatically create a new group?

I can imagine some installations may want to set this value as blank as either (a) they are not affected by this issue (no private products) or (b) the requiredlogin value is set.

  -- simon
(In reply to Simon Green from comment #7)
> Is anyone working on fixing this? If not, I'm happy to give this a crack on
> Monday (AEST).

Feel free to work on it.


> One question though, should the group name by configured in the data/params
> file, like the insidergroup value is (default value: admin), or should I
> automatically create a new group?

No need for a hardcoded group. Simply add a new param named e.g. "debugger_group", and set it to admin by default.


> I can imagine some installations may want to set this value as blank as
> either (a) they are not affected by this issue (no private products) or (b)
> the requiredlogin value is set.

Blank means nobody can access the feature, because nobody belongs to the group. That's the desired behavior.
(In reply to Frédéric Buclin from comment #8)
> Feel free to work on it.

Will do. I'll try and get this done on Monday.

> No need for a hardcoded group. Simply add a new param named e.g.
> "debugger_group", and set it to admin by default.

Sounds good to me.
 
> > I can imagine some installations may want to set this value as blank as
> > either (a) they are not affected by this issue (no private products) or (b)
> > the requiredlogin value is set.
> 
> Blank means nobody can access the feature, because nobody belongs to the
> group. That's the desired behavior.

For the reasons stated above, I would take blank to mean debug is available to everyone (most installations don't have a everybody group like bmo does)

  -- simon
Assignee: query-and-buglist → sgreen
(In reply to Simon Green from comment #9)
> For the reasons stated above, I would take blank to mean debug is available
> to everyone (most installations don't have a everybody group like bmo does)

No, else this param would behave in the exact opposite way of other group parameters. Leaving a group param blank always meant to disable the feature. I don't want to make an exception here.
(In reply to Frédéric Buclin from comment #10)
> I don't want to make an exception here.

Fair point.
Attached patch v1 patch (obsolete) — Splinter Review
First crack at this. Tested against trunk, patches cleanly against 4.0 (with offsets). I'm not entirely sure about the wording of the message on the parameters page. If you want it changed, please suggest an alternative :)

I also decided to silently ignore a user that tried to view debugging information without being in the appropriate group. If you want an error message to appear, let me know.
Attachment #698242 - Flags: review?
Comment on attachment 698242 [details] [diff] [review]
v1 patch

>=== modified file 'Bugzilla/Config/GroupSecurity.pm'

>+   name => 'debuggroup',

Let's name it debug_group, to follow our guidelines (old param names were using the foobar syntax instead of the more readable foo_bar).



>=== modified file 'buglist.cgi'

>+if ($cgi->param('debug')
>+    and $user->in_group(Bugzilla->params->{debuggroup})

Before calling $user->in_group(), you must make sure that debug_group is set. Also, let's use && instead of and, which is what we use 99.5% of the time.


You must also patch report.cgi and/or reports/report.html.tmpl which also have a debug mode.



>=== modified file 'template/en/default/admin/params/groupsecurity.html.tmpl'

>+  debuggroup => "The name of the group of users who can view the raw " _
>+                "SQL queries in buglist.cgi. Note: This can expose " _
>+                "private products and components. See " _
>+                "<a href=\"https://bugzilla.mozilla.org/show_bug.cgi?id=824399\">bug 824399</a> " _
>+                "for more information.",

Do not mention products and components specifically, nor the bug ID (that's not the right place for it anyway). Also, this parameter is not specific to buglist.cgi as report.cgi is involved too.
Attachment #698242 - Flags: review? → review-
Attached patch v2 patch (obsolete) — Splinter Review
Made the suggested changes. This patch is for trunk only. When it is r+, I'll generate patches for 4.4 and 4.0 too.
Attachment #698242 - Attachment is obsolete: true
Attachment #698320 - Flags: review?(LpSolit)
Flags: blocking4.4+
Comment on attachment 698320 [details] [diff] [review]
v2 patch

>=== modified file 'report.cgi'

>+my $debug = $cgi->param('debug')
>+    && Bugzilla->params->{debug_group}
>+    && Bugzilla->user->in_group(Bugzilla->params->{debug_group});

You must move this code after Bugzilla->login() is called, else Bugzilla->user doesn't point to the current user yet, and it always returns 0.


>-$format->{'ctype'} = "text/html" if $cgi->param('debug');
>+$format->{'ctype'} = "text/html" if $debug;

This change must be reverted. It's fine to display raw data for reports for all users, as it displays the same data as in the table itself, but in a different way.


>-if ($cgi->param('debug')) {
>+if ($debug) {

This change must be reverted too, for the same reason as above.

What must be fixed is this line:

    $vars->{'debug'} = $cgi->param('debug');

else the template still displays debug stuff about executed SQL queries.


Everything else is fine.
Attachment #698320 - Flags: review?(LpSolit) → review-
To be honest, I don't want this fix for 3.6 and 4.0. Adding a new group so late in these respective branches is not a good idea, IMO. 3.6 is going to reach EOL very soon anyway. 4.2 is not affected so that's not a problem and it doesn't need the fix. This leaves us with 4.4 and trunk only where I'm fine to take this fix.

What do you guys think?
Sounds reasonable.
I disagree. It should be fixed for Bugzilla 4.0. We aren't adding a new group, we are adding a new parameter. It's not ideal, but some sites (brc included) wouldn't want the existence of products shown.

Given that this bug was originally public, it is the reason we haven't put a 4.4rc1 preview on a public facing server.

Having said that brc is currently running 4.2, so from that perspective it doesn't bother me if you don't fix Bugzilla 4.0.
Looks like a simple enough patch to be safe in 4.0 to me.
Attached patch v3 patch (obsolete) — Splinter Review
Attachment #698320 - Attachment is obsolete: true
Attachment #703061 - Flags: review?(LpSolit)
(In reply to Dave Miller [:justdave] from comment #19)
> Looks like a simple enough patch to be safe in 4.0 to me.

The question is not about the patch being trivial/safe but about adding a new parameter in the 10th minor release of a stable branch. For 3.6, this would be the 13th minor release on that branch. Is that really what we want?
Comment on attachment 703061 [details] [diff] [review]
v3 patch

>=== modified file 'report.cgi'

>+if (Bugzilla->params->{debug_group}
>+    && Bugzilla->user->in_group(Bugzilla->params->{debug_group})
>+) {
>+    $vars->{'debug'} = $cgi->param('debug');
>+}

I would prefer a fix like you did for buglist.cgi, i.e.:

if ($cgi->param('debug')
    && Bugzilla->params->{debug_group}
    && Bugzilla->user->in_group(Bugzilla->params->{debug_group}))
{
    $vars->{'debug'} = 1;
}

This way we don't waste cycles into ->in_group() if the user didn't ask for debug stuff.


r=LpSolit with this comment fixed. Please upload an updated patch which includes this fix.
Attachment #703061 - Flags: review?(LpSolit) → review+
Flags: approval?
Flags: approval4.4?
(In reply to Frédéric Buclin from comment #21)
> (In reply to Dave Miller [:justdave] from comment #19)
> > Looks like a simple enough patch to be safe in 4.0 to me.
> 
> The question is not about the patch being trivial/safe but about adding a
> new parameter in the 10th minor release of a stable branch. For 3.6, this
> would be the 13th minor release on that branch. Is that really what we want?

Most of that argument is irrelevant because it's a security fix.  What we want is the safety and security of our users.
Attached patch v4 patch, 4.4 + trunk (obsolete) — Splinter Review
Attachment #703061 - Attachment is obsolete: true
Attachment #703629 - Flags: review?(LpSolit)
(In reply to Dave Miller [:justdave] from comment #23)
> Most of that argument is irrelevant because it's a security fix.

+1

> What we want is the safety and security of our users.

and of the company's data.
Comment on attachment 703629 [details] [diff] [review]
v4 patch, 4.4 + trunk

>=== modified file 'template/en/default/admin/params/groupsecurity.html.tmpl'

>+  debug_group => "The name of the group of users who can view the actual " _
>+                 "SQL query generated when viewing bug lists and reports.",

Oops, I just realized that you have "bug" hardcoded in the description. It must be $terms.bug. Could you please attach an updated patch with this fix? Everything else looks good and works fine. r=LpSolit
Attachment #703629 - Flags: review?(LpSolit) → review+
Comment on attachment 703629 [details] [diff] [review]
v4 patch, 4.4 + trunk

The patch doesn't apply cleanly to 4.2 and older (conflict in report.cgi). It needs to be backported.
Attachment #703629 - Attachment description: v4 patch → v4 patch, 4.4 + trunk
Status: NEW → ASSIGNED
Target Milestone: --- → Bugzilla 3.6
Blocks: 832267
@reed, @dveditz: we need a CVE number for this bug.
Flags: blocking4.0.10+
Flags: blocking3.6.13+
Now runtest compliant. I really need to run that before submitting bugs :)
Attachment #703629 - Attachment is obsolete: true
Attachment #703859 - Flags: review?(LpSolit)
Attachment #703860 - Flags: review?(LpSolit)
Comment on attachment 703859 [details] [diff] [review]
v5 patch, 4.4+trunk

Thanks! r=LpSolit
Attachment #703859 - Flags: review?(LpSolit) → review+
Attachment #703860 - Attachment description: v5 patch, 3.6, 4.0 and 4.2 → v5 patch, 4.0 and 4.2
Attached patch v5 patch, 3.6Splinter Review
Attachment #703863 - Flags: review?(LpSolit)
Comment on attachment 703860 [details] [diff] [review]
v5 patch, 4.0 and 4.2

r=LpSolit
Attachment #703860 - Flags: review?(LpSolit) → review+
Comment on attachment 703863 [details] [diff] [review]
v5 patch, 3.6

r=LpSolit
Attachment #703863 - Flags: review?(LpSolit) → review+
Flags: approval4.2?
Flags: approval4.0?
Flags: approval3.6?
(In reply to Frédéric Buclin from comment #28)
> @reed, @dveditz: we need a CVE number for this bug.

dveditz: ping?
CVE-2013-0786
Alias: CVE-2013-0786
Flags: approval?
Flags: approval4.4?
Flags: approval4.4+
Flags: approval4.2?
Flags: approval4.2+
Flags: approval4.0?
Flags: approval4.0+
Flags: approval3.6?
Flags: approval3.6+
Flags: approval+
Committing to: bzr+ssh://lpsolit%40gmail.com@bzr.mozilla.org/bugzilla/trunk/
modified buglist.cgi
modified report.cgi
modified Bugzilla/Config/GroupSecurity.pm
modified template/en/default/admin/params/groupsecurity.html.tmpl
Committed revision 8586.


Committing to: bzr+ssh://lpsolit%40gmail.com@bzr.mozilla.org/bugzilla/4.4/
modified buglist.cgi
modified report.cgi
modified Bugzilla/Config/GroupSecurity.pm
modified template/en/default/admin/params/groupsecurity.html.tmpl
Committed revision 8524.


Committing to: bzr+ssh://lpsolit%40gmail.com@bzr.mozilla.org/bugzilla/4.2/
modified buglist.cgi
modified report.cgi
modified Bugzilla/Config/GroupSecurity.pm
modified template/en/default/admin/params/groupsecurity.html.tmpl
Committed revision 8190.


Committing to: bzr+ssh://lpsolit%40gmail.com@bzr.mozilla.org/bugzilla/4.0/
modified buglist.cgi
modified report.cgi
modified Bugzilla/Config/GroupSecurity.pm
modified template/en/default/admin/params/groupsecurity.html.tmpl
Committed revision 7743.


Committing to: bzr+ssh://lpsolit%40gmail.com@bzr.mozilla.org/bugzilla/3.6/
modified buglist.cgi
modified report.cgi
modified Bugzilla/Config/GroupSecurity.pm
modified template/en/default/admin/params/groupsecurity.html.tmpl
Committed revision 7310.
Status: ASSIGNED → RESOLVED
Closed: 11 years ago
Resolution: --- → FIXED
Security advisory sent. Removing sec flag.
Group: bugzilla-security
Blocks: 1053802
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: