Một trong những thế mạnh của PHP là khả năng liên lạc dễ dàng với cơ sở dữ liệu, nhất là MySQL. Tuy nhiên, điều này cũng tiềm ẩn nhiều nguy cơ bảo mật mà hay gặp nhất là SQL Injection – người dùng sử dụng một lỗi bảo mật nào đó để truy vấn trực tiếp vào cơ sở dữ liệu của bạn và lấy các thông tin cần thiết.
Chúng ta hãy bắt đầu việc phân tích lỗi này bằng một truy vấn kiểm tra đăng nhập (đây là phần được rất nhiều website thực hiện):
?
[Copy to clipboard] View Code PHP
1 $check = mysql_query("SELECT Username, Password, UserLevel FROM Users WHERE Username = '".$_POST['username']."' and Password = '".
$_POST['password']."'");
Nhìn có vẻ ổn ? Và thực tế nó sẽ làm việc tốt khi cần kiểm tra thông tin người đăng nhập có hợp lệ hay khơng. Nhưng một hơm nào đó, tơi nhập vào trường username thơng tin sau
' OR 1=1 #
Lúc này câu truy vẫn sẽ được thay đổi thành:
?
[Copy to clipboard] View Code PHP
1 SELECT Username, Password FROM Users WHERE Username = '' OR 1=1 #' and Password = ''
Ký tự thăng (#) cho lệnh truy vấn sẽ xác định đoạn phía sau nó là một đoạn ghi chú (comment) và sẽ bỏ qua. Lúc này, câu truy vấn sẽ thực hiện đến đoạn trước dấu thăng (#) mà thơi. 1 thì ln luôn bằng 1 đúng không . Và như vậy, hacker dễ dàng vượt qua vòng kiểm tra mật khẩu :( . Chỉ cần biết thêm username của một quản trị viên nào đó nữa là có thể đăng nhập dễ dàng.
Bằng một chút sáng tạo của mình, hacker có thể khai thác tiếp rất nhiều thơng tin của người quản trị này như thơng tin thẻ tín dụng, địa chỉ email hay có thể chiếm quyền quản trị website để khai thác thông tin người dùng.
May q, lỗi này có thể được vơ hiệu hóa dễ dàng bằng cách kiểm tra các dấu nháy (‘) do người dùng nhập và vơ hiệu hóa chúng bằng hàm sau (hoặc bạn có thể viết thêm để kiểm tra kĩ càng hơn):
?
[Copy to clipboard] View Code PHP
12 2 3 function make_safe($variable) { $variable = mysql_real_escape_string(trim($variable)); return $variable;
4 }
Bây giờ, trước khi chạy đoạn lệnh truy vấn cơ sở dữ liệu đã nói ở trên, chúng ta sẻ dụng hàm make_safe để vơ hiệu hóa các kí tự nhạy :
?
[Copy to clipboard] View Code PHP
12 2 3
$username = make_safe($_POST['username']); $password = make_safe($_POST['password']);
$check = mysql_query("SELECT Username, Password, UserLevel FROM Users
WHERE Username = '".$username."' and Password = '".$password."'");
Bây giờ, các dữ liệu độc hại ở trên được vơ hiệu hóa trước khi thực hiện lệnh truy vấn. Lúc này dữ liệu nhập vào được sửa thành “\ ‘OR 1 = 1 #” trước khi thực hiện truy vấn.
?
[Copy to clipboard] View Code PHP
1 SELECT Username1=1 #' and Password = '', Password, UserLevel FROM Users WHERE Username = '' OR
Bây giờ, trừ khi trong cơ sở dữ liệu của bạn chứa 1 dòng dữ liệu đặc biệt nào đó mà hacker có thể khơng cần đăng nhập. Nếu không, chúng ta không cần phải lo.
Khai thác tập tin
Một số trang web chạy đoạn URL như thế này:
?
[Copy to clipboard] View Code PHP
1 index.php?page=contactus.html
Với trường hợp này, thơng thường mục đích của lập trình viên là chạy đoạn mã được lưu trong file contactus.html trong file index.php. Chuyện gì sẽ xảy ra nếu người dùng thay thế contactus.html thành một trang nào đó ? Ví dụ, nếu bạn đang sử dụng Apache ‘s mod_auth để bảo vệ các tập tin và có lưu mật khẩu của bạn trong một tập tin có tên “. htpasswd” (tên gọi thơng thường), sau đó nếu người dùng đã truy cập vào địa chỉ sau, script sẽ ra tên người dùng của bạn và mật khẩu:
?
[Copy to clipboard] View Code PHP