SQL Injection là gì và cách phòng ngừa trong các ứng dụng PHP?

Vì vậy, bạn nghĩ rằng cơ sở dữ liệu SQL của bạn là hiệu suất và an toàn khỏi sự phá hủy ngay lập tức? Chà, SQL Injection không đồng ý!


Vâng, đó là sự phá hủy tức thì mà chúng tôi đang nói đến, bởi vì tôi không muốn mở bài viết này với thuật ngữ khập khiễng thông thường về việc siết chặt bảo mật, và ngăn chặn truy cập độc hại. SQL Injection là một thủ thuật cũ trong cuốn sách mà mọi người, mọi nhà phát triển, đều biết về nó rất rõ và nhận thức rõ về cách ngăn chặn nó. Ngoại trừ một lần kỳ lạ khi họ trượt lên, và kết quả có thể không có gì là tai hại.

Nếu bạn đã biết SQL Injection là gì, vui lòng bỏ qua nửa sau của bài viết. Nhưng đối với những người mới bắt đầu trong lĩnh vực phát triển web và đang mơ ước được đảm nhận các vai trò cao cấp hơn, một số giới thiệu là theo thứ tự.

SQL tiêm là gì?

Chìa khóa để hiểu SQL Injection nằm ở tên của nó: SQL + Injection. Từ “tiêm chích” ở đây không có ý nghĩa y tế, nhưng thay vào đó là cách sử dụng động từ tiêm chích. Cùng nhau, hai từ này truyền đạt ý tưởng đưa SQL vào một ứng dụng web.

Đưa SQL vào một ứng dụng web. . . hừm . . Đây có phải là những gì chúng tôi làm không? Có, nhưng chúng tôi không muốn kẻ tấn công lái cơ sở dữ liệu của chúng tôi. Hãy để hiểu rằng với sự giúp đỡ của một ví dụ.

Hãy nói rằng bạn đang xây dựng một trang web PHP điển hình cho một cửa hàng thương mại điện tử địa phương, vì vậy bạn quyết định thêm một hình thức liên hệ như thế này:

Tên của bạn

Tin nhắn của bạn

Và hãy để Giả sử tập tin send_message.php lưu trữ mọi thứ trong cơ sở dữ liệu để chủ sở hữu cửa hàng có thể đọc tin nhắn của người dùng sau này. Nó có thể có một số mã như thế này:

<?php

$ name = $ _POST [‘name’];
$ tin nhắn = $ _POST [‘tin nhắn’];

// kiểm tra xem người dùng này đã có tin nhắn chưa
mysqli_query ($ Conn, "CHỌN * từ các tin nhắn trong đó name = $ name");

// Mã khác ở đây

Vì vậy, trước tiên bạn hãy thử xem người dùng này đã có tin nhắn chưa đọc chưa. Truy vấn CHỌN * từ các tin nhắn trong đó name = $ name có vẻ đơn giản, đúng không?

SAI LẦM!

Trong sự ngây thơ của chúng tôi, chúng tôi đã mở các cánh cửa để phá hủy cơ sở dữ liệu của chúng tôi ngay lập tức. Để điều này xảy ra, kẻ tấn công phải có các điều kiện sau:

  • Ứng dụng này đang chạy trên cơ sở dữ liệu SQL (ngày nay, hầu hết mọi ứng dụng đều như vậy)
  • Kết nối cơ sở dữ liệu hiện tại có các quyền chỉnh sửa và xóa xóa các quyền của cơ sở dữ liệu trên cơ sở dữ liệu
  • Tên của các bảng quan trọng có thể được đoán

Điểm thứ ba có nghĩa là bây giờ kẻ tấn công biết bạn đang điều hành một cửa hàng thương mại điện tử, bạn rất có thể lưu trữ dữ liệu đơn hàng trong bảng đơn hàng. Được trang bị tất cả những điều này, tất cả những kẻ tấn công cần làm là cung cấp tên này như tên của chúng:

Joe; đơn đặt hàng cắt ngắn ;? Vâng thưa ngài! Hãy để xem các truy vấn sẽ trở thành gì khi nó được thực thi bởi tập lệnh PHP:

CHỌN * TỪ tin nhắn WHERE tên = Joe; cắt ngắn đơn đặt hàng;

Được rồi, phần đầu tiên của truy vấn có lỗi cú pháp (không có dấu ngoặc kép xung quanh của Joe Joe), nhưng dấu chấm phẩy buộc công cụ MySQL bắt đầu diễn giải một lệnh mới: cắt ngắn các đơn đặt hàng. Cứ như thế, chỉ trong một cú nhấn, toàn bộ lịch sử đơn hàng đã biến mất!

Bây giờ bạn đã biết SQL tiêm hoạt động như thế nào, đã đến lúc phải xem cách ngăn chặn nó. Hai điều kiện cần được đáp ứng để tiêm SQL thành công là:

  1. Tập lệnh PHP phải có các đặc quyền sửa đổi / xóa trên cơ sở dữ liệu. Tôi nghĩ điều này đúng với tất cả các ứng dụng và bạn sẽ không thể làm cho ứng dụng của mình ở chế độ chỉ đọc. Và đoán xem, ngay cả khi chúng tôi xóa tất cả các đặc quyền sửa đổi, SQL tiêm vẫn có thể cho phép ai đó chạy các truy vấn CHỌN và xem tất cả cơ sở dữ liệu, bao gồm dữ liệu nhạy cảm. Nói cách khác, việc giảm mức truy cập cơ sở dữ liệu không hoạt động và ứng dụng của bạn vẫn cần nó.
  2. Đầu vào của người dùng đang được xử lý. Cách duy nhất SQL có thể hoạt động là khi bạn chấp nhận dữ liệu từ người dùng. Một lần nữa, nó không thực tế để dừng tất cả các đầu vào cho ứng dụng của bạn chỉ vì bạn lo lắng về việc tiêm SQL.

Ngăn chặn SQL SQL trong PHP

Bây giờ, do các kết nối cơ sở dữ liệu, truy vấn và đầu vào của người dùng là một phần của cuộc sống, làm thế nào để chúng ta ngăn chặn SQL SQL? Rất may, nó rất đơn giản và có hai cách để thực hiện: 1) vệ sinh đầu vào của người dùng và 2) sử dụng các câu lệnh đã chuẩn bị.

Vệ sinh đầu vào của người dùng

Nếu bạn sử dụng phiên bản PHP cũ hơn (5.5 trở xuống và điều này xảy ra rất nhiều trên dịch vụ lưu trữ chia sẻ), thì bạn nên khôn ngoan chạy tất cả đầu vào của người dùng thông qua một chức năng gọi là mysql_real_escape_opes (). Về cơ bản, những gì nó làm sẽ loại bỏ tất cả các ký tự đặc biệt trong một chuỗi để chúng mất đi ý nghĩa khi được sử dụng bởi cơ sở dữ liệu.

Ví dụ: nếu bạn có một chuỗi như tôi là một chuỗi, ký tự trích dẫn (‘) có thể được sử dụng bởi kẻ tấn công để thao tác truy vấn cơ sở dữ liệu được tạo và gây ra lỗi SQL. Việc chạy nó thông qua mysql_real_escape_opes () tạo ra tôi là một chuỗi, thêm dấu gạch chéo ngược vào trích dẫn đơn, thoát khỏi nó. Kết quả là toàn bộ chuỗi bây giờ được chuyển thành một chuỗi vô hại cho cơ sở dữ liệu, thay vì có thể tham gia thao tác truy vấn.

Có một nhược điểm với cách tiếp cận này: đó là một kỹ thuật thực sự rất cũ đi cùng với các hình thức truy cập cơ sở dữ liệu cũ hơn trong PHP. Kể từ phiên bản PHP 7, chức năng này không còn tồn tại nữa, điều này đưa chúng ta đến giải pháp tiếp theo.

Sử dụng báo cáo đã chuẩn bị

Báo cáo chuẩn bị là một cách để làm cho các truy vấn cơ sở dữ liệu an toàn và đáng tin cậy hơn. Ý tưởng là thay vì gửi truy vấn thô đến cơ sở dữ liệu, trước tiên chúng tôi cho cơ sở dữ liệu biết cấu trúc của truy vấn mà chúng tôi sẽ gửi. Đây là những gì chúng tôi muốn nói bằng cách chuẩn bị một bản tuyên bố. Sau khi một câu lệnh được chuẩn bị, chúng tôi chuyển thông tin dưới dạng các đầu vào được tham số hóa để cơ sở dữ liệu có thể lấp đầy các khoảng trống bằng cách cắm các đầu vào vào cấu trúc truy vấn mà chúng tôi đã gửi trước đó. Điều này sẽ lấy đi bất kỳ sức mạnh đặc biệt nào mà các đầu vào có thể có, khiến chúng được coi là các biến đơn thuần (hoặc tải trọng, nếu bạn muốn) trong toàn bộ quá trình. Ở đây, những gì các tuyên bố đã chuẩn bị trông như thế nào:

<?php
$ tên máy chủ = "localhost";
$ tên người dùng = "tên tài khoản";
$ mật khẩu = "mật khẩu";
$ dbname = "myDB";

// Tạo kết nối
$ Conn = new mysqli ($ servername, $ username, $ password, $ dbname);

// Kiểm tra kết nối
nếu ($ Conn->kết nối lỗi) {
chết("Kết nối thất bại: " . $ Conn->kết nối lỗi);
}

// chuẩn bị và ràng buộc
$ stmt = $ Conn->chuẩn bị("XÁC NHẬN VÀO MyGuests (tên, họ, email) GIÁ TRỊ (?,?,?)");
$ stmt->bind_param ("sss", $ tên, $ họ, $ email);

// đặt tham số và thực thi
$ tên đầu tiên = "John";
$ họ "Doe";
$ email = "[email được bảo vệ]";
$ stmt->hành hình();

$ tên đầu tiên = "Mary";
$ họ "Mơ";
$ email = "[email được bảo vệ]";
$ stmt->hành hình();

$ tên đầu tiên = "Julie";
$ họ "Dooley";
$ email = "[email được bảo vệ]";
$ stmt->hành hình();

tiếng vang "Bản ghi mới được tạo thành công";

$ stmt->đóng();
$ Conn->đóng();
?>

Tôi biết quy trình nghe có vẻ phức tạp không cần thiết nếu bạn mới biết về các tuyên bố đã chuẩn bị, nhưng khái niệm này rất đáng để nỗ lực. Tại đây một lời giới thiệu hay về nó.

Đối với những người đã quen thuộc với tiện ích mở rộng PDO của PHP và sử dụng nó để tạo các câu lệnh đã chuẩn bị, tôi có một lời khuyên nhỏ.

Cảnh báo: Cẩn thận khi thiết lập PDO

Khi sử dụng PDO để truy cập cơ sở dữ liệu, chúng ta có thể bị cuốn vào một cảm giác an toàn sai lầm. Mạnh Ah, tốt, tôi sử dụng PDO. Bây giờ tôi không cần phải nghĩ về bất cứ điều gì khác nữa – đây là cách suy nghĩ của chúng ta thường diễn ra. Điều đó đúng là PDO (hoặc các câu lệnh được chuẩn bị bởi MySQLi) là đủ để ngăn chặn tất cả các loại tấn công SQL SQL, nhưng bạn phải cẩn thận khi thiết lập nó. Nó phổ biến để chỉ sao chép-dán mã từ hướng dẫn hoặc từ các dự án trước đó của bạn và tiếp tục, nhưng cài đặt này có thể hoàn tác mọi thứ:

$ dbConnection->setAttribution (PDO :: ATTR_EMULATE_PREPARES, đúng);

Những gì cài đặt này làm là yêu cầu PDO mô phỏng các câu lệnh đã chuẩn bị thay vì thực sự sử dụng tính năng câu lệnh đã chuẩn bị của cơ sở dữ liệu. Do đó, PHP gửi các chuỗi truy vấn đơn giản đến cơ sở dữ liệu ngay cả khi mã của bạn trông giống như nó tạo ra các câu lệnh đã chuẩn bị và cài đặt các tham số và tất cả điều đó. Nói cách khác, bạn có thể dễ bị tiêm SQL như trước đây. ��

Giải pháp rất đơn giản: đảm bảo mô phỏng này được đặt thành false.

$ dbConnection->setAttribution (PDO :: ATTR_EMULATE_PREPARES, sai);

Bây giờ tập lệnh PHP buộc phải sử dụng các câu lệnh được chuẩn bị ở mức cơ sở dữ liệu, ngăn chặn tất cả các kiểu SQL SQL.

Ngăn chặn sử dụng WAF

Bạn có biết bạn cũng có thể bảo vệ các ứng dụng web khỏi SQL tiêm bằng cách sử dụng WAF (tường lửa ứng dụng web)?

Chà, không chỉ SQL SQL mà nhiều lỗ hổng lớp 7 khác như kịch bản chéo trang, xác thực bị hỏng, giả mạo chéo trang, tiếp xúc dữ liệu, v.v. Hoặc bạn có thể sử dụng tự lưu trữ như Mod Security hoặc dựa trên đám mây như sau.

SQL SQL và các khung công tác PHP hiện đại

Việc tiêm SQL rất phổ biến, quá dễ dàng, gây nản lòng và nguy hiểm đến mức tất cả các khung web PHP hiện đại đều được tích hợp sẵn các biện pháp đối phó. Ví dụ, trong WordPress, chúng tôi có $ wpdb->Hàm Chuẩn bị (), trong khi nếu bạn sử dụng một khung công tác MVC, thì nó thực hiện tất cả các công việc bẩn thỉu cho bạn và bạn thậm chí không phải nghĩ đến việc ngăn chặn việc tiêm SQL. Nó có một chút khó chịu khi trong WordPress bạn phải chuẩn bị các câu lệnh một cách rõ ràng, nhưng này, nó là WordPress mà chúng tôi đang nói đến. ��

Dù sao, quan điểm của tôi là, các nhà phát triển web hiện đại don don phải suy nghĩ về việc tiêm SQL, và kết quả là, họ thậm chí còn nhận thức được khả năng này. Như vậy, ngay cả khi họ để một cửa hậu mở trong ứng dụng của họ (có thể đó là một tham số truy vấn $ _GET và thói quen cũ để thực hiện một cú truy vấn bẩn), kết quả có thể rất thảm khốc. Vì vậy, nó luôn luôn tốt hơn để dành thời gian để đi sâu hơn vào nền tảng.

Phần kết luận

SQL Injection là một cuộc tấn công rất khó chịu trên một ứng dụng web nhưng có thể dễ dàng tránh được. Như chúng ta đã thấy trong bài viết này, hãy cẩn thận khi xử lý dữ liệu nhập của người dùng (nhân tiện, SQL Injection không phải là mối đe dọa duy nhất mà việc xử lý đầu vào của người dùng mang lại) và truy vấn cơ sở dữ liệu là tất cả. Điều đó nói rằng, chúng tôi luôn luôn làm việc trong bảo mật của một khung web, vì vậy, tốt hơn hết là bạn nên biết về loại tấn công này và không thuộc về nó.

Jeffrey Wilson Administrator
Sorry! The Author has not filled his profile.
follow me
    Like this post? Please share to your friends:
    Adblock
    detector
    map