CVE-2021-4298 (published 2023-01-02T08:15Z)

A vulnerability classified as critical has been found in Hesburgh Libraries of Notre Dame Sipity. This affects the function SearchCriteriaForWorksParameter of the file app/parameters/sipity/parameters/search_criteria_for_works_parameter.rb. The manipulation leads to sql injection. Upgrading to version 2021.8 is able to address this issue. The patch is named d1704c7363b899ffce65be03a796a0ee5fdbfbdc. It is recommended to upgrade the affected component. The associated identifier of this vulnerability is VDB-217179.

CVSS v3 base score: 9.8, CRITICAL (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-89
cwe_name: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
description: The product constructs all or part of an SQL command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended SQL command when it is sent to a downstream component. Without sufficient removal or quoting of SQL syntax in user-controllable inputs, the generated SQL query can cause those inputs to be interpreted as SQL instead of ordinary user data.
extended_description: 
            
            
         
         

Fix information:
repo_url: https://github.com/ndlib/sipity
commit_details: repo_url: https://github.com/ndlib/sipity
author: Jeremy Friesen
author_date: 2021-08-12 09:33:32-04:00
msg: Adding protection against SQL injection

Prior to this commit, the SearchCriteriaForWorksParameter class was to
optimistic in the additional_attributes it received.  This was "okay" in
that these attributes were passed from within the application (and not
from user input).

However, I wanted to tighten that up further which is why I added the
changes to fetch the attributes from a map.

And even with all of this, [brakeman][1] identified this as a weak
chance for SQL injection.  So I also added a config/brakeman.yml file to
skip over this file. (alas I can't skip over a singular violation)

[1]:https://rubygems.org/gems/brakeman
repository: repo_url: https://github.com/ndlib/sipity
repo_name: ndlib/sipity
description: CURATE-related. Sipity is a patron-oriented workflow application.
repo_language: Ruby
owner: ndlib
file_changes: filename: search_criteria_for_works_parameter.rb
change_type: ModificationType.MODIFY
diff: @@ -17,6 +17,22 @@ module Sipity
       self.default_q = nil
       self.default_order = 'title'.freeze
       self.default_additional_attributes = ["author_name", "submission_date"].freeze
+
+      # Note the parity between this and the additional attributes.
+      # I'm including the following map to remove a possible SQL
+      # injection spot.
+      #
+      # Each key has a value that is a hash with two keys:
+      # 1. `key`: - the `sipity_additional_attributes.key` field's value
+      # 2. `join_as_table_name`: - for the purposes of the join, the
+      #    table name we'll join as.
+      #
+      # We need the `join_as_table_name` so that we can join multiple
+      # times to the same `sipity_additional_attributes` table.
+      ADDITIONAL_ATTRIBUTE_MAP = {
+        "author_name" => { key: 'author_name', join_as_table_name: 'author_names' },
+        "submission_date" => { key: 'submission_date', join_as_table_name: 'submission_dates' },
+      }
       ORDER_BY_OPTIONS = ['title', 'title DESC', 'created_at', 'created_at DESC', 'updated_at', 'updated_at DESC'].freeze
 
       def self.order_options_for_select
@@ -68,11 +84,12 @@ module Sipity
         select_fields = ["#{work_table_name}.*"]
 
         additional_attributes.each do |attribute|
-          table_name = attribute.to_s.pluralize
+          table_name = attribute.fetch(:join_as_table_name)
+          key = attribute.fetch(:key)
           scope = scope.joins(
-            %(LEFT OUTER JOIN #{attr_table_name} AS #{table_name} ON #{table_name}.work_id = #{work_table_name}.id AND #{table_name}.key = "#{attribute}")
+            %(LEFT OUTER JOIN #{attr_table_name} AS #{table_name} ON #{table_name}.work_id = #{work_table_name}.id AND #{table_name}.key = "#{key}")
           )
-          select_fields << "#{table_name}.value AS #{attribute}"
+          select_fields << "#{table_name}.value AS #{key}"
         end
 
         scope.select(select_fields.join(", "))
@@ -84,7 +101,7 @@ module Sipity
       # Doing our due diligence to santize parameters
       def additional_attributes=(input)
         @additional_attributes = Array(input).map do |attribute_name|
-          Models::AdditionalAttribute.sanitize_sql_for_conditions(attribute_name.to_s)
+          ADDITIONAL_ATTRIBUTE_MAP.fetch(attribute_name)
         end
       end
 

programming_language: Ruby
filename: brakeman.yml
change_type: ModificationType.ADD
diff: @@ -0,0 +1,5 @@
+---
+# We're hand building a SQL line, for which we've taken precautions to
+# avoid SQL injection.
+:skip_files:
+- app/parameters/sipity/parameters/search_criteria_for_works_parameter.rb
\ No newline at end of file

programming_language: Markdown