Oracle
 sql >> Database >  >> RDS >> Oracle

Un esempio per dimostrare la vulnerabilità dell'iniezione di SQL e la sua prevenzione in Oracle

Sappiamo tutti che se un codice dell'applicazione è scritto male, chiunque può hackerare le informazioni usando un piccolo trucco come SQL Injection. In questo post, fornisco un esempio per dimostrare come SQL Injection potrebbe essere vulnerabile a un'applicazione e come puoi prevenirla.

La dimostrazione si basa sulla tabella EMP dello schema SCOTT. Per scaricare lo script dello schema SCOTT, fare clic sul collegamento seguente Scarica lo script dello schema Scott.

Un esempio per eseguire SQL injection

In questa sezione, sto fornendo un esempio di una procedura memorizzata PL/SQL che accetterà un numero di dipendente parametro come (p_empno) per visualizzare lo stipendio per quel dipendente. Nel codice, sto usando la concatenazione di quel valore del parametro (p_empno) nella stringa dell'istruzione SQL per REF CURSOR, che non è raccomandato e sarà la causa dell'inserimento corretto di SQL. Di seguito la procedura:

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;
/

Ora testeremo normalmente la procedura precedente passando un numero di dipendente.

Test

SET SERVEROUTPUT ON;

BEGIN
   prc_get_emp_sal ('7566');
END;
/

Uscita

JONES -- 27706.89
PL/SQL procedure successfully completed.

Fino ad ora va tutto bene. Perché abbiamo chiamato correttamente la procedura. Ora vedremo come possiamo hackerare la procedura di cui sopra usando il trucco SQL Injection per recuperare lo stipendio di tutti i dipendenti. Forse a volte vuoi farlo anche tu. Scherzo!

Test utilizzando SQL injection

SET SERVEROUTPUT ON;

BEGIN
   prc_get_emp_sal ('X'' OR ''1''= ''1');
END;
/

Output SQL injection riuscito

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, ora puoi vedere lo stipendio di ogni dipendente usando questo trucco SQL Injection. Immagina di avere un campo di testo in un'applicazione sia che sia basata su browser o desktop e stai passando il valore direttamente alla procedura, e se usi il trucco sopra, sicuramente questo accadrà.

Un esempio per prevenire SQL injection

Ora modificheremo la procedura precedente per utilizzare la variabile bind invece di concatenare il valore del parametro e in questo modo nessun trucco SQL Injection può funzionare.

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;
/

Verifica normalmente la procedura precedente

SET SERVEROUTPUT ON;

BEGIN
   prc_get_emp_sal_2 ('7566');
END;
/

Uscita

JONES -- 27706.89
PL/SQL procedure successfully completed.

Verifica la procedura precedente utilizzando SQL injection

SET SERVEROUTPUT ON;

BEGIN
   prc_get_emp_sal_2 ('1'' OR ''1''= ''1');
END;
/

Output SQL injection non riuscito

Can not fetch any records for: 1' OR '1'= '1
PL/SQL procedure successfully completed.

Quindi prendine nota, se stai creando programmi PL/SQL utilizzando SQL dinamico, usa i metodi di collegamento.