Commit 9e186bdd authored by Frédéric Buclin's avatar Frédéric Buclin Committed by David Lawrence

Bug 1075578: [SECURITY] Improper filtering of CGI arguments

r=dkl,a=sgreen
parent 553568dd
...@@ -96,10 +96,9 @@ sub init { ...@@ -96,10 +96,9 @@ sub init {
if ($self->{'datefrom'} && $self->{'dateto'} && if ($self->{'datefrom'} && $self->{'dateto'} &&
$self->{'datefrom'} > $self->{'dateto'}) $self->{'datefrom'} > $self->{'dateto'})
{ {
ThrowUserError("misarranged_dates", ThrowUserError('misarranged_dates', { 'datefrom' => scalar $cgi->param('datefrom'),
{'datefrom' => $cgi->param('datefrom'), 'dateto' => scalar $cgi->param('dateto') });
'dateto' => $cgi->param('dateto')}); }
}
} }
# Alter Chart so that the selected series are added to it. # Alter Chart so that the selected series are added to it.
......
...@@ -196,8 +196,9 @@ sub validateContext ...@@ -196,8 +196,9 @@ sub validateContext
{ {
my $context = $cgi->param('context') || "patch"; my $context = $cgi->param('context') || "patch";
if ($context ne "file" && $context ne "patch") { if ($context ne "file" && $context ne "patch") {
detaint_natural($context) my $orig_context = $context;
|| ThrowUserError("invalid_context", { context => $cgi->param('context') }); detaint_natural($context)
|| ThrowUserError("invalid_context", { context => $orig_context });
} }
return $context; return $context;
...@@ -515,13 +516,14 @@ sub insert { ...@@ -515,13 +516,14 @@ sub insert {
# Get the filehandle of the attachment. # Get the filehandle of the attachment.
my $data_fh = $cgi->upload('data'); my $data_fh = $cgi->upload('data');
my $attach_text = $cgi->param('attach_text');
my $attachment = Bugzilla::Attachment->create( my $attachment = Bugzilla::Attachment->create(
{bug => $bug, {bug => $bug,
creation_ts => $timestamp, creation_ts => $timestamp,
data => scalar $cgi->param('attach_text') || $data_fh, data => $attach_text || $data_fh,
description => scalar $cgi->param('description'), description => scalar $cgi->param('description'),
filename => $cgi->param('attach_text') ? "file_$bugid.txt" : scalar $cgi->upload('data'), filename => $attach_text ? "file_$bugid.txt" : $data_fh,
ispatch => scalar $cgi->param('ispatch'), ispatch => scalar $cgi->param('ispatch'),
isprivate => scalar $cgi->param('isprivate'), isprivate => scalar $cgi->param('isprivate'),
mimetype => $content_type, mimetype => $content_type,
......
...@@ -945,7 +945,7 @@ if (scalar(@products) == 1) { ...@@ -945,7 +945,7 @@ if (scalar(@products) == 1) {
# This is used in the "Zarroo Boogs" case. # This is used in the "Zarroo Boogs" case.
elsif (my @product_input = $cgi->param('product')) { elsif (my @product_input = $cgi->param('product')) {
if (scalar(@product_input) == 1 and $product_input[0] ne '') { if (scalar(@product_input) == 1 and $product_input[0] ne '') {
$one_product = Bugzilla::Product->new({ name => $cgi->param('product'), cache => 1 }); $one_product = Bugzilla::Product->new({ name => $product_input[0], cache => 1 });
} }
} }
# We only want the template to use it if the user can actually # We only want the template to use it if the user can actually
......
...@@ -41,23 +41,24 @@ my @products = @{$vars->{products}}; ...@@ -41,23 +41,24 @@ my @products = @{$vars->{products}};
my $action = $cgi->param('action') || 'list'; my $action = $cgi->param('action') || 'list';
my $token = $cgi->param('token'); my $token = $cgi->param('token');
my $product = $cgi->param('product'); my $prod_name = $cgi->param('product');
my $component = $cgi->param('component'); my $comp_name = $cgi->param('component');
my $flag_id = $cgi->param('id'); my $flag_id = $cgi->param('id');
if ($product) { my ($product, $component);
if ($prod_name) {
# Make sure the user is allowed to view this product name. # Make sure the user is allowed to view this product name.
# Users with global editcomponents privs can see all product names. # Users with global editcomponents privs can see all product names.
($product) = grep { lc($_->name) eq lc($product) } @products; ($product) = grep { lc($_->name) eq lc($prod_name) } @products;
$product || ThrowUserError('product_access_denied', { name => $cgi->param('product') }); $product || ThrowUserError('product_access_denied', { name => $prod_name });
} }
if ($component) { if ($comp_name) {
($product && $product->id) $product || ThrowUserError('flag_type_component_without_product');
|| ThrowUserError('flag_type_component_without_product'); ($component) = grep { lc($_->name) eq lc($comp_name) } @{$product->components};
($component) = grep { lc($_->name) eq lc($component) } @{$product->components};
$component || ThrowUserError('product_unknown_component', { product => $product->name, $component || ThrowUserError('product_unknown_component', { product => $product->name,
comp => $cgi->param('component') }); comp => $comp_name });
} }
# If 'categoryAction' is set, it has priority over 'action'. # If 'categoryAction' is set, it has priority over 'action'.
......
...@@ -224,7 +224,7 @@ if ($action eq 'new') { ...@@ -224,7 +224,7 @@ if ($action eq 'new') {
if ($action eq 'del') { if ($action eq 'del') {
# Check that an existing group ID is given # Check that an existing group ID is given
my $group = Bugzilla::Group->check({ id => $cgi->param('group') }); my $group = Bugzilla::Group->check({ id => scalar $cgi->param('group') });
$group->check_remove({ test_only => 1 }); $group->check_remove({ test_only => 1 });
$vars->{'shared_queries'} = $vars->{'shared_queries'} =
$dbh->selectrow_array('SELECT COUNT(*) $dbh->selectrow_array('SELECT COUNT(*)
...@@ -248,7 +248,7 @@ if ($action eq 'del') { ...@@ -248,7 +248,7 @@ if ($action eq 'del') {
if ($action eq 'delete') { if ($action eq 'delete') {
check_token_data($token, 'delete_group'); check_token_data($token, 'delete_group');
# Check that an existing group ID is given # Check that an existing group ID is given
my $group = Bugzilla::Group->check({ id => $cgi->param('group') }); my $group = Bugzilla::Group->check({ id => scalar $cgi->param('group') });
$vars->{'name'} = $group->name; $vars->{'name'} = $group->name;
$group->remove_from_db({ $group->remove_from_db({
remove_from_users => scalar $cgi->param('removeusers'), remove_from_users => scalar $cgi->param('removeusers'),
......
...@@ -152,7 +152,10 @@ if (defined $cgi->param('version')) { ...@@ -152,7 +152,10 @@ if (defined $cgi->param('version')) {
# after the bug is filed. # after the bug is filed.
# Add an attachment if requested. # Add an attachment if requested.
if (defined($cgi->upload('data')) || $cgi->param('attach_text')) { my $data_fh = $cgi->upload('data');
my $attach_text = $cgi->param('attach_text');
if ($data_fh || $attach_text) {
$cgi->param('isprivate', $cgi->param('comment_is_private')); $cgi->param('isprivate', $cgi->param('comment_is_private'));
# Must be called before create() as it may alter $cgi->param('ispatch'). # Must be called before create() as it may alter $cgi->param('ispatch').
...@@ -167,9 +170,9 @@ if (defined($cgi->upload('data')) || $cgi->param('attach_text')) { ...@@ -167,9 +170,9 @@ if (defined($cgi->upload('data')) || $cgi->param('attach_text')) {
$attachment = Bugzilla::Attachment->create( $attachment = Bugzilla::Attachment->create(
{bug => $bug, {bug => $bug,
creation_ts => $timestamp, creation_ts => $timestamp,
data => scalar $cgi->param('attach_text') || $cgi->upload('data'), data => $attach_text || $data_fh,
description => scalar $cgi->param('description'), description => scalar $cgi->param('description'),
filename => $cgi->param('attach_text') ? "file_$id.txt" : scalar $cgi->upload('data'), filename => $attach_text ? "file_$id.txt" : $data_fh,
ispatch => scalar $cgi->param('ispatch'), ispatch => scalar $cgi->param('ispatch'),
isprivate => scalar $cgi->param('isprivate'), isprivate => scalar $cgi->param('isprivate'),
mimetype => $content_type, mimetype => $content_type,
......
...@@ -87,19 +87,21 @@ elsif ($action eq 'begin-sudo') { ...@@ -87,19 +87,21 @@ elsif ($action eq 'begin-sudo') {
{ {
$credentials_provided = 1; $credentials_provided = 1;
} }
# Next, log in the user # Next, log in the user
my $user = Bugzilla->login(LOGIN_REQUIRED); my $user = Bugzilla->login(LOGIN_REQUIRED);
my $target_login = $cgi->param('target_login');
my $reason = $cgi->param('reason') || '';
# At this point, the user is logged in. However, if they used a method # At this point, the user is logged in. However, if they used a method
# where they could have provided a username/password (i.e. CGI), but they # where they could have provided a username/password (i.e. CGI), but they
# did not provide a username/password, then throw an error. # did not provide a username/password, then throw an error.
if ($user->authorizer->can_login && !$credentials_provided) { if ($user->authorizer->can_login && !$credentials_provided) {
ThrowUserError('sudo_password_required', ThrowUserError('sudo_password_required',
{ target_login => $cgi->param('target_login'), { target_login => $target_login, reason => $reason });
reason => $cgi->param('reason')});
} }
# The user must be in the 'bz_sudoers' group # The user must be in the 'bz_sudoers' group
unless ($user->in_group('bz_sudoers')) { unless ($user->in_group('bz_sudoers')) {
ThrowUserError('auth_failure', { group => 'bz_sudoers', ThrowUserError('auth_failure', { group => 'bz_sudoers',
...@@ -123,30 +125,22 @@ elsif ($action eq 'begin-sudo') { ...@@ -123,30 +125,22 @@ elsif ($action eq 'begin-sudo') {
&& ($token_data eq 'sudo_prepared')) && ($token_data eq 'sudo_prepared'))
{ {
ThrowUserError('sudo_preparation_required', ThrowUserError('sudo_preparation_required',
{ target_login => scalar $cgi->param('target_login'), { target_login => $target_login, reason => $reason });
reason => scalar $cgi->param('reason')});
} }
delete_token($cgi->param('token')); delete_token($cgi->param('token'));
# Get & verify the target user (the user who we will be impersonating) # Get & verify the target user (the user who we will be impersonating)
my $target_user = my $target_user = new Bugzilla::User({ name => $target_login });
new Bugzilla::User({ name => $cgi->param('target_login') });
unless (defined($target_user) unless (defined($target_user)
&& $target_user->id && $target_user->id
&& $user->can_see_user($target_user)) && $user->can_see_user($target_user))
{ {
ThrowUserError('user_match_failed', ThrowUserError('user_match_failed', { name => $target_login });
{ 'name' => $cgi->param('target_login') }
);
} }
if ($target_user->in_group('bz_sudo_protect')) { if ($target_user->in_group('bz_sudo_protect')) {
ThrowUserError('sudo_protected', { login => $target_user->login }); ThrowUserError('sudo_protected', { login => $target_user->login });
} }
# If we have a reason passed in, keep it under 200 characters
my $reason = $cgi->param('reason') || '';
$reason = substr($reason, 0, 200);
# Calculate the session expiry time (T + 6 hours) # Calculate the session expiry time (T + 6 hours)
my $time_string = time2str('%a, %d-%b-%Y %T %Z', time + MAX_SUDO_TOKEN_AGE, 'GMT'); my $time_string = time2str('%a, %d-%b-%Y %T %Z', time + MAX_SUDO_TOKEN_AGE, 'GMT');
...@@ -166,9 +160,12 @@ elsif ($action eq 'begin-sudo') { ...@@ -166,9 +160,12 @@ elsif ($action eq 'begin-sudo') {
# For the present, change the values of Bugzilla::user & Bugzilla::sudoer # For the present, change the values of Bugzilla::user & Bugzilla::sudoer
Bugzilla->sudo_request($target_user, $user); Bugzilla->sudo_request($target_user, $user);
# NOTE: If you want to log the start of an sudo session, do it here. # NOTE: If you want to log the start of an sudo session, do it here.
# If we have a reason passed in, keep it under 200 characters
$reason = substr($reason, 0, 200);
# Go ahead and send out the message now # Go ahead and send out the message now
my $message; my $message;
my $mail_template = Bugzilla->template_inner($target_user->setting('lang')); my $mail_template = Bugzilla->template_inner($target_user->setting('lang'));
......
...@@ -167,7 +167,6 @@ ...@@ -167,7 +167,6 @@
], ],
'global/messages.html.tmpl' => [ 'global/messages.html.tmpl' => [
'message_tag',
'series.frequency * 2', 'series.frequency * 2',
], ],
......
...@@ -943,7 +943,7 @@ ...@@ -943,7 +943,7 @@
[% IF !message %] [% IF !message %]
[% message = BLOCK %] [% message = BLOCK %]
You are using Bugzilla's messaging functions incorrectly. You You are using Bugzilla's messaging functions incorrectly. You
passed in the string '[% message_tag %]'. The correct use is to pass passed in the string '[% message_tag FILTER html %]'. The correct use is to pass
in a tag, and define that tag in the file <kbd>messages.html.tmpl</kbd>.<br> in a tag, and define that tag in the file <kbd>messages.html.tmpl</kbd>.<br>
<br> <br>
If you are a [% terms.Bugzilla %] end-user seeing this message, please If you are a [% terms.Bugzilla %] end-user seeing this message, please
......
...@@ -313,7 +313,7 @@ sub confirm_create_account { ...@@ -313,7 +313,7 @@ sub confirm_create_account {
my $otheruser = Bugzilla::User->create({ my $otheruser = Bugzilla::User->create({
login_name => $login_name, login_name => $login_name,
realname => $cgi->param('realname'), realname => scalar $cgi->param('realname'),
cryptpassword => $password}); cryptpassword => $password});
# Now delete this token. # Now delete this token.
......
...@@ -544,7 +544,7 @@ sub SaveApiKey { ...@@ -544,7 +544,7 @@ sub SaveApiKey {
if ($cgi->param('new_key')) { if ($cgi->param('new_key')) {
$vars->{new_key} = Bugzilla::User::APIKey->create({ $vars->{new_key} = Bugzilla::User::APIKey->create({
user_id => $user->id, user_id => $user->id,
description => $cgi->param('new_description'), description => scalar $cgi->param('new_description'),
}); });
# As a security precaution, we always sent out an e-mail when # As a security precaution, we always sent out an e-mail when
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment