Tiêm SQL
Tiêm SQL
SQL SQL là một kỹ thuật chèn mã có thể phá hủy cơ sở dữ liệu của bạn.
SQL SQL là một trong những kỹ thuật hack web phổ biến nhất.
SQL SQL là việc đặt mã độc vào câu lệnh SQL thông qua đầu vào trang web.
SQL trong trang web
Việc chèn SQL thường xảy ra khi bạn yêu cầu người dùng nhập dữ liệu, chẳng hạn như tên người dùng/userid của họ và thay vì tên/id, người dùng sẽ cung cấp cho bạn một câu lệnh SQL mà bạn sẽ vô tình chạy trên cơ sở dữ liệu của mình.
Hãy xem ví dụ sau để tạo câu lệnh SELECT
bằng cách thêm một biến (txtUserId) vào chuỗi chọn. Biến được tìm nạp từ đầu vào của người dùng (getRequestString):
Ví dụ
txtUserId = getRequestString("UserId");
txtSQL = "SELECT *
FROM Users WHERE UserId = " + txtUserId;
Phần còn lại của chương này mô tả những mối nguy hiểm tiềm ẩn khi sử dụng dữ liệu đầu vào của người dùng trong các câu lệnh SQL.
Việc tiêm SQL dựa trên 1=1 luôn đúng
Hãy nhìn lại ví dụ trên một lần nữa. Mục đích ban đầu của mã là tạo một câu lệnh SQL để chọn một người dùng với id người dùng nhất định.
Nếu không có gì ngăn cản người dùng nhập dữ liệu "sai", người dùng có thể nhập một số dữ liệu nhập "thông minh" như thế này:
Tên người dùng:
Sau đó, câu lệnh SQL sẽ trông như thế này:
SELECT * FROM Users WHERE UserId = 105 OR 1=1;
SQL ở trên hợp lệ và sẽ trả về TẤT CẢ các hàng từ bảng "Người dùng", vì OR 1=1 luôn là TRUE.
Ví dụ trên có vẻ nguy hiểm không? Điều gì sẽ xảy ra nếu bảng "Người dùng" chứa tên và mật khẩu?
Câu lệnh SQL ở trên gần giống như sau:
SELECT UserId, Name, Password
FROM Users WHERE UserId = 105 or 1=1;
Tin tặc có thể có quyền truy cập vào tất cả tên người dùng và mật khẩu trong cơ sở dữ liệu chỉ bằng cách chèn 105 OR 1=1 vào trường nhập.
Việc tiêm SQL dựa trên ""="" luôn đúng
Dưới đây là ví dụ về người dùng đăng nhập vào một trang web:
Tên tài khoản:
Mật khẩu:
Ví dụ
uName = getRequestString("username");
uPass = getRequestString("userpassword");
sql = 'SELECT * FROM Users WHERE Name ="' + uName + '" AND Pass ="' + uPass +
'"'
Kết quả
SELECT * FROM Users WHERE Name ="John Doe" AND Pass ="myPass"
Tin tặc có thể truy cập vào tên người dùng và mật khẩu trong cơ sở dữ liệu bằng cách chèn " OR ""=" vào hộp văn bản tên người dùng hoặc mật khẩu:
Tên tài khoản:
Mật khẩu:
Mã tại máy chủ sẽ tạo một câu lệnh SQL hợp lệ như thế này:
Kết quả
SELECT * FROM Users WHERE Name ="" or ""="" AND Pass ="" or ""=""
SQL ở trên hợp lệ và sẽ trả về tất cả các hàng từ bảng "Người dùng", vì OR ""="" luôn là TRUE.
SQL SQL dựa trên các câu lệnh SQL hàng loạt
Hầu hết các cơ sở dữ liệu đều hỗ trợ câu lệnh SQL theo đợt.
Một loạt câu lệnh SQL là một nhóm gồm hai câu lệnh SQL trở lên, được phân tách bằng dấu chấm phẩy.
Câu lệnh SQL bên dưới sẽ trả về tất cả các hàng từ bảng "Người dùng", sau đó xóa bảng "Nhà cung cấp".
Ví dụ
SELECT * FROM Users; DROP TABLE Suppliers
Hãy xem ví dụ sau:
Ví dụ
txtUserId = getRequestString("UserId");
txtSQL = "SELECT *
FROM Users WHERE UserId = " + txtUserId;
Và đầu vào sau:
Tên người dùng:
Câu lệnh SQL hợp lệ sẽ trông như thế này:
Kết quả
SELECT * FROM Users WHERE
UserId = 105; DROP TABLE Suppliers;
Sử dụng tham số SQL để bảo vệ
Để bảo vệ một trang web khỏi việc tiêm SQL, bạn có thể sử dụng các tham số SQL.
Tham số SQL là các giá trị được thêm vào truy vấn SQL tại thời điểm thực thi, theo cách được kiểm soát.
Ví dụ về dao cạo ASP.NET
txtUserId = getRequestString("UserId");
txtSQL = "SELECT *
FROM Users WHERE UserId = @0";
db.Execute(txtSQL,txtUserId);
Lưu ý rằng các tham số được thể hiện trong câu lệnh SQL bằng dấu @.
Công cụ SQL kiểm tra từng tham số để đảm bảo rằng nó đúng với cột của nó và được xử lý theo nghĩa đen chứ không phải là một phần của SQL sẽ được thực thi.
Một vi dụ khac
txtNam = getRequestString("CustomerName");
txtAdd = getRequestString("Address");
txtCit = getRequestString("City");
txtSQL = "INSERT INTO Customers (CustomerName,Address,City) Values(@0,@1,@2)";
db.Execute(txtSQL,txtNam,txtAdd,txtCit);
Ví dụ
Các ví dụ sau đây cho thấy cách xây dựng các truy vấn được tham số hóa bằng một số ngôn ngữ web phổ biến.
TUYÊN BỐ CHỌN TRONG ASP.NET:
txtUserId = getRequestString("UserId");
sql = "SELECT * FROM Customers WHERE CustomerId = @0";
command = new SqlCommand(sql);
command.Parameters.AddWithValue("@0",txtUserId);
command.ExecuteReader();
CHÈN VÀO TUYÊN BỐ TRONG ASP.NET:
txtNam = getRequestString("CustomerName");
txtAdd = getRequestString("Address");
txtCit = getRequestString("City");
txtSQL = "INSERT INTO Customers (CustomerName,Address,City) Values(@0,@1,@2)";
command = new SqlCommand(txtSQL);
command.Parameters.AddWithValue("@0",txtNam);
command.Parameters.AddWithValue("@1",txtAdd);
command.Parameters.AddWithValue("@2",txtCit);
command.ExecuteNonQuery();
CHÈN VÀO TUYÊN BỐ TRONG PHP:
$stmt = $dbh->prepare("INSERT INTO Customers (CustomerName,Address,City)
VALUES (:nam, :add, :cit)");
$stmt->bindParam(':nam', $txtNam);
$stmt->bindParam(':add', $txtAdd);
$stmt->bindParam(':cit', $txtCit);
$stmt->execute();