sql >> Database >  >> RDS >> Oracle

Een voorbeeld om de kwetsbaarheid van SQL-injectie en de preventie ervan in Oracle aan te tonen

We weten allemaal dat als een applicatiecode slecht is geschreven, iedereen de informatie kan hacken door een klein trucje te gebruiken, zoals SQL-injectie. In dit bericht geef ik een voorbeeld om aan te tonen hoe SQL-injectie kwetsbaar kan zijn voor een toepassing en hoe u dit kunt voorkomen.

De demonstratie is gebaseerd op de EMP-tabel van het SCOTT-schema. Om het SCOTT-schemascript te downloaden, klikt u op de volgende link Scott Schema Script downloaden.

Een voorbeeld om SQL-injectie uit te voeren

In deze sectie geef ik een voorbeeld van een PL/SQL-opgeslagen procedure die een parameter werknemernummer accepteert als (p_empno) om het salaris voor die werknemer weer te geven. In de code gebruik ik de aaneenschakeling van die parameterwaarde (p_empno) in de SQL-instructiereeks voor REF CURSOR, wat niet wordt aanbevolen en de oorzaak zal zijn van succesvolle SQL-injectie. Hieronder vindt u de procedure:

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

Nu zullen we de bovenstaande procedure normaal testen door een personeelsnummer door te geven.

Test

SET SERVEROUTPUT ON;

BEGIN
   prc_get_emp_sal ('7566');
END;
/

Uitvoer

JONES -- 27706.89
PL/SQL procedure successfully completed.

Tot nu toe is alles in orde. Omdat we de procedure correct hebben genoemd. Nu zullen we zien hoe we de bovenstaande procedure kunnen hacken door de SQL-injectietruc te gebruiken om het salaris van alle werknemers op te halen. Misschien wil jij dit ook wel eens doen. Een grapje!

Test met SQL-injectie

SET SERVEROUTPUT ON;

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

Succesvolle uitvoer van SQL-injectie

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.

Wauw, nu kun je het salaris van elke werknemer zien met deze SQL-injectietruc. Stelt u zich eens voor dat u een tekstveld in een toepassing hebt, of deze nu browsergebaseerd of desktop is, en u geeft de waarde meteen door aan de procedure, en als u de bovenstaande truc toepast, dan zal dit zeker gebeuren.

Een voorbeeld om SQL-injectie te voorkomen

Nu zullen we de bovenstaande procedure aanpassen om de bindvariabele te gebruiken in plaats van de parameterwaarde samen te voegen en op deze manier kan geen enkele SQL-injectietruc werken.

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

Test de bovenstaande procedure normaal

SET SERVEROUTPUT ON;

BEGIN
   prc_get_emp_sal_2 ('7566');
END;
/

Uitgang

JONES -- 27706.89
PL/SQL procedure successfully completed.

Test de bovenstaande procedure met SQL-injectie

SET SERVEROUTPUT ON;

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

Mislukte uitvoer van SQL-injectie

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

Noteer het dus, als u PL/SQL-programma's maakt met dynamische SQL, gebruik dan de bindingsmethoden.

  1. Verwijder dubbele rijen in MySQL (negert primaire sleutel)

  2. Wat is het verschil tussen REFERENTIES met of zonder BUITENLANDSE SLEUTEL?

  3. Een weergave maken in SQL Server

  4. Aangepaste grafieken om uw MySQL-, MariaDB-, MongoDB- en PostgreSQL-systemen te bewaken - ClusterControl Tips &Tricks