Các câu trả lời khác đã bao gồm những gì bạn cần biết. Nhưng có thể nó sẽ giúp làm sáng tỏ thêm một số điều:
Có hai điều bạn cần làm:
1. Xác thực dữ liệu biểu mẫu.
Như câu trả lời của Jonathan Hobbs cho thấy rất rõ ràng, việc lựa chọn phần tử html cho đầu vào biểu mẫu không thực hiện bất kỳ bộ lọc đáng tin cậy nào đối với bạn.
Việc xác thực thường được thực hiện theo cách không làm thay đổi dữ liệu, nhưng sẽ hiển thị lại biểu mẫu, với các trường được đánh dấu là "Vui lòng sửa lỗi này".
Hầu hết các khuôn khổ và CMS đều có trình tạo biểu mẫu giúp bạn thực hiện nhiệm vụ này. Và không chỉ vậy, chúng còn giúp chống lại CSRF (hoặc "XSRF"), là một dạng tấn công khác.
2. Dọn dẹp / Thoát biến trong câu lệnh SQL ..
.. hoặc để các câu lệnh chuẩn bị sẵn thực hiện công việc cho bạn.
Nếu bạn xây dựng một câu lệnh SQL (của Tôi) với bất kỳ biến nào, do người dùng cung cấp hoặc không, bạn cần phải thoát và trích dẫn các biến này.
Nói chung, bất kỳ biến nào như vậy bạn chèn vào một câu lệnh MySQL phải là một chuỗi hoặc một cái gì đó mà PHP có thể biến một cách đáng tin cậy thành một chuỗi mà MySQL có thể tiêu hóa. Chẳng hạn như, các con số.
Đối với chuỗi, sau đó bạn cần chọn một trong một số phương pháp để thoát khỏi chuỗi, nghĩa là thay thế bất kỳ ký tự nào sẽ có tác dụng phụ trong MySQL.
- Trong MySQL + PHP cũ, mysql_real_escape_string () thực hiện công việc. Vấn đề là nó quá dễ quên, vì vậy bạn hoàn toàn nên sử dụng các câu lệnh đã chuẩn bị sẵn hoặc trình tạo truy vấn.
- Trong MySQLi, bạn có thể sử dụng các câu lệnh đã chuẩn bị sẵn.
- Hầu hết các khuôn khổ và CMS đều cung cấp các trình tạo truy vấn giúp bạn thực hiện nhiệm vụ này.
Nếu bạn đang xử lý một số, bạn có thể bỏ qua lối thoát và dấu ngoặc kép (đây là lý do tại sao các câu lệnh đã chuẩn bị cho phép chỉ định một kiểu).
Điều quan trọng là phải chỉ ra rằng bạn thoát khỏi các biến cho câu lệnh SQL và KHÔNG cho chính cơ sở dữ liệu . Cơ sở dữ liệu sẽ lưu trữ chuỗi gốc, nhưng câu lệnh cần phiên bản thoát.
Điều gì xảy ra nếu bạn bỏ qua một trong những điều này?
Nếu bạn không sử dụng xác thực biểu mẫu , nhưng bạn làm sạch đầu vào SQL của mình, bạn có thể thấy tất cả các loại lỗi đang xảy ra, nhưng bạn sẽ không thấy SQL injection! (*)
Đầu tiên, nó có thể đưa ứng dụng của bạn vào trạng thái mà bạn không dự kiến. Ví dụ: nếu bạn muốn tính độ tuổi trung bình của tất cả người dùng, nhưng một người dùng đã cho "aljkdfaqer" cho độ tuổi, thì phép tính của bạn sẽ không thành công.
Thứ hai, có thể có tất cả các loại tấn công tiêm khác mà bạn cần xem xét: Ví dụ: đầu vào của người dùng có thể chứa javascript hoặc những thứ khác.
Vẫn có thể xảy ra sự cố với cơ sở dữ liệu: Ví dụ: nếu một trường (cột trong bảng cơ sở dữ liệu) bị giới hạn ở 255 ký tự và chuỗi dài hơn thế. Hoặc nếu trường chỉ chấp nhận số và bạn cố gắng lưu một chuỗi không phải số. Nhưng đây không phải là "tiêm", nó chỉ là "crash ứng dụng".
Tuy nhiên, ngay cả khi bạn có trường văn bản miễn phí, nơi bạn cho phép bất kỳ đầu vào nào mà không cần xác thực, bạn vẫn có thể lưu trường này vào cơ sở dữ liệu giống như vậy, nếu bạn thoát nó đúng cách khi nó chuyển đến câu lệnh cơ sở dữ liệu. Vấn đề xảy ra khi bạn muốn sử dụng chuỗi này ở đâu đó.
(*) hoặc đây sẽ là một cái gì đó thực sự kỳ lạ.
Nếu bạn không thoát khỏi các biến cho câu lệnh SQL , nhưng bạn đã xác thực đầu vào biểu mẫu, thì bạn vẫn có thể thấy điều tồi tệ xảy ra.
Đầu tiên, bạn có nguy cơ khi bạn lưu dữ liệu vào cơ sở dữ liệu và tải lại, nó sẽ không còn là dữ liệu như cũ nữa, "mất bản chất".
Thứ hai, nó có thể dẫn đến các câu lệnh SQL không hợp lệ và do đó làm hỏng ứng dụng của bạn. Ví dụ: nếu bất kỳ biến nào chứa một dấu ngoặc kép hoặc ký tự dấu ngoặc kép, tùy thuộc vào loại dấu ngoặc kép bạn sử dụng, bạn sẽ nhận được câu lệnh MySQL không hợp lệ.
Thứ ba, nó vẫn có thể gây ra SQL injection.
Nếu đầu vào của người dùng của bạn từ các biểu mẫu đã được lọc / xác thực, thì việc đưa vào SQl có chủ đích có thể trở nên ít xảy ra hơn, NẾU đầu vào của bạn bị giảm thành danh sách tùy chọn được mã hóa cứng hoặc nếu nó bị giới hạn ở số. Nhưng bất kỳ kiểu nhập văn bản miễn phí nào cũng có thể được sử dụng cho SQL injection, nếu bạn không thoát đúng các biến trong câu lệnh SQL.
Và ngay cả khi bạn hoàn toàn không có đầu vào biểu mẫu, bạn vẫn có thể có các chuỗi từ tất cả các loại nguồn: Đọc từ hệ thống tệp, cóp nhặt từ internet, v.v. Không ai có thể đảm bảo rằng các chuỗi này an toàn.
<select>
đầu vào của bạn . Thật vậy, ngay cả một người dùng kỹ thuật một chút cũng có thể thêm các tùy chọn bổ sung bằng bảng điều khiển trình duyệt. nếu bạn giữ một mảng danh sách trắng của các giá trị có sẵn và so sánh đầu vào chống lại nó, bạn có thể giảm thiểu đó (và bạn nên vì nó ngăn chặn các giá trị mong muốn)