Oracle
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Oracle

Một ví dụ để chứng minh lỗ hổng của SQL Injection và cách ngăn chặn nó trong Oracle

Tất cả chúng ta đều biết, nếu bất kỳ mã ứng dụng nào được viết kém, thì bất kỳ ai cũng có thể hack thông tin bằng cách sử dụng một thủ thuật nhỏ như SQL Injection. Trong bài đăng này, tôi đưa ra một ví dụ để chứng minh cách SQL Injection có thể dễ bị tấn công vào một ứng dụng và cách bạn có thể ngăn chặn nó.

Trình diễn dựa trên bảng EMP của lược đồ SCOTT. Để tải xuống tập lệnh lược đồ SCOTT, hãy nhấp vào liên kết sau Tải xuống tập lệnh lược đồ Scott.

Một ví dụ để thực hiện SQL Injection

Trong phần này, tôi đưa ra một ví dụ về thủ tục được lưu trữ PL / SQL sẽ chấp nhận một số nhân viên tham số là (p_empno) để hiển thị mức lương cho nhân viên đó. Trong mã, tôi đang sử dụng nối giá trị tham số (p_empno) đó trong chuỗi câu lệnh SQL cho REF CURSOR, điều này không được khuyến nghị và sẽ là nguyên nhân của SQL Injection thành công. Dưới đây là quy trình:

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

Bây giờ chúng tôi sẽ kiểm tra quy trình trên một cách bình thường bằng cách chuyển một số nhân viên.

Kiểm tra

SET SERVEROUTPUT ON;

BEGIN
   prc_get_emp_sal ('7566');
END;
/

Đầu ra

JONES -- 27706.89
PL/SQL procedure successfully completed.

Cho đến bây giờ mọi thứ vẫn ổn. Bởi vì chúng tôi đã gọi một cách chính xác thủ tục. Bây giờ chúng ta sẽ xem cách chúng ta có thể hack quy trình trên bằng cách sử dụng thủ thuật SQL Injection để lấy lương của tất cả nhân viên. Có lẽ đôi khi bạn cũng muốn làm điều này. Đùa!

Kiểm tra bằng SQL Injection

SET SERVEROUTPUT ON;

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

Đầu ra Chèn SQL thành công

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.

Chà, bây giờ bạn có thể xem mức lương của mọi nhân viên khi sử dụng thủ thuật SQL Injection này. Chỉ cần tưởng tượng, bạn có một trường văn bản trong một ứng dụng, cho dù nó dựa trên trình duyệt hay máy tính để bàn và bạn đang chuyển thẳng giá trị vào quy trình và nếu bạn sử dụng thủ thuật trên thì chắc chắn điều này sẽ xảy ra.

Một ví dụ để ngăn chặn SQL Injection

Bây giờ chúng ta sẽ sửa đổi thủ tục trên để sử dụng biến ràng buộc thay vì nối giá trị tham số và theo cách này, không có thủ thuật SQL Injection nào có thể hoạt động.

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

Kiểm tra quy trình trên một cách bình thường

SET SERVEROUTPUT ON;

BEGIN
   prc_get_emp_sal_2 ('7566');
END;
/

Đầu ra

JONES -- 27706.89
PL/SQL procedure successfully completed.

Kiểm tra quy trình trên bằng SQL Injection

SET SERVEROUTPUT ON;

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

Đầu ra Chèn SQL không thành công

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

Vì vậy, hãy ghi nhớ nó, nếu bạn đang tạo chương trình PL / SQL bằng SQL động, hãy sử dụng các phương thức liên kết.

  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Hàm NLS_LOWER () trong Oracle

  2. Kiểu dữ liệu .NET nào tốt nhất để ánh xạ kiểu dữ liệu NUMBER Oracle trong NHibernate?

  3. điều gì xảy ra trong giai đoạn chuyển tiếp của việc áp dụng trong R12.2

  4. Ví dụ về hàm Pipelined của Oracle

  5. Hợp nhất hai hàng thành một trong khi thay thế các giá trị rỗng