Trong phát triển web với PHP, SQL Injection là một trong những lỗ hổng bảo mật phổ biến và nguy hiểm nhất. Hacker có thể chèn các đoạn lệnh SQL độc hại vào input của người dùng để lấy cắp dữ liệu, xóa bảng, hoặc chiếm quyền quản trị hệ thống. Để phòng chống, giải pháp hiệu quả nhất chính là Prepared Statements trong PDO (PHP Data Objects).
Nếu trước đây bạn đã tìm hiểu cách kết nối MySQL bằng PDO trong PHP và triển khai CRUD PHP thuần, thì việc nắm vững kỹ thuật prepared statements sẽ giúp ứng dụng của bạn an toàn hơn. Trong bài viết này, chúng ta sẽ tìm hiểu chi tiết cách hoạt động, cách triển khai và lý do tại sao prepared statements lại chống được SQL Injection.
SQL Injection là gì và nguy hiểm như thế nào?
SQL Injection xảy ra khi ứng dụng chèn trực tiếp dữ liệu đầu vào của người dùng vào câu truy vấn SQL mà không xử lý an toàn. Điều này cho phép kẻ tấn công thay đổi cấu trúc câu lệnh SQL.
Ví dụ, một đoạn code nguy hiểm:
<?php $user = $_POST['username']; $pass = $_POST['password']; $sql = "SELECT * FROM users WHERE username = '$user' AND password = '$pass'"; $stmt = $pdo->query($sql);
Nếu hacker nhập admin' OR '1'='1 vào username, câu SQL sẽ trở thành:
SELECT * FROM users WHERE username = 'admin' OR '1'='1' AND password = ''
Kết quả: hacker có thể đăng nhập mà không cần mật khẩu. Đây chính là SQL Injection.
Nguyên lý của Prepared Statements
Trước khi viết code, cần hiểu rằng prepared statement hoạt động theo 2 bước:
- Chuẩn bị câu lệnh SQL: Trong câu SQL sẽ có placeholder (
?hoặc:name) thay cho dữ liệu người dùng. - Bind dữ liệu và thực thi: PDO sẽ tự động xử lý dữ liệu nhập vào, escape ký tự đặc biệt, và gắn vào placeholder.
Nhờ vậy, dữ liệu người dùng chỉ được coi là giá trị, không bao giờ bị coi là một phần của câu lệnh SQL, từ đó ngăn chặn SQL Injection.
Ví dụ sử dụng Prepared Statements với Placeholder ?
Trước khi viết code, hãy lưu ý rằng kiểu placeholder ? (anonymous) phù hợp với câu SQL có ít tham số. Bạn cần bind dữ liệu theo đúng thứ tự của dấu ?.
Ví dụ dưới đây là đoạn code an toàn cho đăng nhập người dùng:

