0

I have a procedure as you can see below:

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;

As you can see , the variable final_query is highly dynamic based on two input variablesqry1 and qry2. Since I'm new to Oracle pl-sql injection , I don't exactly know how to prevent this piece of code from sql injection . I know the basic concepts of injection and how it occurs -for example when we have null or 1=1 for one of the input variables,all the records of the table will be inserted in the final table- but I do not know exactly how to change this procedure and usebind variables to prevent injection from happening.

I was wondering if you could help me out with this Thanks in advance

asked Jul 14, 2020 at 12:36
1
  • Nobody has a good answer? Commented Jul 15, 2020 at 5:59

1 Answer 1

1

I'm not sure there is a good answer. In general, string concatenation to build your SQL is always a bad idea and should be avoided whenever possible. That said, it would be difficult to avoid in your case except for replacing user_id references with bind variables. Other than that, you will have to come up with some custom logic to validate the content of qry1 and qry2 to ensure they only contain what you expect them to contain. Perhaps a length limitation, or a check of keywords or column names? Either that, or replace qry1 and qry2 with explicit values for the columns in each table, including wildcards, then turn those into bind variables.

As long as you have to accept actual SQL code snippets as your input, I would recommend something like this:

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;
answered Jul 15, 2020 at 11:57

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.