L’attaque du code PL/SQL par une injection SQL est toujours d'actualité malgré son apparition depuis plusieurs années, cela est du généralement aux mauvaises habitudes des développeurs, en gros l'attaque consiste à forgé une autre requête a partir d'une requête qui accepte des paramètres, exemple :
SQL> create or replace procedure vul_proc(param varchar2) is
2 type fir_name is table of hr.employees.first_name%type;
3 fname fir_name := fir_name();
4 stmt varchar2(300);
5 begin
6 stmt:='select first_name from hr.employees where last_name='''||param||'''';
7 execute immediate stmt bulk collect into fname;
8 for i in fname.first..fname.last loop
9 dbms_output.put_line(fname(i));
10 end loop;
11 end;
12 /
Procédure crée.
L’utilisation légitime de cette procédure est :
SQL> set serveroutput on
SQL> exec vul_proc('King')
Janette
Steven
Procédure PL/SQL terminée avec succès.
SQL>
Mais le paramètre param est concaténé à l'instruction stmt sans aucun contrôle ce qui peut donner des idées :
SQL> exec vul_proc('King'' or ''1''=''1 ')
Ellen
Sundar
Mozhe
David
Hermann
Shelli
....
ou pire encore :
SQL> exec vul_proc('King'' union select password from dba_users where ''1''=''1 ')
2BE6F80744E08FEB
2CA614501F09FCCC
2D594E86F93B17A1
3DF26A8B17D0F29F
3FB8EF9DB538647C
4A3BA55E08595C81
4C6D73C3E8B0F0DA
66F4EF5650C20355
71E687F036AD56E5
72979A94BAD2AF80
72E382A52E89575A
7C9BA362F8314299
7EFA02EC7EA6B86F
84B8CBCA4D477FA3
88A2B2C183431F00
88D8364765FCE6AF
8A8F025737A9097A
9793B3777CD3BD1A
9C30855E7E0CB02D
BFBA5A553FD9E28A
CE4A36B8E06CA59C
DF02A496267DEE66
F25A184809D6458D
F894844C34402B67
FA1D2B85B70213F3
FFF45BB2C0C327EC
Janette
Steven
anonymous
Procédure PL/SQL terminée avec succès.
Pour éviter ce genre de situation le mieux sera d'utiliser des variables attachées dans la chaine passer à execute immediate et une clause USING pour utiliser le paramètre :
SQL> create or replace procedure vul_proc(param varchar2) is
2 type fir_name is table of hr.employees.first_name%type;
3 fname fir_name := fir_name();
4 stmt varchar2(300);
5 begin
6 stmt:='select first_name from hr.employees where last_name= :param ';
7 execute immediate stmt bulk collect into fname using param;
8 for i in fname.first..fname.last loop
9 dbms_output.put_line(fname(i));
10 end loop;
11 end;
12 /
Procédure crue.
L’attaque par une injection SQL ne marchera pas, puisque ORACLE précompile l'instruction STMT et il ne permettra qu'un seul paramètre valide qui ne contiendra aucun mot clé SQL :
SQL> exec vul_proc('King'' union select password from dba_users where ''1''=''1 ')
BEGIN vul_proc('King'' union select password from dba_users where ''1''=''1 '); END;
*
ERREUR à la ligne 1 :
ORA-06502: PL/SQL : erreur numérique ou erreur sur une valeur
ORA-06512: à "SYS.VUL_PROC", ligne 8
ORA-06512: à ligne 1
SQL> create or replace procedure vul_proc(param varchar2) is
2 type fir_name is table of hr.employees.first_name%type;
3 fname fir_name := fir_name();
4 stmt varchar2(300);
5 begin
6 stmt:='select first_name from hr.employees where last_name='''||param||'''';
7 execute immediate stmt bulk collect into fname;
8 for i in fname.first..fname.last loop
9 dbms_output.put_line(fname(i));
10 end loop;
11 end;
12 /
Procédure crée.
L’utilisation légitime de cette procédure est :
SQL> set serveroutput on
SQL> exec vul_proc('King')
Janette
Steven
Procédure PL/SQL terminée avec succès.
SQL>
Mais le paramètre param est concaténé à l'instruction stmt sans aucun contrôle ce qui peut donner des idées :
SQL> exec vul_proc('King'' or ''1''=''1 ')
Ellen
Sundar
Mozhe
David
Hermann
Shelli
....
ou pire encore :
SQL> exec vul_proc('King'' union select password from dba_users where ''1''=''1 ')
2BE6F80744E08FEB
2CA614501F09FCCC
2D594E86F93B17A1
3DF26A8B17D0F29F
3FB8EF9DB538647C
4A3BA55E08595C81
4C6D73C3E8B0F0DA
66F4EF5650C20355
71E687F036AD56E5
72979A94BAD2AF80
72E382A52E89575A
7C9BA362F8314299
7EFA02EC7EA6B86F
84B8CBCA4D477FA3
88A2B2C183431F00
88D8364765FCE6AF
8A8F025737A9097A
9793B3777CD3BD1A
9C30855E7E0CB02D
BFBA5A553FD9E28A
CE4A36B8E06CA59C
DF02A496267DEE66
F25A184809D6458D
F894844C34402B67
FA1D2B85B70213F3
FFF45BB2C0C327EC
Janette
Steven
anonymous
Procédure PL/SQL terminée avec succès.
Pour éviter ce genre de situation le mieux sera d'utiliser des variables attachées dans la chaine passer à execute immediate et une clause USING pour utiliser le paramètre :
SQL> create or replace procedure vul_proc(param varchar2) is
2 type fir_name is table of hr.employees.first_name%type;
3 fname fir_name := fir_name();
4 stmt varchar2(300);
5 begin
6 stmt:='select first_name from hr.employees where last_name= :param ';
7 execute immediate stmt bulk collect into fname using param;
8 for i in fname.first..fname.last loop
9 dbms_output.put_line(fname(i));
10 end loop;
11 end;
12 /
Procédure crue.
L’attaque par une injection SQL ne marchera pas, puisque ORACLE précompile l'instruction STMT et il ne permettra qu'un seul paramètre valide qui ne contiendra aucun mot clé SQL :
SQL> exec vul_proc('King'' union select password from dba_users where ''1''=''1 ')
BEGIN vul_proc('King'' union select password from dba_users where ''1''=''1 '); END;
*
ERREUR à la ligne 1 :
ORA-06502: PL/SQL : erreur numérique ou erreur sur une valeur
ORA-06512: à "SYS.VUL_PROC", ligne 8
ORA-06512: à ligne 1
0 comments:
Enregistrer un commentaire