これについては、いろいろなSOのスレッド、ガイドなどでお伝えしていますが、すべての回答は矛盾して矛盾しています。Rails 5 SQL Injection
多くの類似の方法があるようですが、多くの回答では別の方法を使用すると言われています。
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%で動作する場合、私は
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])
さらにそれがquote
へsanitize
委譲しているようです。しかし、this SO postによれば、単引用符で物をラップするだけでは安全ではないので...私は考えていません。
方法2
私は、これは同じように安全であるかどうかわからないんだけど、実際のPGを使用しているようだ(私は100%安全であると仮定している)機能を用意しました。唯一の問題は、レールがコンソールに表示されず、SQL実行時間(プロファイリングツールが破損する)が含まれないことです。
RawQuery.new.prepare('SELECT * FROM users WHERE name = $1', params[:name])
は別をより安全な一つの方法である:?同じように使用
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
両方とも100%安全ですか?
私のアプリは、常にRailsがSQLに対応しているものの外に広がっています。私が知っている私のすべてのプロジェクトにインクルードすることができます。
私は理解します。では、 'sanitize'と' sanitize_sql_for_conditions'の主な違いは何ですか?私が最初の質問に含めることを忘れていたもう1つの部分は、 'method sanitize_sql_for_conditions'の文書には、** WHERE **句の有効なSQLフラグメントにそれらをサニタイズすることです。 'sanitize'のドキュメントは次のように言っています:オブジェクトがSQL ** SELECT **ステートメントで使用される前にオブジェクトをサニタイズするのに使われました。それは状況依存であり、SQL文のどこでも使用できないメソッドなのでしょうか? (SELECT、WHERE、GROUP BYなどで)。または、場所に関係なく 'sanitize'を使用できますか? – Tallboy
'sanitize_ *'メソッドはすべて保護されているように見えますから、あなたがそれらを使うつもりはないと思います。私はいつも 'quote'がこのようなことに使う主な公的方法であると理解してきました。実際、単純な 'sanitize'メソッドは単にあなたが言ったように' quote'を呼び出します。コードを見るだけで、他の 'sanitize_ *'メソッドは本当にRailsyのデータ構造( '{name:" foo "、email:" [email protected] "}')と 'quote' 。彼らはそれぞれの値に対して 'quote'を呼び出します。 '* for_conditions'と' * for_assignment'は主に '、'と 'と'を使っているようです。 –
助けてくれてありがとう!素晴らしい答え。 – Tallboy