]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 515191: [SECURITY] SQL Injection via Bug.search (CVE-2009-3125) and Bug.create...
authormkanat%bugzilla.org <>
Fri, 11 Sep 2009 16:13:50 +0000 (16:13 +0000)
committermkanat%bugzilla.org <>
Fri, 11 Sep 2009 16:13:50 +0000 (16:13 +0000)
Patch by Max Kanat-Alexander <mkanat@bugzilla.org> r=LpSolit, a=mkanat

Bugzilla/Object.pm
Bugzilla/WebService/Bug.pm
Bugzilla/WebService/Constants.pm
template/en/default/global/code-error.html.tmpl

index b24e9b69df4b63998b1ea35bb269a92f44eded5a..5a74996f1394c6b1d836ebf456db5ab19fc69edb 100644 (file)
@@ -164,7 +164,19 @@ sub match {
         next if $field eq 'OFFSET';
         if ( $field eq 'LIMIT' ) {
             next unless defined $value;
-            $postamble = $dbh->sql_limit( $value, $criteria->{OFFSET} );
+            detaint_natural($value)
+              or ThrowCodeError('param_must_be_numeric', 
+                                { param    => 'LIMIT', 
+                                  function => "${class}::match" });
+            my $offset;
+            if (defined $criteria->{OFFSET}) {
+                $offset = $criteria->{OFFSET};
+                detaint_signed($offset)
+                  or ThrowCodeError('param_must_be_numeric', 
+                                    { param    => 'OFFSET',
+                                      function => "${class}::match" });
+            }
+            $postamble = $dbh->sql_limit($value, $offset);
             next;
         }
         elsif ( $field eq 'WHERE' ) {
@@ -180,6 +192,8 @@ sub match {
             next;
         }
         
+        $class->_check_field($field, 'match');
+
         if (ref $value eq 'ARRAY') {
             # IN () is invalid SQL, and if we have an empty list
             # to match against, we're just returning an empty
@@ -345,6 +359,17 @@ sub create {
     return $object;
 }
 
+# Used to validate that a field name is in fact a valid column in the
+# current table before inserting it into SQL.
+sub _check_field {
+    my ($invocant, $field, $function) = @_;
+    my $class = ref($invocant) || $invocant;
+    if (!Bugzilla->dbh->bz_column_info($class->DB_TABLE, $field)) {
+        ThrowCodeError('param_invalid', { param    => $field,
+                                          function => "${class}::$function" });
+    }
+}
+
 sub check_required_create_fields {
     my ($class, $params) = @_;
 
@@ -387,6 +412,7 @@ sub insert_create_data {
 
     my (@field_names, @values);
     while (my ($field, $value) = each %$field_values) {
+        $class->_check_field($field, 'create');
         push(@field_names, $field);
         push(@values, $value);
     }
index 8e712ff3adeca5bf194ad75cc5a4c96ce3b1727d..7c6be1a0a12a3902c803c51074752e5d9eb07cc3 100644 (file)
@@ -254,6 +254,7 @@ sub search {
     }
     
     $params = _map_fields($params);
+    delete $params->{WHERE};
     
     # Do special search types for certain fields.
     if ( my $bug_when = delete $params->{delta_ts} ) {
index 2267c923db34c37f5b8b275c5aa8d5880c9d8029..e47beb1f26555c888d79501bb6489d25b6b9f4b4 100644 (file)
@@ -53,7 +53,9 @@ use constant WS_ERROR_CODE => {
     param_required              => 50,
     params_required             => 50,
     object_does_not_exist       => 51,
+    param_must_be_numeric       => 52,
     xmlrpc_invalid_value        => 52,
+    param_invalid               => 53,
     # Bug errors usually occupy the 100-200 range.
     improper_bug_id_field_value => 100,
     bug_id_does_not_exist       => 101,
index 1d0eed39d8505e47de3de3ec35956498db958f0b..626ad500828e8dc46c5ecfa7504141e8f37a91d6 100644 (file)
     There is no valid transition from
     [%+ get_status("UNCONFIRMED") FILTER html %] to an open state.
 
+  [% ELSIF error == "param_invalid" %]
+    [% title = "Invalid Parameter" %]
+    <code>[% param FILTER html %]</code> is not a valid parameter
+    for the [% function FILTER html %] function.
+
   [% ELSIF error == "param_must_be_numeric" %]
     [% title = "Invalid Parameter" %]
     Invalid parameter passed to [% function FILTER html %].