SQLite - Injection
Nếu bạn lấy thông tin đầu vào của người dùng thông qua một trang web và chèn nó vào cơ sở dữ liệu SQLite, có khả năng bạn đã bỏ ngỏ cho một vấn đề bảo mật được gọi là SQL Injection. Trong chương này, bạn sẽ học cách giúp ngăn điều này xảy ra và giúp bạn bảo mật các tập lệnh và câu lệnh SQLite của mình.
Injection thường xảy ra khi bạn yêu cầu người dùng nhập vào, chẳng hạn như tên của họ, và thay vì tên họ cung cấp cho bạn một câu lệnh SQLite mà bạn sẽ vô tình chạy trên cơ sở dữ liệu của mình.
Không bao giờ tin tưởng vào dữ liệu do người dùng cung cấp, chỉ xử lý dữ liệu này sau khi xác nhận; như một quy luật, điều này được thực hiện bằng cách đối sánh mẫu. Trong ví dụ sau, tên người dùng bị hạn chế đối với các ký tự chữ và số cộng với dấu gạch dưới và có độ dài từ 8 đến 20 ký tự - hãy sửa đổi các quy tắc này nếu cần.
if (preg_match("/^\w{8,20}$/", $_GET['username'], $matches)){
$db = new SQLiteDatabase('filename');
$result = @$db->query("SELECT * FROM users WHERE username = $matches[0]");
} else {
echo "username not accepted";
}
Để chứng minh vấn đề, hãy xem đoạn trích này -
$name = "Qadir'; DELETE FROM users;";
@$db->query("SELECT * FROM users WHERE username = '{$name}'");
Lời gọi hàm được cho là lấy một bản ghi từ bảng người dùng trong đó cột tên khớp với tên được chỉ định bởi người dùng. Trong những trường hợp bình thường,$namesẽ chỉ chứa các ký tự chữ và số và có thể là khoảng trắng, chẳng hạn như chuỗi ilia. Tuy nhiên trong trường hợp này, bằng cách thêm một truy vấn hoàn toàn mới vào $ name, lệnh gọi đến cơ sở dữ liệu sẽ trở thành một thảm họa: truy vấn DELETE được đưa vào sẽ xóa tất cả các bản ghi khỏi người dùng.
Có những giao diện cơ sở dữ liệu không cho phép xếp chồng truy vấn hoặc thực hiện nhiều truy vấn trong một lệnh gọi hàm duy nhất. Nếu bạn cố gắng xếp chồng các truy vấn, cuộc gọi không thành công nhưng SQLite và PostgreSQL, vui vẻ thực hiện các truy vấn xếp chồng, thực thi tất cả các truy vấn được cung cấp trong một chuỗi và tạo ra một vấn đề bảo mật nghiêm trọng.
Ngăn chặn SQL Injection
Bạn có thể xử lý tất cả các ký tự thoát một cách thông minh bằng các ngôn ngữ lập trình như PERL và PHP. Ngôn ngữ lập trình PHP cung cấp chức năngstring sqlite_escape_string() để thoát các ký tự đầu vào đặc biệt đối với SQLite.
if (get_magic_quotes_gpc()) {
$name = sqlite_escape_string($name);
}
$result = @$db->query("SELECT * FROM users WHERE username = '{$name}'");
Mặc dù mã hóa giúp chèn dữ liệu an toàn, nhưng nó sẽ hiển thị các so sánh văn bản đơn giản và LIKE các mệnh đề trong truy vấn của bạn không thể sử dụng được cho các cột chứa dữ liệu nhị phân.
Note - addslashes()KHÔNG được sử dụng để trích dẫn các chuỗi của bạn cho các truy vấn SQLite; nó sẽ dẫn đến kết quả lạ khi lấy dữ liệu của bạn.