SQL Injection là gì? Làm thế nào để phòng chống SQL Injection
Thịnh Văn Hạnh
09/03/2026
2074 Lượt xem
Chia sẻ bài viết
SQL Injection là một kỹ thuật tấn công thông qua việc chèn các câu lệnh SQL bất hợp pháp vào các truy vấn SQL được tạo bởi ứng dụng web. Điều này sẽ gây ra cản trở với việc truy cập web bình thường, không những thế bạn còn có nguy cơ bị đánh cắp dữ liệu cho các mục đích xấu. Cùng BKNS tìm hiểu SQL Injection là gì, các cách phòng chống SQL Injection qua bài viết này nhé.

Tóm Tắt Bài Viết
- SQL Injection là gì?
- Các loại SQL Injection
- Ví dụ về cách sử dụng SQL Injection
- Cách ngăn chặn SQL Injection
- Giải pháp phòng chống SQL Injection
- Cách kiểm tra Website có bị lỗi SQL Injection hay không?
- Kết luận
SQL Injection là gì?
SQL Injection (SQLi) là một dạng lỗ hổng bảo mật phổ biến trên các ứng dụng web. Lỗ hổng này cho phép kẻ tấn công chèn hoặc thao túng các câu lệnh SQL mà hệ thống sử dụng để truy vấn cơ sở dữ liệu. Khi khai thác thành công, kẻ tấn công có thể truy cập vào những dữ liệu mà bình thường họ không có quyền xem.
Các dữ liệu bị lộ có thể bao gồm thông tin của người dùng khác, dữ liệu hệ thống hoặc bất kỳ thông tin nào mà ứng dụng web có quyền truy cập. Không chỉ dừng lại ở việc xem dữ liệu, trong nhiều trường hợp kẻ tấn công còn có thể chỉnh sửa, thêm mới hoặc xóa dữ liệu trong cơ sở dữ liệu. Điều này có thể gây ra những thay đổi nghiêm trọng và lâu dài đối với nội dung cũng như hoạt động của ứng dụng.
Nguy hiểm hơn, một số cuộc tấn công SQL Injection còn có thể được khai thác sâu hơn để xâm nhập vào máy chủ hoặc các hệ thống backend liên quan. Khi đó, kẻ tấn công có thể kiểm soát hệ thống, đánh cắp dữ liệu lớn hoặc thậm chí thực hiện các cuộc tấn công từ chối dịch vụ (DoS) nhằm làm gián đoạn hoạt động của website hoặc dịch vụ trực tuyến.
Các loại SQL Injection
Để phòng chống hiệu quả một cuộc tấn công, bạn cần phải hiểu rõ “vũ khí” mà kẻ gian đang sử dụng. Trong thế giới bảo mật ứng dụng web, SQL Injection (SQLi) không chỉ có một hình hài duy nhất. Tùy thuộc vào cách ứng dụng web phản hồi và cấu hình máy chủ cơ sở dữ liệu, các hacker sẽ lựa chọn những phương thức tiếp cận khác nhau.
Dưới đây là bức tranh toàn cảnh và chuyên sâu về 3 nhóm tấn công SQL Injection phổ biến nhất mà bất kỳ chuyên gia bảo mật hay lập trình viên nào cũng cần nắm vững.
1. In-band SQLi (Classic SQLi): Tấn công trực tiếp và nhận kết quả ngay
In-band SQLi là hình thức tấn công phổ biến nhất và cũng dễ thực hiện nhất. Đặc điểm nhận diện của phương pháp này là hacker sử dụng cùng một kênh giao tiếp (thường là trình duyệt web) để vừa gửi đi mã độc (payload), vừa trực tiếp thu thập kết quả trả về.
Vì mọi thứ diễn ra “ngay trước mắt”, kẻ tấn công có thể nhanh chóng trích xuất toàn bộ dữ liệu một cách dễ dàng. In-band SQLi được chia thành hai kỹ thuật chính:
Error-based SQLi (Dựa trên thông báo lỗi)
Kỹ thuật này hoạt động bằng cách cố tình chèn các ký tự đặc biệt hoặc cú pháp sai để ép cơ sở dữ liệu (Database) phải trả về một thông báo lỗi.
- Mục đích: Các thông báo lỗi này thường chứa những thông tin “vàng” đối với hacker, chẳng hạn như tên hệ quản trị cơ sở dữ liệu (MySQL, SQL Server, Oracle…), cấu trúc bảng, hoặc tên cột.
- Tại sao nguy hiểm? Mặc dù không trực tiếp làm rò rỉ dữ liệu người dùng, nhưng Error-based SQLi cung cấp cho kẻ tấn công bản đồ chi tiết về hệ thống của bạn, tạo tiền đề để chúng tung ra các đòn tấn công chính xác hơn ở giai đoạn sau.
Union-based SQLi (Dựa trên toán tử UNION)
Đây là kỹ thuật trích xuất dữ liệu trực tiếp và nguy hiểm nhất trong nhóm In-band. Hacker sẽ sử dụng toán tử UNION trong ngôn ngữ SQL để gộp kết quả của một truy vấn hợp lệ với kết quả của một truy vấn độc hại.
- Cách thức hoạt động: Nếu một trang web hiển thị thông tin sản phẩm dựa trên ID, hacker có thể nối thêm lệnh truy vấn bảng mật khẩu người dùng. Kết quả là mật khẩu sẽ được hiển thị ngay trên giao diện trang web, lẫn vào vị trí lẽ ra dành cho thông tin sản phẩm.
- Điều kiện: Kẻ tấn công phải đoán đúng số lượng cột và kiểu dữ liệu của truy vấn gốc thì lệnh UNION mới có thể thực thi thành công.
Inferential SQLi (Blind SQLi): Tấn công “mù”
Trái ngược với In-band, Blind SQLi (hay còn gọi là Inferential SQLi) xảy ra khi ứng dụng web đã được cấu hình để ẩn đi các thông báo lỗi hoặc không hiển thị trực tiếp dữ liệu ra màn hình. Tuy nhiên, hacker vẫn có thể đánh cắp dữ liệu bằng cách đặt ra các câu hỏi dạng Đúng/Sai (True/False) và quan sát cách hệ thống phản hồi.
Vì không nhìn thấy trực tiếp kết quả (mù), quá trình này diễn ra chậm hơn, phải đoán từng ký tự một, nhưng mức độ tàn phá thì không hề thua kém.
Boolean-based Blind SQLi (Dựa trên nội dung phản hồi)
Kẻ tấn công gửi các truy vấn SQL buộc cơ sở dữ liệu phải đánh giá một điều kiện là Đúng hoặc Sai. Dựa trên kết quả này, nội dung của trang web (HTTP response) sẽ có sự thay đổi.
- Ví dụ thực tế: Hacker chèn một lệnh kiểm tra xem ký tự đầu tiên của mật khẩu Admin có phải là chữ ‘A’ hay không. Nếu trang web tải ra đầy đủ hình ảnh sản phẩm như bình thường $\rightarrow$ Điều kiện Đúng. Nếu trang web bị thiếu một phần tử nào đó hoặc báo lỗi “Không tìm thấy” $\rightarrow$ Điều kiện Sai. Cứ thế, chúng dò dẫm từng ký tự cho đến khi ghép được toàn bộ chuỗi dữ liệu.
Time-based Blind SQLi (Dựa trên độ trễ thời gian)
Khi ứng dụng web luôn trả về một giao diện giống hệt nhau dù điều kiện đúng hay sai (vô hiệu hóa hoàn toàn Boolean-based), hacker sẽ chuyển sang dùng thời gian làm thước đo.
- Cách thức hoạt động: Chúng tiêm các lệnh yêu cầu hệ thống phải “ngủ” (ví dụ: SLEEP(10) trong MySQL hoặc WAITFOR DELAY ‘0:0:10’ trong SQL Server) nếu một điều kiện là Đúng.
- Nhận biết: Nếu hacker hỏi “Bảng Users có tồn tại không?” kèm theo lệnh chờ 10 giây. Nếu trang web mất đúng 10 giây mới tải xong $\rightarrow$ Câu trả lời là Có. Kỹ thuật này đòi hỏi sự kiên nhẫn cực lớn hoặc các công cụ tự động hóa mạnh mẽ, nhưng nó chứng minh rằng việc che giấu thông báo lỗi là chưa đủ để ngăn chặn SQL Injection.

Out-of-band SQLi
Out-of-band (OOB) SQLi là một dạng tấn công hiếm gặp hơn, tinh vi hơn và thường được sử dụng khi cả phương pháp In-band và Inferential đều thất bại (ví dụ: truy vấn phản hồi quá chậm hoặc máy chủ bị chặn đầu ra nghiêm ngặt).
Khác với việc nhận dữ liệu qua chính trang web, hacker cấu hình sao cho máy chủ cơ sở dữ liệu phải tự động mở một kết nối mới gửi dữ liệu ra máy chủ bên ngoài do chúng kiểm soát.
- Cơ chế thực thi: Dạng tấn công này lợi dụng khả năng kích hoạt các yêu cầu mạng (như truy vấn DNS hoặc giao thức HTTP) vốn được tích hợp sẵn trong một số hệ quản trị CSDL. Ví dụ, hàm xp_cmdshell trong Microsoft SQL Server hoặc các package mạng trong Oracle.
- Kịch bản tấn công: Kẻ tấn công tiêm mã độc yêu cầu Database tự động tra cứu một tên miền (DNS Lookup). Tên miền này chứa luôn cả phần dữ liệu cần đánh cắp (ví dụ: mat-khau-admin.hacker-server.com). Bằng cách kiểm tra nhật ký truy cập (log) trên máy chủ DNS của mình, hacker sẽ dễ dàng đọc được dữ liệu mà không cần trang web phải hiển thị bất cứ thứ gì.
Ví dụ về cách sử dụng SQL Injection
Kẻ tấn công muốn thực hiện SQL injection sẽ thao túng một truy vấn SQL tiêu chuẩn, để khai thác các lỗ hổng input không được xác thực trong Cơ sở dữ liệu. Có nhiều cách để thực hiện vector tấn công này. Sau đây là một số cách để vận hành SQLi:
Lấy ví dụ về input ở trên. Nó sẽ lấy thông tin cho một sản phẩm cụ thể, có thể được đổi thành
http://www.estore.com/items/items.asp?itemid=999 or 1=1
Và truy vấn SQL sẽ có dạng như sau:

Vì lệnh 1=1 là luôn đúng, nên truy vấn trả về tất cả tên và mô tả sản phẩm trong Cơ sở dữ liệu, ngay cả những tên mà bạn không đủ điều kiện truy cập.
Những hacker cũng có thể lợi dụng các ký tự được lọc không chính xác để thay đổi các lệnh SQL. Trong đó gồm cả việc sử dụng dấu chấm phẩy để tách hai trường.
Ví dụ, có input:
http://www.estore.com/items/iteams.asp?itemid=999; DROP TABLE USERS
Người dùng sẽ tạo truy vấn SQL như sau:

Lúc đó, toàn bộ Cơ sở dữ liệu có thể bị xóa.
Một cách khác để thao túng truy vấn SQL là sử dụng lệnh UNION SELECT. Nó kết hợp hai truy vấn SELECT không liên quan để lấy dữ liệu từ các bảng Cơ sở dữ liệu khác nhau.
Ví dụ, có input:
http://www.estore.com/items/items.asp?itemid=999 UNION SELECT user-name, password FROM USERS
Input này sẽ tạo truy vấn SQL sau:

Bằng cách sử dụng lệnh UNION SELECT, truy vấn này kết hợp request cho tên và mô tả mục item 999 với một request khác, pull tên và password cho mọi người dùng trong Cơ sở dữ liệu.
Cách ngăn chặn SQL Injection
Chúng ta cần biết được cách phòng chống SQL injection hiệu quả. Vì SQL Injection có vector chính là các kênh input của người dùng. Nên cách tiếp cận tốt nhất là kiểm soát và xem xét input của người dùng để theo dõi các kiểu tấn công. Các developer cũng có thể tránh các lỗ hổng bảo mật bằng cách áp dụng các cách phòng chống SQL injection sau:
Input Validation (Xác thực đầu vào)
Quá trình xác thực nhằm xác minh xem loại input do người dùng gửi có hợp lệ hay không. Xác thực đầu vào đảm bảo đó là kiểu, độ dài, định dạng… được chấp nhận. Chỉ các giá trị qua được xác thực mới có thể được xử lý. Nó giúp chống lại mọi lệnh được chèn vào trong chuỗi input.
Xác thực nên được áp dụng với các trường cho phép người dùng nhập đầu vào, mà bạn còn nên quan tâm đến các tình huống sau:
- Sử dụng biểu thức chính quy làm whitelist cho các dữ liệu có cấu trúc (chẳng hạn như tên, tuổi, thu nhập, zip code) để đảm bảo xác thực đầu vào hợp lệ.
- Trong trường hợp có một bộ giá trị cố định (như drop-down list), hãy xác định giá trị được trả về. Dữ liệu đầu vào phải khớp với một trong các tùy chọn được cung cấp.
Dưới đây là cách xác thực tên bảng:
switswitch ($tableName) {
case 'fooTable': return true;
case 'barTable': return true;
default: return new BadMessageException('unexpected value provided as table name');
}
Biến $tableName có thể được append trực tiếp, bây giờ nó được biết đến là một trong những giá trị hợp pháp cho tên của Table.
Đối với drop-down list, việc xác thực dữ liệu rất đơn giản. Giả sử bạn muốn người dùng chọn xếp hạng từ 1 đến 5, hãy đổi PHP code thành:
<?php
if(isset($_POST["selRating"]))
{
$number = $_POST["selRating"];
if((is_numeric($number)) && ($number > 0) && ($number < 6))
{
echo "Selected rating: " . $number;
}
else
echo "The rating has to be a number between 1 and 5!";
}
Bạn đã thêm hai check đơn giản:
- Phải là một số (hàm is_numeric())
- $number phải lớn hơn 0, nhỏ hơn 6. Do đó điểm có phạm vi từ 1 – 5.
Dữ liệu nhận được từ bên ngoài phải được xác thực. Quy tắc này không chỉ áp dụng cho input do người dùng Internet cung cấp, mà còn cho các nhà cung cấp, đối tác, cơ quan quản lý.
Parametrized queries (Tham số hóa truy vấn)
Các truy vấn tham số hóa là một phương tiện pre-compile lệnh SQL. Sau đó bạn có thể cung cấp các tham số để câu lệnh được thực thi.
Phương pháp này giúp Cơ sở dữ liệu có thể nhận ra mã và phân biệt nó với dữ liệu đầu vào.
Input của người dùng được trích dẫn tự động, và kiểu mã hóa này giúp giảm thiểu tấn công SQL injection.
Ta cũng có thể sử dụng các truy vấn tham số hóa với phần mở rộng MySQLi, nhưng PHP 5.1 đã trình bày một cách tiếp cận tốt hơn khi làm việc với CSDL: PHP Data Objects (PDO). PDO áp dụng các phương pháp đơn giản hóa việc sử dụng các truy vấn tham số hóa. Ngoài ra, nó làm cho code dễ đọc hơn và dễ di chuyển hơn, vì nó còn hoạt động trên một số Cơ sở dữ liệu khác, không chỉ mỗi MySQL.
Code này sử dụng PDO với các truy vấn được tham số hóa để ngăn chặn lỗ hổng SQL injection:
<?php
$id = $_GET['id'];
$db_connection = new PDO('mysql:host=localhost;dbname=sql_injection_example', 'dbuser', 'dbpasswd');
//preparing the query
$sql = "SELECT username
FROM users
WHERE id = :id";
$query = $db_connection->prepare($sql);
$query->bindParam(':id', $id);
$query->execute();
//getting the result
$query->setFetchMode(PDO::FETCH_ASSOC);
$result = $query->fetchColumn();
print(htmlentities($result));
Stored Procedures
Các stored procedures (SP) yêu cầu developer nhóm một hay nhiều lệnh SQL thành một đơn vị logic để có thể tạo một kế hoạch thực thi. Các lần thực thi tiếp theo cho phép các lệnh được tham số hóa tự động. Nói một cách đơn giản, nó là một loại code có thể được lưu trữ để sử dụng sau này.
Vì vậy, bất cứ khi nào bạn cần thực hiện truy vấn, thay vì viết đi viết lại thì có thể gọi một stored procedure.
Đây là một quá trình tạo một SP trong server MySQL. Ví dụ bạn có một bảng như sau:
CREATE TABLE `salary` (
`empid` int(11) NOT NULL,
`sal` int(11) DEFAULT NULL,
PRIMARY KEY (`empid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Giả sử có một nhân viên cần lấy dữ liệu tổng hợp về lương công ty từ Table đó. Trước tiên, bạn cần tạo một người dùng ‘tr’:
CREATE USER 'tr'@'localhost' IDENTIFIED BY 'mypass';
Người dùng đó sẽ chỉ cần quyền EXECUTE đối với lược đồ nơi có Table:
grant execute on hris.* to tr@`%`
SP sẽ được tạo như sau:
DELIMITER $$
CREATE PROCEDURE `avg_sal`(out avg_sal decimal)
BEGIN
select avg(sal) into avg_sal from salary;
END
Quá trình phát hành lệnh tạo một avg_sal SP và nó sẽ được lưu trữ trong Cơ sở dữ liệu.
Để gọi một SP từ một ừng dụng PHP, bạn có thể sử dụng PDO:
$db_connection = new PDO('mysql:host=localhost;dbname=hris', 'tr', 'mypass');
$query = $db_connection->exec('call avg_sal(@out)');
$res = $query->query('select @out')->fetchAll();
print_r($res);
$res sẽ hiện thị mức lương trung bình theo yêu cầu người dùng. Sau đó, người dùng có thể thực hiện quá trình output với PHP.

Sử dụng Escaping
Luôn sử dụng các hàm character-escaping cho input do user cung cấp, được cấp bởi mỗi hệ thống quản lý Cơ sở dữ liệu (DBMS). Việc này giúp đảm bảo DBMS không bao giờ nhầm lẫn nó với lệnh SQL do developer cung cấp.
Ví dụ: dùng mysql_real_escape_string() trong PHP để tránh các ký tự có thể dẫn đến lệnh SQL không mong muốn. Một phiên sửa đổi cho login bypass sẽ như sau:
$db_connection = mysqli_connect("localhost", "user", "password", "db");
$username = mysqli_real_escape_string($db_connection, $_POST['username']);
$password = mysqli_real_escape_string($db_connection, $_POST['password']);
$query = "SELECT * FROM users WHERE username = '" . $username. "' AND password = '" . $password . "'";
Trước đây, code của bạn có thể dễ bị thêm escape character (\) ở phía trước dấu ngoặc. Tuy nhiên, bằng mã trên bạn sẽ được bảo vệ khỏi người dùng bất hợp pháp và giảm thiểu SQL injection.
Giải pháp phòng chống SQL Injection
Nếu ví cơ sở dữ liệu (Database) như “trái tim” lưu trữ mọi tài sản quý giá nhất của doanh nghiệp, thì SQL Injection chính là mũi dao nhắm thẳng vào đó. Để bảo vệ hệ thống trước những đòn tấn công tinh vi đã được phân tích, chúng ta không thể chỉ hy vọng hacker sẽ bỏ qua ứng dụng của mình. Thay vào đó, bạn cần thiết lập một hệ thống phòng thủ đa lớp (Defense in Depth).
Dưới đây là 4 giải pháp cốt lõi và mang tính sống còn để triệt tiêu hoàn toàn rủi ro từ SQL Injection.
1. Sử dụng Prepared Statements (Parameterized Queries)
Nếu bạn chỉ có thể chọn một biện pháp duy nhất để chống lại SQL Injection, thì đó bắt buộc phải là Prepared Statements (hay Truy vấn có tham số). Đây được giới bảo mật công nhận là phương pháp hiệu quả nhất, giải quyết tận gốc rễ của vấn đề.
Tại sao Prepared Statements lại mạnh mẽ đến vậy? Lỗ hổng SQLi xảy ra vì cơ sở dữ liệu bị nhầm lẫn giữa mã lệnh (cấu trúc SQL) và dữ liệu người dùng nhập vào. Prepared Statements loại bỏ hoàn toàn sự nhầm lẫn này bằng cách tách biệt quá trình xử lý:
- Ứng dụng gửi trước cấu trúc câu lệnh SQL lên Database (để biên dịch).
- Dữ liệu người dùng nhập vào sẽ được gửi lên sau và được Database đối xử nghiêm ngặt như một chuỗi giá trị (data), tuyệt đối không được thực thi như một phần của câu lệnh.
Dù hacker có nhập vào ‘ OR 1=1 —, cơ sở dữ liệu sẽ chỉ đi tìm một người dùng có tên đăng nhập chính xác là chuỗi ký tự đó, chứ không hề kích hoạt logic OR 1=1.
Ví dụ thực tế bằng PHP (PDO):
PHP
// CÁCH LÀM SAI (Dễ bị SQLi): Nối chuỗi trực tiếp
// $sql = “SELECT * FROM users WHERE username = ‘” . $_POST[‘username’] . “‘”;
// CÁCH LÀM CHUẨN (An toàn tuyệt đối): Sử dụng Prepared Statements
$username = $_POST[‘username’];
$password = $_POST[‘password’];
// 1. Chuẩn bị câu lệnh với các tham số ẩn danh (?) hoặc có tên (:username)
$stmt = $pdo->prepare(‘SELECT * FROM users WHERE username = :username AND password = :password’);
// 2. Gắn giá trị (Bind parameters) và thực thi
$stmt->execute([
‘username’ => $username,
‘password’ => $password
]);
$user = $stmt->fetch();
2. Input Validation & Sanitization: Kiểm duyệt khắt khe từ “cửa ngõ”
Mặc dù Prepared Statements rất mạnh, nhưng nguyên tắc vàng trong bảo mật là “Không bao giờ tin tưởng dữ liệu đầu vào” (Never trust user input). Bạn cần làm sạch và kiểm duyệt mọi dữ liệu trước khi cho phép chúng tiến sâu vào hệ thống.
- Input Validation (Xác thực dữ liệu): Đảm bảo dữ liệu nhập vào đúng định dạng mong muốn. Hãy ưu tiên sử dụng Whitelist (Danh sách trắng) thay vì Blacklist (Danh sách đen).
- Ví dụ: Nếu trường nhập liệu là Tuổi, nó bắt buộc phải là số nguyên (Integer). Nếu là Email, nó phải khớp với định dạng chuẩn của Email. Mọi dữ liệu sai định dạng đều bị từ chối ngay lập tức.
- Sanitization (Làm sạch dữ liệu): Nếu bạn không thể dùng Prepared Statements (trong một số trường hợp legacy code quá cũ), bạn buộc phải lọc bỏ hoặc vô hiệu hóa (escape) các ký tự nguy hiểm có ý nghĩa đặc biệt trong SQL như dấu nháy đơn (‘), dấu chấm phẩy (;), hoặc dấu gạch ngang (—).
Lưu ý: Sanitization chỉ là biện pháp hỗ trợ, không thể thay thế được Prepared Statements trong việc chống SQLi.
3. Nguyên tắc “Đặc quyền tối thiểu” (Least Privilege): Giới hạn rủi ro khi vỡ trận
Hãy tưởng tượng, nếu một nhân viên giao hàng chỉ cần bước vào phòng khách, bạn không có lý do gì để giao cho họ chìa khóa của phòng ngủ hay két sắt. Cơ sở dữ liệu cũng hoạt động theo logic tương tự.
Nguyên tắc Đặc quyền tối thiểu yêu cầu bạn cấp cho tài khoản kết nối Database (Database User) quyền hạn thấp nhất vừa đủ để ứng dụng hoạt động.
- Tuyệt đối không sử dụng tài khoản root, sa, hoặc admin để kết nối ứng dụng web với Database.
- Phân quyền chi tiết: Nếu trang web chỉ có chức năng hiển thị tin tức, tài khoản Database kết nối ứng dụng chỉ được phép sử dụng lệnh SELECT. Không được cấp quyền INSERT, UPDATE, DELETE, và càng không được quyền DROP TABLE (xóa bảng).
- Lợi ích: Kể cả khi hacker tìm ra một lỗ hổng SQLi cực kỳ tinh vi để vượt qua các lớp trên, thiệt hại cũng được khoanh vùng ở mức tối thiểu. Chúng không thể phá hủy toàn bộ dữ liệu hay chiếm quyền điều khiển hệ thống máy chủ.
4. Sử dụng WAF (Web Application Firewall): Tấm khiên thép bảo vệ vòng ngoài
Để xây dựng một hệ thống phòng thủ hoàn hảo, bạn cần một lính canh thường trực ở lớp mạng – đó chính là Tường lửa Ứng dụng Web (WAF).
WAF đứng giữa người dùng và máy chủ web, đóng vai trò như một bộ lọc thông minh:
- Nhận diện mẫu tấn công (Signature-based): WAF chứa sẵn một cơ sở dữ liệu khổng lồ về các đoạn mã độc (payload) SQLi phổ biến. Khi phát hiện một HTTP Request chứa dấu hiệu như UNION SELECT hoặc 1=1, WAF sẽ lập tức chặn đứng yêu cầu đó trước khi nó kịp chạm đến Server của bạn.
- Phân tích hành vi bất thường: Các WAF hiện đại còn có thể học hỏi lưu lượng truy cập bình thường và chặn các hành vi gửi yêu cầu bất thường.
- Giải pháp cứu cánh: Trong trường hợp ứng dụng của bạn dính lỗ hổng Zero-day hoặc bạn chưa có thời gian để vá lại toàn bộ mã nguồn cũ, WAF chính là “miếng băng gạc” hoàn hảo để cầm máu và bảo vệ hệ thống tức thời.
Cách kiểm tra Website có bị lỗi SQL Injection hay không?
Hiểu được sự nguy hiểm của SQL Injection là chưa đủ. Giống như việc bạn biết có trộm ngoài kia, bước tiếp theo bạn phải làm là đi vòng quanh nhà và kiểm tra xem có cánh cửa nào đang quên khóa hay không.
Đối với website, việc rà soát lỗ hổng SQL Injection có thể được thực hiện từ những dấu hiệu cơ bản nhất cho đến việc sử dụng các công cụ rà quét chuyên sâu. Dưới đây là cách để bạn “khám bệnh” cho hệ thống của mình.
Dấu hiệu nhận biết: Khi Website vô tình “lên tiếng”
Đôi khi, hệ thống của bạn sẽ tự “tố cáo” lỗ hổng của chính nó nếu bạn biết cách thử nghiệm. Một trong những phương pháp kiểm tra thủ công (Manual Testing) phổ biến nhất là cố tình nhập các ký tự đặc biệt (như ‘, “, ;, hoặc \) vào thanh tìm kiếm, URL (ví dụ: id=1′) hoặc các ô đăng nhập.
Nếu website của bạn mắc lỗi, nó sẽ bộc lộ hai triệu chứng cực kỳ rõ ràng sau:
- Các thông báo lỗi SQL lạ (Verbose Error Messages): Đây là dấu hiệu “chết người” nhất. Thay vì hiện ra trang lỗi 404 hoặc thông báo “Không tìm thấy nội dung” thân thiện, website lại trả về một dòng code dài ngoằng với những nội dung như: “You have an error in your SQL syntax”, “Warning: mysql_fetch_array()” hoặc “Unclosed quotation mark”. Điều này chứng tỏ ký tự đặc biệt bạn nhập vào đã đi thẳng xuống Database và phá vỡ cấu trúc câu lệnh gốc. Đối với Hacker, những thông báo lỗi này chính là “bản đồ kho báu” tiết lộ chính xác loại cơ sở dữ liệu bạn đang dùng (MySQL, SQL Server hay Oracle) để chúng điều chỉnh mã độc cho phù hợp.
- Dữ liệu hiển thị không đúng logic (Blind SQL Injection): Trong nhiều trường hợp, lập trình viên đã tắt tính năng hiển thị lỗi. Tuy nhiên, bạn vẫn có thể nhận ra bất thường khi dữ liệu hiển thị hoàn toàn sai lệch. Ví dụ: một bài viết tự nhiên biến mất, giao diện bị vỡ, website trả về trang trắng (Blank Page), hoặc trang load chậm một cách bất thường (mất đến 10-15 giây) khi bạn chèn thêm một câu lệnh bắt Database phải “chờ” (Time-based SQLi).
Công cụ hỗ trợ: “Vũ khí” rà quét chuyên sâu (Dành cho Dev / Pentester)
Việc kiểm tra thủ công bằng tay chỉ giúp bạn phát hiện những lỗ hổng bề nổi. Để chắc chắn 100% hệ thống “sạch bóng” SQL Injection, các Chuyên gia bảo mật (Pentester) và Lập trình viên (Dev) bắt buộc phải nhờ đến các công cụ chuyên dụng.
- SQLMap – Công cụ tự động hóa “hủy diệt” nhất: Trong giới bảo mật, SQLMap được xem là “vũ khí hạng nặng”. Đây là một công cụ mã nguồn mở hoàn toàn tự động, có khả năng tự điền hàng ngàn mẫu mã độc (payloads) khác nhau vào các lỗ hổng trên website với tốc độ chóng mặt. SQLMap không chỉ giúp phát hiện lỗi mà còn cho phép Pentester thử nghiệm mức độ nghiêm trọng bằng cách: mô phỏng việc trút tải dữ liệu (dump data), truy cập hệ thống tệp tin, hay thậm chí chiếm quyền điều khiển máy chủ. Nếu SQLMap có thể khai thác được website của bạn, hacker cũng vậy.
- Burp Suite – “Trạm kiểm soát” chặn bắt và sửa đổi Request: Nếu SQLMap là cỗ máy tự động thì Burp Suite lại là công cụ phẫu thuật tinh vi dành cho chuyên gia. Burp Suite hoạt động như một “người đứng giữa” (Proxy) chèn ép giữa trình duyệt của người dùng và máy chủ website. Nhờ đó, Pentester có thể chặn đứng một thao tác gửi dữ liệu (ví dụ: bấm nút Đăng nhập), từ từ mổ xẻ, chèn thêm các đoạn mã SQL Injection hiểm hóc vào những trường dữ liệu ẩn mà mắt thường không thấy được, sau đó mới gửi đi và phân tích cách máy chủ phản hồi.
- Các Plugin bảo mật (Dành cho nền tảng như WordPress): Nếu bạn không phải là một Dev chuyên nghiệp nhưng đang quản trị một website WordPress, bạn vẫn có thể tự bảo vệ mình một cách thụ động. Hãy cài đặt ngay các Plugin bảo mật uy tín như Wordfence hay Sucuri. Chúng hoạt động như một Tường lửa ứng dụng web (WAF – Web Application Firewall), liên tục giám sát lưu lượng truy cập, tự động nhận diện các mẫu mã độc SQLi quen thuộc từ hacker và chặn đứng chúng trước khi chúng kịp chạm tới Database của bạn.
Kết luận
Trên đây là những gì BKNS chia sẻ đến bạn về các loại SQL Injection và những cách phòng chống vấn đề này. Hy vọng qua bài viết này bạn sẽ học thêm được nhiều kiến thức mới và biết cách ngăn chặn SQL Injection hiệu quả.
Đọc thêm các bài viết hữu ích khác tại BKNS.
> Có thể bạn quan tâm:


































