データベースに情報を格納するストアド プロシージャに情報を送信します。
ストアド プロシージャはクエリを動的に作成するため、ストアド プロシージャに送信する内容に注意する必要があります。フロントエンド(asp.net MVCを使用しています)またはWebサービスで、必要なパラメーターから悪意のある文字を引き出すだけです。それは機能しますが、たとえば O'brian のような名前を入力する必要がある場合はどうすればよいでしょうか? それともできない?それをオラクルに入力できるようにする必要があります。動的に構築されているときに、これらの特定のパラメーターを q[] でラップすることもできますが、うまくいかないと思います。odp .net には、その特別なケースを魔法のように処理できる特別なメソッド呼び出しがありますか?
または、自分でそれを具体的にコーディングする必要がありますか?
1 に答える
ODP.net は、.net コードと Oracle 間のインターフェースを提供します。制御がprocに渡された後に動的SQLを構築している場合、odp.netができることはあまりありません。
危険なのは文字列で、この場合は varchar です。誰かがあなたのコードに追加のSQLを注入できるのは、実際には単なる文字列または類似のものです。バインド変数が常に単一の文字列 (つまり、エスケープされていない一重引用符のセット) である限り、悪意のあるユーザーができることはほとんどありません。
したがって、これを安全と見なすことができるいくつかのルールがあると思います。
1) varchar/clob パラメータは、絶対に必要な場合にのみ使用してください。
2) Varchar/Clob バインド値は、結果の sql 内で常に一重引用符で囲む必要があります。
良い:
'where myval=''' || p_my_val || ''''
悪い:
'where myval=' || p_my_val
3) 文字列内の一重引用符を 2 つの一重引用符に置き換えます。
'where myval=''' || replace(p_my_val, '''', '''''') || ''''
その時点で、リスクを軽減できたと思います。以下はオラクル側からの完全な動作例です。また、SQL 内にバインド変数 "l_fname" を含め、"using" を入力しました。これは、他の変数が常にクエリ内にあり (条件付きで追加されるのに対して)、常に同じ順序である場合に備えています。
--create the ref cursor (simulates cmd.Parameters.Add)
var c refcursor;
--vvvvvvvvv simulates your stored proc vvvvvvvvvvvv
declare
l_lname varchar2(200) :='O''brian';
l_fname varchar2(200) :='Bob';
l_sql varchar2(2000);
begin
l_sql := 'select * from dual where dummy!=:l_fname ' || 'and dummy!=''' || replace(l_lname, '''','''''') || '''';
dbms_output.put_line(l_sql);
open :c for l_sql using replace(l_fname, '''', '''''');
end;
--^^^^^^^^^ ends yoru stored proc ^^^^^^^^^^^^^^^^^
/
--debugging within oracle only:
print c;
また、動的SQLが必要かどうかも検討してください。最終的なSQL文字列の外側で行うほとんどすべてのロジックは、代わりにその中で行うことができます。
if( p_my_var is not null ) then
p_sql = p_sql || ' and myval = ''' || replace(p_my_val, '''', '''''') || ''''
になり得る
and p_my_val is null or myval=p_my_val
SQLサーバーでは上記を強くお勧めします。Oracleでも実行することをお勧めしますが、バインド値が実行計画で考慮されないため、SQLサーバーの場合と同様に短絡しません。場合によっては最適とは言えません(少なくとも10gでは)。 . このような場合は、代わりに次を使用します。
and myval=decode(p_my_val, null, col1, p_my_val);