Oracle-11g-R2
如何使用綁定變數防止高度動態的 PL-SQL 查詢注入
我有一個程序,如下所示:
create or replace procedure Injection_test(qry1 varchar2, qry2 varchar2, user_id varchar2) is final_query varchar2(1000) := ''; begin if (qry1 is not null) then final_query := 'select c_num from z_test_a where userid = ''' ||user_id || ''' and ' || qry1; if (qry2 is not null) then final_query := final_query || 'intersect '; end if; end if; if (qry2 is not null) then final_query := final_query || ' select c_num from z_test_b where userid = ''' ||user_id || ''' and ' || qry2; end if; --dbms_output.put_line(final_query); execute immediate 'insert into Z_final_result (c_num)'||final_query; commit; end;
如您所見,該變數
final_query
基於兩個輸入變數是高度動態的qry1 and qry2
。由於我是 Oracle pl-sql injection 的新手,我不完全知道如何防止這段程式碼被 sql injection 。我知道注入的基本概念以及它是如何發生的——例如,當我們有null or 1=1
一個輸入變數時,表的所有記錄都將插入到最終表中——但我不知道如何改變這個過程和用於bind variables
防止注射發生。我想知道你是否可以幫助我提前謝謝
我不確定有沒有好的答案。通常,使用字元串連接來建構 SQL 總是一個壞主意,應盡可能避免。也就是說,除了用綁定變數替換 user_id 引用之外,在您的情況下很難避免。除此之外,您將不得不提出一些自定義邏輯來驗證 qry1 和 qry2 的內容,以確保它們只包含您期望它們包含的內容。也許是長度限制,或者檢查關鍵字或列名?要麼這樣,要麼用每個表中列的顯式值(包括萬用字元)替換 qry1 和 qry2,然後將它們轉換為綁定變數。
只要您必須接受實際的 SQL 程式碼片段作為輸入,我會推薦如下內容:
create or replace procedure Injection_test(p_qry1 varchar2, p_qry2 varchar2, p_user_id varchar2) is final_query varchar2(1000) := ''; begin -- put some logic here to validate the content of p_qry1 and p_qry2 to make sure -- they don't contain keywords like "select", "update", "delete", "1=1", ";" or -- equivalents, and/or that they do contain things you expect to see. Raise an -- application error anything unexpected is found if p_qry1 is not null then final_query := 'select c_num from z_test_a where userid = :user_id and ' || qry1; if p_qry2 is not null then final_query := final_query || ' intersect '; end if; end if; if p_qry2 is not null then final_query := final_query || 'select c_num from z_test_b where userid = :user_id and ' || qry2; end if; if final_query is not null then final_query := 'insert into Z_final_result (c_num) ' || final_query; --dbms_output.put_line(final_query); if instr(final_query,'intersect') > 1 then execute immediate final_query using p_user_id, p_user_id; else execute immediate final_query using p_user_id; end if; commit; end if; end;