Hướng dẫn SQL

TRANG CHỦ SQL Giới thiệu SQL Cú pháp SQL Lựa chọn SQL SQL Chọn phân biệt SQL ở đâu SQL Và, Hoặc, Không Đặt hàng SQL theo Chèn SQL vào Giá trị rỗng trong SQL Cập nhật SQL SQL Delete SQL Select Top SQL Min và Max Số lượng SQL, Trung bình, Tổng SQL như Ký tự đại diện SQL SQL trong SQL giữa Bí danh SQL SQL tham gia Tham gia bên trong SQL SQL còn lại tham gia SQL Right Join Tham gia đầy đủ SQL SQL tự tham gia SQL Union Nhóm SQL bởi SQL có SQL tồn tại SQL Bất kỳ, Tất cả SQL chọn vào Chèn SQL vào vùng chọn Trường hợp SQL Hàm Null trong SQL Thủ tục lưu trữ SQL Nhận xét SQL Toán tử SQL

Cơ sở dữ liệu SQL

SQL Tạo cơ sở dữ liệu SQL Drop DB Cơ sở dữ liệu sao lưu SQL SQL Tạo bảng Bảng thả SQL Bảng thay thế SQL Các ràng buộc SQL SQL không rỗng SQL duy nhất Khóa chính SQL Khóa ngoại SQL Kiểm tra SQL SQL mặc định Chỉ mục SQL Tăng tự động SQL SQL Dates Chế độ xem SQL SQL Injection Lưu trữ SQL Các kiểu dữ liệu SQL

Tham chiếu SQL

Từ khóa SQL Các chức năng của MySQL Các chức năng của SQL Server Chức năng MS Access Tham khảo nhanh SQL

Ví dụ về SQL

Ví dụ về SQL Câu hỏi SQL Bài tập SQL Chứng chỉ SQL

SQL Injection


SQL Injection

SQL injection là một kỹ thuật chèn mã có thể phá hủy cơ sở dữ liệu của bạn.

SQL injection là một trong những kỹ thuật hack web phổ biến nhất.

SQL injection là vị trí của mã độc hại trong các câu lệnh SQL, thông qua đầu vào trang web.


SQL trong các 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 vào, như tên người dùng / userrid của họ và thay vì tên / id, người dùng 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 một SELECTcâu lệnh bằng cách thêm một biến (txtUserId) vào một chuỗi được chọn. Biến được tìm nạp từ đầu vào của người dùng (getRequestString):

Thí 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 nguy cơ tiềm ẩn khi sử dụng đầu vào của người dùng trong các câu lệnh SQL.


SQL Injection dựa trên 1 = 1 luôn đúng

Nhìn lại ví dụ trên. 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 một id người dùng nhất định.

Nếu không có gì ngăn người dùng nhập "sai" đầu vào, người dùng có thể nhập một số đầu vào "thông minh" như sau:

Tên người dùng:

Sau đó, câu lệnh SQL sẽ giống như sau:

SELECT * FROM Users WHERE UserId = 105 OR 1=1;

SQL ở trên là 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ó 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 giống như sau:

SELECT UserId, Name, Password FROM Users WHERE UserId = 105 or 1=1;

Một 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, bằng cách chỉ cần chèn 105 OR 1 = 1 vào trường đầu vào.



SQL Injection dựa trên "" = "" luôn đúng

Đây là một ví dụ về đăng nhập của người dùng trên một trang web:

Tên tài khoản:

Mật khẩu:

Thí 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"

Một tin tặc có thể có quyền 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ỉ cần chèn "HOẶC" "=" 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ư sau:

Kết quả

SELECT * FROM Users WHERE Name ="" or ""="" AND Pass ="" or ""=""

SQL ở trên là hợp lệ và sẽ trả về tất cả các hàng từ bảng "Người dùng", vì HOẶC "" = "" luôn là TRUE.


SQL Injection dựa trên các câu lệnh SQL theo lô 

Hầu hết các cơ sở dữ liệu hỗ trợ câu lệnh SQL theo lô.

Một loạt câu lệnh SQL là một nhóm gồm hai hoặc nhiều câu lệnh SQL, đượ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".

Thí dụ

SELECT * FROM Users; DROP TABLE Suppliers

Hãy xem ví dụ sau:

Thí 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 giống như sau:

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 SQL injection, 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ề ASP.NET Razor

txtUserId = getRequestString("UserId");
txtSQL = "SELECT * FROM Users WHERE UserId = @0";
db.Execute(txtSQL,txtUserId);

Lưu ý rằng các tham số được biểu diễ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, và không phải là một phần của SQL đượ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);

Các 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 trong một số ngôn ngữ web phổ biến.

CHỌN BÁO CÁO 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 BÁO CÁO 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 BÁO CÁO 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();