Todos sabemos que si el código de una aplicación está mal escrito, cualquiera puede piratear la información usando un pequeño truco como la inyección SQL. En esta publicación, doy un ejemplo para demostrar cómo SQL Injection podría ser vulnerable a una aplicación y cómo puede evitarlo.
La demostración se basa en la tabla EMP del esquema SCOTT. Para descargar el script de esquema de SCOTT, haga clic en el siguiente enlace Descargar script de esquema de Scott.
Un ejemplo para realizar una inyección SQL
En esta sección, doy un ejemplo de un procedimiento almacenado PL/SQL que aceptará un número de empleado de parámetro como (p_empno) para mostrar el salario de ese empleado. En el código, estoy usando la concatenación del valor de ese parámetro (p_empno) en la cadena de instrucción SQL para REF CURSOR, que no se recomienda y será la causa de una inyección de SQL exitosa. A continuación se muestra el procedimiento:
CREATE OR REPLACE PROCEDURE PRC_GET_EMP_SAL (p_empno VARCHAR2) IS --Declare a ref cursor and local variables-- TYPE C IS REF CURSOR; CUR_EMP C; L_ENAME VARCHAR2 (100); L_SAL NUMBER; L_STMT VARCHAR2 (4000); BEGIN --Open the ref cursor for a Dynamic SELECT statement-- L_STMT := 'SELECT ename, sal FROM emp WHERE empno = ''' || p_empno || ''''; OPEN CUR_EMP FOR L_STMT; LOOP --Fetch the result set and print the result set-- FETCH CUR_EMP INTO L_ENAME, L_SAL; EXIT WHEN CUR_EMP%NOTFOUND; DBMS_OUTPUT.PUT_LINE (L_ENAME || ' -- ' || L_SAL); END LOOP; CLOSE CUR_EMP; END; /
Ahora vamos a probar el procedimiento anterior normalmente pasando un número de empleado.
Prueba
SET SERVEROUTPUT ON; BEGIN prc_get_emp_sal ('7566'); END; /
Salida
JONES -- 27706.89 PL/SQL procedure successfully completed.
Hasta ahora todo está bien. Porque llamamos correctamente al procedimiento. Ahora veremos cómo podemos piratear el procedimiento anterior utilizando el truco de inyección SQL para obtener el salario de todos los empleados. Quizás a veces tú también quieras hacer esto. ¡Bromeando!
Prueba usando inyección SQL
SET SERVEROUTPUT ON; BEGIN prc_get_emp_sal ('X'' OR ''1''= ''1'); END; /
Salida de inyección SQL exitosa
WARD -- 11641.56 JONES -- 27706.89 MARTIN -- 11641.56 BLAKE -- 26542.7 CLARK -- 22817.41 SCOTT -- 83819.06 KING -- 46566.18 TURNER -- 13969.85 ADAMS -- 10244.6 JAMES -- 8847.64 FORD -- 27939.74 MILLER -- 12107.2 PL/SQL procedure successfully completed.
Wow, ahora puedes ver el salario de cada empleado usando este truco de inyección SQL. Imagínese que tiene un campo de texto en una aplicación, ya sea basada en navegador o de escritorio, y está pasando el valor directamente al procedimiento, y si usa el truco anterior, seguramente esto sucederá.
Un ejemplo para prevenir la inyección SQL
Ahora modificaremos el procedimiento anterior para usar la variable de vinculación en lugar de concatenar el valor del parámetro y de esta manera no funcionará ningún truco de inyección SQL.
CREATE OR REPLACE PROCEDURE PRC_GET_EMP_SAL_2 (p_empno VARCHAR2) IS --Declare a ref cursor and local variables-- TYPE C IS REF CURSOR; CUR_EMP C; L_ENAME VARCHAR2 (100); L_SAL NUMBER; L_STMT VARCHAR2 (4000); BEGIN --Open the ref cursor for a Dynamic SELECT statement-- L_STMT := 'SELECT ename, sal FROM emp WHERE empno = :p_bind_empno'; OPEN CUR_EMP FOR L_STMT USING p_EMPNO; LOOP --Fetch the result set and print the result set-- FETCH CUR_EMP INTO L_ENAME, L_SAL; EXIT WHEN CUR_EMP%NOTFOUND; DBMS_OUTPUT.PUT_LINE (L_ENAME || ' -- ' || L_SAL); END LOOP; CLOSE CUR_EMP; EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE ('Can not fetch any records for: ' || p_empno); END; /
Pruebe el procedimiento anterior normalmente
SET SERVEROUTPUT ON; BEGIN prc_get_emp_sal_2 ('7566'); END; /
Salida
JONES -- 27706.89 PL/SQL procedure successfully completed.
Pruebe el procedimiento anterior usando SQL Injection
SET SERVEROUTPUT ON; BEGIN prc_get_emp_sal_2 ('1'' OR ''1''= ''1'); END; /
Salida de inyección SQL fallida
Can not fetch any records for: 1' OR '1'= '1 PL/SQL procedure successfully completed.
Así que anótelo, si está creando programas PL/SQL usando SQL dinámico, use los métodos de vinculación.
-
¿Cuál es la forma más rápida de calcular la mediana?
-
Perspectiva de rendimiento de consultas:¿Descubriendo qué consume recursos de su base de datos Azure SQL?
-
Cómo prevenir la corrupción de la base de datos en Microsoft Access
-
Uso de Oracle JDeveloper con MySQL Database Service en Oracle Cloud Platform, Parte 3