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

Et eksempel til at demonstrere sårbarheden af ​​SQL-injektion og dens forebyggelse i Oracle

Vi ved alle, at hvis en applikationskode er dårligt skrevet, så kan enhver hacke informationen ved at bruge et lille trick såsom SQL Injection. I dette indlæg giver jeg et eksempel for at demonstrere, hvordan SQL Injection kan være sårbar over for en applikation, og hvordan du kan forhindre det.

Demonstrationen er baseret på SCOTT-skemaets EMP-tabel. For at downloade SCOTT-skemascriptet skal du klikke på følgende link Download Scott Schema Script.

Et eksempel til at udføre SQL-injektion

I dette afsnit giver jeg et eksempel på en PL/SQL-lagret procedure, som vil acceptere et parameter medarbejdernummer som (p_empno) for at vise lønnen for den pågældende medarbejder. I koden bruger jeg sammenkædningen af ​​den parameter (p_empno) værdi i SQL-sætningsstrengen for REF CURSOR, som ikke anbefales og vil være årsagen til en vellykket SQL-injektion. Nedenfor er proceduren:

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 vil vi teste ovenstående procedure normalt ved at videregive et medarbejdernummer.

Test

SET SERVEROUTPUT ON;

BEGIN
   prc_get_emp_sal ('7566');
END;
/

Output

JONES -- 27706.89
PL/SQL procedure successfully completed.

Indtil nu er alt fint. Fordi vi kaldte proceduren korrekt. Nu vil vi se, hvordan vi kan hacke ovenstående procedure ved at bruge SQL Injection-tricket til at hente lønnen til alle medarbejdere. Måske har du nogle gange også lyst til at gøre dette. Spøg!

Test ved hjælp af SQL Injection

SET SERVEROUTPUT ON;

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

Succesfuldt SQL-injektionsoutput

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, nu kan du se hver medarbejders løn ved at bruge dette SQL Injection-trick. Forestil dig bare, at du har et tekstfelt i et program, uanset om det er browserbaseret eller desktop, og du sender værdien med det samme til proceduren, og hvis du bruger ovenstående trick, så vil dette helt sikkert ske.

Et eksempel til at forhindre SQL-injektion

Nu vil vi ændre ovenstående procedure til at bruge bind-variablen i stedet for at sammenkæde parameterværdien, og på denne måde kan intet SQL-injektionstrick fungere.

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 ovenstående procedure normalt

SET SERVEROUTPUT ON;

BEGIN
   prc_get_emp_sal_2 ('7566');
END;
/

Output

JONES -- 27706.89
PL/SQL procedure successfully completed.

Test ovenstående procedure ved hjælp af SQL Injection

SET SERVEROUTPUT ON;

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

Mislykket SQL Injection Output

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

Så noter det, hvis du opretter PL/SQL-programmer ved hjælp af dynamisk SQL, så brug bindingsmetoderne.

  1. Kan ikke oprette forbindelse til lokal MySQL-server via socket '/tmp/mysql.sock

  2. System.Data.OracleClient kræver Oracle-klientsoftware version 8.1.7

  3. Top 5 fakta til at finde og erstatte SQL-tekster i SQL Server med REPLACE-funktionen

  4. Sådan fungerer UPDATEXML() i MariaDB