Ở bài viết này chúng tôi đề cập sâu về khía cạnh SQL Injection với các website ASP.Net, tuy nhiên bạn cần hiểu rằng SQL Inject có thể xuất hiện ngay cả khi bạn dùng PHP và database là MySQL, thậm chí với cả cơ sơ dữ liệu Oracle cũng có thể dính lỗi SQL Injection.
1. Không lầm tưởng về xác thực từ "client-side" là an toàn
Bắt đầu bằng cách hạn chế code server-side cho cáctrang Web ASP.NET. Không dựa vào xác thực client-side vì nó có thể dễ dàng bị bypass. Chỉ sử dụng xác thực client-side để cải thiện trải nghiệm người dùng.
Để làm điều này bạn có có thể lọc bỏ các ký tự lạ hoặc thay chúng bằng các ký tự hợp lệ trong truy vấn sql. ký tự đặc biệt với sql như dấu nháy đơn, dấu nháy đôi, NULL, % --, ... (',",%,\r,\n,\t) .
- Hết sức lưu ý với các biểu thức luôn đúng: " OR 1=1 OR " . Nếu không chú ý bạn có thể để hacker show toàn bộ dữ liệu của bạn
ví dụ câu sql của bạn lấy thông tin về chính 1 user: select * from Users where uid='abc' , câu này show chỉ lấy được 1 bản ghi của đúng user đó nhưng hacker có thể tìm cách add thêm select * from Users where uid='abc' OR 1=1 , hiển nhiên kết quả trả về là toàn bộ các bản ghi.
- Các ký tự comment " --", "\xbf"
Giả sử nếu code trước đó, giá trị SSN được nắm bởi control ASP.NET TextBox, bạn có thể hạn chế đầu vào của nó bằng cách sử dụng control RegularExpressionValidator control như dưới đây:
Nếu đầu vào SSN là từ một nguồn khác, chẳng hạn như control HTML, một tham số chuỗi truy vấn hoặc một cookie, bạn có thể hạn chế đầu vào bằng cách sử dụng lớp Regex từ namespace System.Text.RegularExpressions. Giả sử đầu vào nhận được từ một cookie.
Sử dụng System.Text.RegularExpressions:
if (Regex.IsMatch(Request.Cookies["SSN"], "^\d{3}-\d{2}-\d{4}$"))
{
// access the databases
}
else
{
// handle the bad inputs
}
2. Kiểm tra đầu vào của code ở tầng truy cập dữ liệu.
Trong một số trường hợp tương tự, ngoài việc xác thực cấp độ trang ASP.NET, bạn cũng cần cung cấp xác nhận hợp lệ trong mã truy cập dữ liệu của mình. 2 trường hợp phổ biến mà bạn cần cung cấp xác nhận hợp lệ trong mã truy cập dữ liệu của mình:
- Client không tin cậy: Nếu dữ liệu lấy từ một nguồn không đáng tin cậy hoặc bạn không thể đảm bảo dữ liệu đã được xác thực và hạn chế, thêm xác thực logic để hạn chế đầu vào mã truy cập dữ liệu.
- Mã thư viện (library code): Nếu mã truy cập dữ liệu của bạn được đóng gói như một thư viện được thiết kế sử dụng cho nhiều ứng dụng, mã truy cập dữ liệu của bạn phải thực hiện xác nhận hợp lệ của chính nó, vì bạn không thể đưa ra giả thuyết an toàn về ứng dụng client.
Dưới đây là ví dụ về cách các đối tượng truy cập dữ liệu xác nhận hợp lệ các tham số đầu vào bằng cách sử dụng các biểu thức thông thường trước khi sử dụng các tham số trong lệnh SQL.
using System;
using System.Text.RegularExpressions;
public void CreateNewUserAccount(string name, string password)
{
// Check name contains only lower cases or upper case letters,
// the apostrophe, a dot, or white space. Also check it is
// between 1 and 40 character long
if ( !Regex.IsMatch(userIDTxt.Text, @"^[a-zA-Z'./s]{1,40}$"))
throw new FormatException("Invalid name format");
if ( !Regex.IsMatch(passwordTxt.Text,
@"^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$" ))
throw new FormatException("Invalid password format");
}
Đoạn mã dưới đây hiển thị cách sử dụng SqlParameterCollection khi gọi Stored Procedure:
using System.Data;
using System.Data.SqlClient;
using (SqlConnection connection = new SqlConnection(connectionString))
{
DataSet userDataset = new DataSet();
SqlDataAdapter myCommand = new SqlDataAdapter(
"LoginStoredProcedure", connection);
myCommand.SelectCommand.CommandType = CommandType.StoredProcedure;
myCommand.SelectCommand.Parameters.Add("@au_id", SqlDbType.VarChar, 11);
myCommand.SelectCommand.Parameters["@au_id"].Value = SSN.Text;
myCommand.Fill(userDataset);
}
Trong trường hợp này, tham số @au_id được coi như một literal value chứ không phải là mã thực thi. Ngoài ra tham số được kiểm tra về loại và độ dài. Trong đoạn mã trước, giá trị đầu vào không được dài hơn 11 ký tự. Nếu dữ liệu không phù hợp với loại hoặc độ dài được xác định bởi tham số, lớp SqlParameter sẽ bỏ ngoại lệ.
Sử dụng tham số Batch
Một quan niệm sai lầm đó là nếu bạn nối một vài câu lệnh SQL để gửi batch xử lý hàng loạt các các câu lệnh đến máy chủ trong một quy trình, bạn không thể sử dụng tham số.
Tuy nhiên bạn có thể sử dụng kỹ thuật này nếu chắc chắn tên tham số không được lặp lại. Bạn có thể dễ dàng làm được điều này bằng cách chắc chắn rằng chỉ sử dụng các tên tham số duy nhất trong SQL, như ở dưới đây:
using System.Data;
using System.Data.SqlClient;
. . .
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlDataAdapter dataAdapter = new SqlDataAdapter(
"SELECT CustomerID INTO #Temp1 FROM Customers " +
"WHERE CustomerID > @custIDParm; SELECT CompanyName FROM Customers " +
"WHERE Country = @countryParm and CustomerID IN " +
"(SELECT CustomerID FROM #Temp1);",
connection);
SqlParameter custIDParm = dataAdapter.SelectCommand.Parameters.Add(
"@custIDParm", SqlDbType.NChar, 5);
custIDParm.Value = customerID.Text;
SqlParameter countryParm = dataAdapter.SelectCommand.Parameters.Add(
"@countryParm", SqlDbType.NVarChar, 15);
countryParm.Value = country.Text;
connection.Open();
DataSet dataSet = new DataSet();
dataAdapter.Fill(dataSet);
}
Phần hướng dẫn trên Taimienphi.vn vừa hướng dẫn bạn cách chặn SQL injection tấn công ASP.NET. Tốt nhất bạn nên xác nhận tất cả đầu vào ứng dụng ASP.NET để chặn SQL injection tấn công ASP.NET.
Thêm một vài nguyên tắc về bảo mật SQL:
- Disable user sa: User sa mặc định thường có rất nhiều đặc quyền mặc định rất cao khiến hacker có thể can thiệp vào hệ điều, vì vậy hãy disable chúng.
- Sử dụng user với quyền vừa đủ, phù hợp: Thay vì một user được truy cập tất cả các database, mỗi database sử dụng một user với quyền chỉ được phép truy cập database đó, thậm chí bạn cần tạo các user mới chỉ được phép truy cập tối thiểu đến các Table, Store Procedure, View...
- Mã hóa chuỗi kết nối tới cơ sở dữ liệu, điều này hữu ích khi bạn vô tình bị lộ file .config.
- Thiết lập tường lửa trên cổng dành cho SQL với Microsoft SQL thường là 1433, với MySQL port là 3306
Hiện nay cũng đang có thông tin Microsoft giới thiệu công cụ Security Risk Detection dựa trên AI nhằm phát hiện sớm các lỗ hổng bảo mật trên máy tính, nhằm bảo vệ dữ liệu tốt hơn, chúng ta sẽ cùng chờ đợi và trải nghiệm công cụ Security Risk Detection từ Microsoft trong thời gian sớm nhất.
Trong thời gian chờ đợi sự che chở từ Microsoft có thể sẽ diễn ra, bạn có thể tìm hiểu về Oracle cũng là một cơ sở dữ liệu khá nổi tiếng và được ưa chuộng dùng trong các hệ thống cần sự tin cậy lớn như viễn thông, ngân hàng, khối chính phủ... So sánh SQL Server và Oracle