sails注入的Rails制动器警告

我的模型中有一个范围:

scope :assigned_to_user, ->(user) { task_table = UserTask.table_name joins("INNER JOIN #{task_table} ON #{task_table}.user_id = #{user.id} AND (#{task_table}.type_id = #{table_name}.type_id) AND (#{task_table}.manager_id = #{table_name}.manager_id) ") } 

因此,在运行制动器报告后,我收到此警告:

 assigned_to_user | SQL Injection | Possible 

所以我尝试了以下内容:

 scope :assigned_to_user, ->(user) { task_table = UserTask.table_name joins(ActiveRecord::Base::sanitize("INNER JOIN #{task_table} ON #{task_table}.user_id = #{user.id} AND (#{task_table}.type_id = #{table_name}.type_id) AND (#{task_table}.manager_id = #{table_name}.manager_id) ")) } 

这对我不起作用,因为它将' (撇号)添加到sql的前面和后面。 所以当我使用它作为查询的一部分返回一些结果并且我应用这个范围时它会生成不正确的sql。

我也试过这个:

 scope :assigned_to_user, ->(user) { task_table = UserTask.table_name joins("INNER JOIN #{task_table} ON #{task_table}.user_id = ? AND (#{task_table}.type_id = #{table_name}.type_id) AND (#{task_table}.manager_id = #{table_name}.manager_id) ", user.id) } 

甚至没有建立声明。 并尝试了其他一些不起作用甚至不值得一提的东西。 有人知道如何解决这个问题吗?

经过某种研究后,我将使用它。 有一个名为sanitize_sql_array ( ref )的方法,您可以通过将sql字符串和替换值传递给它来使用它来转义语句,如:

 sanitize_sql_array(['user_id = :user_id', user_id: 5]) # => "user_id = 5" 

如果我们将表名传递给此方法,它也将对其进行转义,但会在一个值上应用ActiveRecord::Base.connection对象的quote方法,该方法用于转义变量,但不转义表名。 也许有时它会起作用,但是当我使用PostrgreSQL时它失败了,因为quote方法使用单引号,但PostgreSQL需要对表名进行双引号。

 sanitize_sql_array([ 'INNER JOIN :table_name ON :table_name.user_id = :user_id', { table_name: 'users', user_id: 5 } ]) # => "INNER JOIN 'users' ON 'users'.user_id = 5" 

connection对象还有一个方法quote_table_name ,它可以单独应用于表名,以确保它们被转义+使用sanitize_sql_array作为用户ID。

 scope :assigned_to_user, -> (user) { task_table = connection.quote_table_name(UserTask.table_name) current_table = connection.quote_table_name(table_name) sanitized_sql = sanitize_sql_array([ "INNER JOIN #{task_table} ON #{task_table}.user_id = :user_id AND (#{task_table}.type_id = #{current_table}.type_id) AND (#{task_table}.manager_id = #{current_table}.manager_id)", { user_id: user.id } ]) joins(sanitized_sql) } 

或者你实际上只需在user.id上使用sanitize ,而不是在sanitize_sql_array方法调用中包装所有内容( #{sanitize(user.id)} )。

顺便说一句,Brakeman不会显示任何警告,因为查询已被移动到变量。 Brakeman按原样解析你的代码,它不知道变量和它的内容。 所以这一切只是为了确保一切都被逃脱。

只是为了关闭Brakeman,您可以将查询移动到变量:

 scope :assigned_to_user, -> (user) { task_table = UserTask.table_name query = "INNER JOIN #{task_table} ON #{task_table}.user_id = #{user.id} AND (#{task_table}.type_id = #{table_name}.type_id) AND (#{task_table}.manager_id = #{table_name}.manager_id)" joins(query) } 
Interesting Posts