2015-07-21 72 views
1

在我的Rails應用我有一個範圍,看起來像這樣:複雜範圍與SQL注入問題

scope :organization_join, -> (organization_type) { 
    organization_table_name = organization_type.underscore.pluralize 
    joins("LEFT JOIN \"#{organization_table_name}\" 
     ON \"#{organization_table_name}\".\"organization_id\" = \"survey_reports\".\"organization_id\" AND 
     \"survey_reports\".\"organization_type\" = '#{organization_type}'" 
    ) 
    } 

此範圍允許SQL注入攻擊... 什麼將是改寫這是最好的方式安全的SQL注入?

回答

2

你來到這裏兩個問題:

  • 您參加該會轉換爲一個表名,而不是針對有效的表名的白名單測試類型的參數。
  • 您內嵌查詢中的潛在用戶數據。

,你可以做些什麼來解決第一個是獸醫對有效名稱的列表表名:

ORGANIZATION_TABLES = %w[ 
    team 
    club 
    house 
] 

scope :organization_join, -> (organization_type) { 
    case (organization_type) 
    when *ORGANIZATION_TABLES 
    _table = organization_type.underscore.pluralize 
    joins(
     "LEFT JOIN %s ON %s.%s = %s.%s", 
     _table, 
     _table, :organization_id, 
     :survey_reports, :organization_id, 
    ).where(
     survey_reports: { organization_type: organization_type } 
    ) 
    else 
    raise "No idea what #{organization_type} is." 
    end 
} 

在這裏,我已經關掉你的加入條款的一部分,以一個標準的where允許使用內置的轉義功能。其次,因爲這些列名或表名都不是保留字,所以您不需要經歷用引號將它們轉義出來的麻煩。

你會發現這一切完全是多餘的,如果你可以簡單地這樣做:

scope :organization_join, -> (organization_type) { 
    includes(:survey_reports).where(survey_reports: { organization_type: organization_type }) 
} 

如果你有一個正確的has_many關係,這允許預先加載與隱式連接。

+0

這是一個非常乾淨的答案。 –