我已經閱讀了一段時間,現在在各種SO線程,指南等,但所有的答案是相互矛盾和矛盾的。Rails 5 SQL注入
看來有很多類似的方法,並且很多答案都表示使用不同的方法。
sanitize
sanitize_conditions
sanitize_sql
sanitize_sql_array
sanitize_sql_for_assignment
sanitize_sql_for_conditions
sanitize_sql_hash
sanitize_sql_hash_for_assignment
sanitize_sql_hash_for_conditions
sanitize_sql_like
我想寫一個「原始查詢」適配器,讓我跑生Postgres的查詢,但允許我插入我自己的參數來自於危險的用戶輸入。
,因爲我在做複雜的緯度/長計算,聚合函數,子查詢複雜等
到目前爲止,我已經試過2點的方法,我不能在這些少數情況下使用AR:
方法1
對於這種方法,我不知道是否sanitize
是上述的最佳選擇,或是否會在案件100%的工作...(我使用的是Postgres只)
class RawQuery
def exec(prepared, *params)
prepared = query.dup
params.flatten.each_with_index do |p, i|
prepared.gsub!("$#{i + 1}", ActiveRecord::Base.sanitize(p))
end
ActiveRecord::Base.connection.exec_query(prepared)
end
end
瑣碎的使用實例(通常它不會是這個簡單的當然還是我只想用AR):
RawQuery.new.exec('SELECT * FROM users WHERE name = $1', params[:name])
而且似乎sanitize
委託給quote
。但根據this SO post它只是簡單地用單引號包裝的東西是不安全的......所以我不知道。
方法2
我不知道這是否是一樣安全,但它似乎用實際PG準備功能(我假設是100%安全的)。唯一的問題是,rails不會將它打印到控制檯,也不包括SQL執行時間(這會中斷我的分析工具)。
class RawQuery
def prepare(query, *params)
name = "raw_query_#{SecureRandom.uuid.gsub('-', '')}"
connection = ActiveRecord::Base.connection.raw_connection
connection.prepare(name, query)
connection.exec_prepared(name, params)
end
end
用同樣的方式:
RawQuery.new.prepare('SELECT * FROM users WHERE name = $1', params[:name])
是一個方法更安全了另一個?既100%安全?
我的應用程序總是遠遠超出Rails具有SQL能力的地方,我需要一個很好的lib,我可以將其包含在我所知道的所有項目中,這些項目我都是完全安全的。
我明白了 - 這很有道理。那麼'sanitize'和'sanitize_sql_for_conditions'之間的主要區別是什麼?另一個我忘了在我原來的問題中包含的部分是,'method sanitize_sql_for_conditions'的文檔提到:*將它們清理成** WHERE **子句的有效SQL片段*。 'sanitize'的文檔say *用於在對象用於SQL ** SELECT **語句*之前對對象進行清理。這是否意味着它們與情境有關,並且一種方法不能在SQL語句中的任何地方使用? (在SELECT,WHERE,GROUP BY等)。或者我可以使用'sanitize'無論位置? – Tallboy
它看起來像'sanitize_ *'方法都受到保護,所以我不認爲你打算使用它們。我一直都把'quote'理解爲這種事情的主要公共方法。事實上,簡單的'sanitize'方法只是調用'quote'(正如你所說的)。看看代碼,看起來像其他'sanitize_ *'方法真的是用於橋接Railsy數據結構(例如'{name:「foo」,email:「[email protected]」}')和'quote' 。他們爲每個值調用'quote'。 '* for_conditions' vs'* for_assignment'似乎主要是關於使用','vs'AND'。 –
感謝您的幫助!很好的答案。 – Tallboy