Trang chủCông nghệSQL injection là gì? Cách phòng chống và ngăn chặn SQL injection

SQL injection là gì? Cách phòng chống và ngăn chặn SQL injection

Thứ Bảy, 5/18/2024, 4:38:02 PMlike 100
SQL injection là gì mà bất kỳ trang web nào cũng phải chú ý và tìm mọi cách để ngăn chặn? Hãy cùng Gofiber tìm hiểu chi tiết qua nội dung bài viết dưới đây!

SQL injection là một kỹ thuật tấn công nguy hiểm, nhưng lại cực kỳ phổ biến hiện nay. Với kỹ thuật này, kẻ tấn công có thể truy cập trái phép vào cơ sở dữ liệu, đánh cắp thông tin nhạy cảm, thực hiện các hành động gây hại khác như xóa dữ liệu, thực hiện các câu lệnh hệ thống độc hại… Vậy, SQL injection là gì? Làm cách nào để phòng chống và ngăn chặn SQL injection? Hãy cùng Gofiber tìm hiểu chi tiết qua bài viết được chia sẻ dưới đây!

SQL Injection là gì?

SQL injection là một kỹ thuật tấn công chèn mã code phổ biến trong lĩnh vực bảo mật web. Khi một trang web/ứng dụng web không kiểm tra hoặc xử lý đúng cách dữ liệu người dùng nhập vào, kẻ tấn công có thể chèn các đoạn mã SQL độc hại vào truy vấn SQL của trang web, ứng dụng đó. 

Thông thường, người dùng sẽ nhập dữ liệu vào hệ thống thông qua các biểu mẫu, tham số URL… Lúc này, nếu trang web hoặc ứng dụng đó có tồn tại lỗ hổng bảo mật, kẻ tấn công khai thác chúng và chèn các lệnh SQL độc hại vào entry field để thực thi (chẳng hạn như việc kết xuất nội dung database). Nói tóm lại, để thực hiện SQL Injection, kẻ tấn công buộc phải khai thác lỗ hổng bảo mật tồn tại trên ứng dụng, trang web. 

SQL Injection là gì?
SQL injection là một kỹ thuật tấn công chèn mã code phổ biến trong lĩnh vực bảo mật web

Trên thực tế, SQL Injection không chỉ là một vector tấn công được thực hiện trên các trang web, mà hình thức tấn công này còn có thể áp dụng cho bất kỳ loại database SQL nào. Điều này đồng nghĩa với việc ngoài ứng dụng web, các ứng dụng di động, ứng dụng desktop hay bất kỳ hệ thống nào sử dụng database SQL đều có thể trở thành nạn nhân của SQL Injection.

Thông qua các cuộc tấn công SQL Injection, hacker có thể giả mạo danh tính để xâm nhập vào hệ thống và gây xáo trộn dữ liệu. Không chỉ thế, hình thức này còn cho phép chúng vô hiệu hóa giao dịch, thay đổi số dư tài khoản, tiết lộ thông tin dữ liệu hay thậm chí là phá hủy dữ liệu trên toàn hệ thống. Nếu nghiêm trọng hơn, chúng còn có thể khiến cho dữ liệu trở nên không khả dụng và chiếm quyền admin của server database.

Để ngăn chặn SQL injection, nhà phát triển web cần phải thực hiện nhiều biện pháp bảo mật khác nhau và điều này sẽ được chia sẻ rõ hơn ở những nội dung tiếp theo của bài viết!

Các loại SQL Injection phổ biến hiện nay

Hiện nay, SQL Injection có 3 loại phổ biến nhất là In-band SQLi (Classic), Out-of-band SQLi và Inferential SQLi (Blind). Ngoài ra, bạn cũng có thể phân loại chúng dựa trên khả năng gây hại hoặc phương pháp truy cập dữ liệu backend. 

In-band SQLi

In-band SQL Injection là một trong các hình thức tấn công mạng phổ biến, trong đó hacker sử dụng cùng một kênh liên lạc để khởi động các cuộc tấn công và thu thập kết quả từ database. Trong số các loại, phương pháp này đơn giản và hiệu quả nhất, nên thường được sử dụng rộng rãi và phổ biến hàng đầu hiện nay. Dưới đây là 2 biến thể phụ của In-band SQL Injection:

  • Error-based SQL Injection: Trong loại tấn công này, kẻ tấn công sử dụng các thao tác gây lỗi trong cơ sở dữ liệu để thu thập thông tin. Khi thực hiện các câu lệnh SQL không hợp lệ hoặc không được xử lý đúng cách, cơ sở dữ liệu sẽ phản hồi bằng thông báo lỗi. Kẻ tấn công sẽ khai thác các thông báo lỗi này để lấy thông tin về cấu trúc của database.

  • Union-based SQL Injection: Loại tấn công này tận dụng toán tử UNION trong SQL để tổng hợp kết quả từ các câu lệnh SQL khác nhau và thu được một HTTP response chứa các dữ liệu mà tin tặc có thể sử dụng. Thông thường, chúng sẽ chèn các câu lệnh SQL phụ vào trong câu truy vấn ban đầu và sử dụng toán tử UNION để nhận về kết quả từ đó. 

Các loại SQL Injection phổ biến hiện nay

Các loại SQL Injection phổ biến hiện nay

Inferential (Blind) SQLi

Blind SQL Injection là một phương pháp tấn công SQL Injection mà trong đó tin tặc sẽ gửi các data payload đến máy chủ và theo dõi cách server phản hồi để tìm hiểu về cấu trúc của database. Phương pháp này được gọi là Bind (mù) vì hacker sẽ không nhận được dữ liệu trực tiếp từ database như trong In-band SQLi.

Hacker sẽ dựa trên hành vi và phản ứng của server để suy ra thông tin về database. Vậy nên các lệnh Blind SQL Injection sẽ được thực thi chậm hơn, nhưng chúng vẫn có thể có những tác động nghiêm trọng tương tự. Hiện nay, Blind SQL Injection được chia thành các loại sau: 

  • Boolean-based Blind SQL Injection: Trong loại tấn công này, kẻ tấn công gửi một truy vấn SQL đến database thông qua ứng dụng web. Kết quả của truy vấn sẽ dẫn đến một phản hồi trả về (ví dụ như một trang web có hiển thị hay không). Dựa trên sự khác nhau của kết quả (true/false), thông tin trong HTTP response sẽ thay đổi hoặc không. Kẻ tấn công sẽ sử dụng các kết quả này để suy ra thông tin về cấu trúc và dữ liệu trong database. 

  • Time-based Blind SQL Injection: Tương tự, kẻ tấn công sẽ gửi một truy vấn SQL đến database thông qua ứng dụng web và khiến cho database phải đợi một khoảng thời gian nhất định trước khi hoạt động. Sau đó, chúng xem xét thời gian mà database cần để phản hồi và xác định truy vấn đó là đúng hay sai. Dựa trên kết quả thu thập được, một HTTP response sẽ được tạo và kẻ tấn công có thể dựa vào các biểu hiện trên để suy đoán thông tin về database. 

Out-of-band SQLi

Out-of-band SQL Injection (OOB SQLi) là một phương thức tấn công SQL Injection mà kẻ tấn công sử dụng khi không thể trực tiếp thu thập dữ liệu từ database thông qua kênh thông thường như trong các kỹ thuật in-band SQLi hay inferential SQLi, chẳng hạn như khi chúng không thể sử dụng cùng một kênh để tấn công và thu thập thông tin, server quá chậm hoặc không đủ ổn định để xử lý các truy vấn SQL và trả về kết quả trong thời gian hợp lý, dẫn đến kết quả thu được không chính xác… 

Đối với kỹ thuật Out-of-band SQL Injectio, kẻ tấn công sẽ tận dụng các tính năng đặc biệt trên server database hoặc ứng dụng web để tấn công và thu thập thông tin. Các tính năng này có thể bao gồm khả năng tạo ra các request DNS hoặc HTTP từ server hoặc khả năng gửi dữ liệu từ server tới kênh mà hacker có thể thu thập.

>> Xem thêm: Cơ sở dữ liệu là gì? Tại sao phải quản lý cơ sở dữ liệu?

Những hậu quả nặng nề của tấn công SQL injection

SQL injection có thể dẫn đến những hậu quả nghiêm trọng cho hệ thống và dữ liệu, bao gồm:

  • Lộ thông tin nhạy cảm: Kẻ tấn công có thể sử dụng SQL injection để truy xuất thông tin nhạy cảm từ cơ sở dữ liệu như tên người dùng, mật khẩu, thông tin tài khoản ngân hàng, v.v. Thông tin này sau đó có thể được sử dụng cho các mục đích xấu.

  • Sửa đổi hoặc xóa dữ liệu: Bằng cách thực hiện các câu lệnh SQL độc hại, kẻ tấn công có thể sửa đổi hoặc xóa dữ liệu trong cơ sở dữ liệu. Điều này có thể gây ra thiệt hại nghiêm trọng cho hệ thống và ảnh hưởng đến hoạt động của doanh nghiệp.

  • Tiết lộ cấu trúc cơ sở dữ liệu: Thông qua việc thử nghiệm và khai thác lỗ hổng SQL injection, kẻ tấn công có thể tiết lộ cấu trúc của cơ sở dữ liệu, bao gồm các bảng, cột, quan hệ giữa các bảng. Điều này giúp họ chuẩn bị cho các cuộc tấn công khác vào hệ thống.

  • Quyền truy cập không ủy quyền: Nếu kẻ tấn công thành công thực hiện SQL injection, họ có thể có quyền truy cập không ủy quyền vào hệ thống, thậm chí trở thành người quản trị hệ thống. Điều này đe dọa tính toàn vẹn và bảo mật của dữ liệu.

Ví dụ thực tiễn về cách sử dụng kỹ thuật tấn công SQL Injection

Để thực hiện SQL injection, tin tặc sẽ tiến hành thao túng 1 truy vấn SQL tiêu chuẩn được sử dụng trong ứng dụng web để khai thác lỗ hổng input không được kiểm tra hoặc xác thực đúng trong database. Để thực hiện vector này, chúng có thể thực hiện theo nhiều cách khác nhau, và đây là một ví dụ điển hình: 

Trong quá trình xử lý thông tin input, hệ thống sẽ lấy một số thông tin của sản phẩm và được đổi thành: 

http://www.estore.com/items/items.asp?itemid=999 or 1=1

Lúc này, truy vấn SQL sẽ như sau: 

truy vấn SQL

Trong truy vấn trên, lệnh 1 = 1 luôn đúng, nên truy vấn sẽ trả về tên và mô tả chi tiết trong database - ngay cả những sản phẩm mà bạn không có đủ điều kiện để truy cập. 

Lúc này, tin tặc sẽ lợi dụng ký tự được lọc không đúng để thay đổi câu lệnh SQL, bao gồm cả việc thêm dấu chấm phẩy để tách biệt thành 2 trường.

Khi đó, câu lệnh sẽ trở thành:

http://www.estore.com/items/iteams.asp?itemid=999; DROP TABLE USERS

Truy vấn SQL sẽ được tạo ra với dạng sau: 

truy vấn SQL

Lúc này, toàn bộ database có thể sẽ bị xóa sạch. 

Có một cách khác thường được kẻ tấn công sử dụng để thao túng truy vấn SQL đó là dùng lệnh UNION SELECT. Phương pháp này sẽ kết hợp 2 truy vấn SELECT không liên quan với nhau để thu thập dữ liệu từ các database khác nhau: 

Chẳng hạn, ta có input:

http://www.estore.com/items/items.asp?itemid=999 UNION SELECT user-name, password FROM USERS

Input trên sẽ tạo nên một truy vấn SQL là: 

truy vấn SQL

Với lệnh UNION SELECT, 2 truy vấn trên sẽ được kết hợp để lấy thông tin về item 999 và danh sách username + password của họ trong database. 

Các phần dễ bị tấn công bằng kỹ thuật SQL Injection

Các thành phần của một ứng dụng web dễ bị tấn công bằng kỹ thuật SQL Injection thường là những nơi mà người dùng có thể cung cấp dữ liệu (đầu vào) và dữ liệu này được sử dụng để xây dựng các truy vấn SQL mà không được kiểm tra hoặc xử lý cẩn thận. Điều này tạo ra cơ hội tuyệt vời cho các cuộc tấn công SQL Injection. Dưới đây là các thành phần thường dễ bị tấn công:

  • Form đăng nhập: Khi người dùng nhập tên người dùng và mật khẩu vào form đăng nhập, các giá trị này thường được sử dụng để kiểm tra trong cơ sở dữ liệu để xác thực người dùng. Nếu không kiểm tra và xử lý đầu vào cẩn thận, tấn công SQL Injection có thể xảy ra.

  • Form tìm kiếm: Các trang web có chức năng tìm kiếm cho phép người dùng nhập từ khóa tìm kiếm có nguy cơ bị tấn công. Nếu các giá trị nhập vào không được sạch, tin tặc có thể chèn các đoạn mã SQL nguy hiểm để can thiệp vào truy vấn tìm kiếm.

  • Form nhận xét: Các form cho phép người dùng nhập nhận xét, bình luận, hoặc phản hồi trên các nội dung. Nếu dữ liệu này không được xử lý đúng cách, tin tặc có thể chèn mã SQL để tấn công cơ sở dữ liệu.

  • Bất kỳ trường lưu hoặc trường đầu vào dữ liệu nào: Bất kỳ trường nào yêu cầu người dùng nhập dữ liệu có thể dễ dàng bị lợi dụng để thực hiện SQL Injection, bao gồm cả các trường đơn giản như họ tên, địa chỉ email, hay các trường thông tin khác.

  • Các liên kết của website: Nếu các thông tin trong URL được sử dụng để thực hiện các truy vấn đến cơ sở dữ liệu mà không được kiểm tra cẩn thận, các liên kết của website cũng có thể dễ bị tấn công bằng SQL Injection.

Các phần dễ bị tấn công bằng kỹ thuật SQL Injection
Các thành phần bị tấn công bằng kỹ thuật SQL Injection thường là những nơi mà người dùng có thể cung cấp dữ liệu (đầu vào)

Để ngăn chặn tấn công SQL Injection, các lập trình viên cần áp dụng các biện pháp bảo mật như sử dụng câu lệnh truy vấn tham số hóa (prepared statements) hoặc dùng ORM (Object-Relational Mapping) để tạo truy vấn an toàn, hạn chế quyền truy cập cơ sở dữ liệu của ứng dụng, và kiểm tra và xử lý đầu vào người dùng kỹ lưỡng. Điều quan trọng là kiểm tra và bảo vệ tất cả các điểm đầu vào của ứng dụng web để đảm bảo an toàn và bảo mật.

Trong nội dung tiếp theo, chúng ta sẽ cùng tìm hiểu rõ hơn về cách ngăn chặn SQL Injection 

Cách ngăn chặn SQL Injection là gì?

Với những hậu quả nặng nề mà SQL Injection gây ra, bạn nên chủ động thực hiện một số biện pháp ngăn chặn sau để giảm thiểu rủi ro đến từ hình thức tấn công nguy hiểm này: 

Input Validation

Input validation (Xác thực đầu vào) là quá trình kiểm tra và xác minh tính hợp lệ của dữ liệu được gửi từ bên ngoài vào một trang web, ứng dụng. Mục đích của quá trình này là đảm bảo rằng dữ liệu đầu vào đáp ứng các tiêu chuẩn và yêu cầu nhất định trước khi nó được xử lý. Hiện nay, đây là một trong những phương pháp hiệu quả giúp người dùng ngăn ngừa các cuộc tấn công như SQL Injection, Cross-Site Scripting (XSS)... 

Đối với SQL Injection, bạn có thể chống lại các câu lệnh được chèn vào chuỗi input của ứng dụng. Trước khi thực hiện biện pháp này, bạn cần chú ý đến một số tình huống như sau: 

  • Sử dụng Regex (biểu thức chính quy) làm whitelist cho dữ liệu có cấu trúc như tên, tuổi, zipcode, thu nhập… để đảm bảo rằng xác thực input là hợp lệ.

  • Nếu như bạn cần tạo bộ giá trị cố định (chẳng hạn như drop-down list), bạn cần xác định rõ value sẽ được trả về để đảm bảo rằng dữ liệu đầu vào trùng khớp chính xác với một trong các tùy chọn trên. 

Đây là cách để bạn 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');

}

Trong đó, biến $tableName có thể được append và trở thành một trong những value hợp lệ cho tên của Table. 

Đối với drop-down list, bạn chỉ cần xác thực dữ liệu bằng cách đổi PHP code (trong trường hợp cần chọn xếp hạng từ 1 - 5) 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!";

}

Lúc này, bạn đã thêm thành công 2 kiểm tra đơn giản là:

  • is_numeric(): Phải là 1 số.

  • Snumber>0, <6: Lớn hơn 0, nhỏ hơn 6 nên sẽ nằm trong khoảng từ 1 - 5.

Cần lưu ý rằng, tất cả dữ liệu được nhập vào từ bên ngoài đều phải được xác thực một cách kỹ lưỡng, kể cả đó là input của người dùng internet hay các nguồn khác như nhà cung cấp, đối tác và cơ quan quản lý. 

Parametrized queries

Parametrized queries hay tham số hóa truy vấn cho phép người dùng pro-compile các lệnh SQL. Thông qua đó, bạn có thể cung cấp các tham số để thực thi truy vấn thay vì phải xử lý trực tiếp các giá trị vào lệnh SQL. Bằng cách này, database có thể nhận ra và phân biệt được mã code với dữ liệu input.

Parametrized queries giúp giảm thiểu rủi ro từ các cuộc tấn công SQL nhờ vào cơ chế mã hóa và trích dẫn tự động input người dùng. Ngoài ra, thay vì sử dụng các truy vấn tham số hóa với phần mở rộng là MySQLi, bạn cũng có thể tham khảo một cách tiếp cận tối ưu hơn với PHP Data Objects (PDO). 

Cách ngăn chặn SQL Injection là gì?
Ngăn chặn SQL Injection với Parametrized queries

PDO sẽ mang đến giải pháp đơn giản và linh hoạt hơn trong việc sử dụng truy vấn tham số hóa. Ngoài ra, PDO còn giúp code trở nên dễ đọc, dễ di chuyển và hoạt động tốt trên nhiều database khác thay vì chỉ sử dụng được cho MySQL. Trong đoạn code dưới đây, Gofiber đang sử dụng PDO cho cho các truy vấn tham số hóa để ngăn chặn 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

Stored Procedure (SP) là một khối mã SQL được lưu trữ trong cơ sở dữ liệu để thực thi các tác vụ cụ thể. Một Stored Procedure là một đơn vị logic tổng hợp mà các lệnh SQL được gom nhóm lại, có thể được gọi và thực thi bất cứ khi nào cần thiết. Nói một cách dễ hiểu thì SP là một loại code có thể được lưu trữ và sử dụng lại trong tương lai. 

Với cách này, bạn không cần phải viết đi viết lại để thực hiện truy vấn bất kì, mà chỉ cần gọi một stored procedure. Quá trình tạo một SP trong máy chủ MySQl có thể diễn ra như sau:

Chẳng hạn như bạn có một bảng như thế này: 

CREATE TABLE `salary` (

  `empid` int(11) NOT NULL,

  `sal` int(11) DEFAULT NULL,

  PRIMARY KEY (`empid`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Nếu một người dùng muốn sử dụng dữ liệu tổng hợp về lương từ bảng trên, bạn cần tạo một người dùng mới tạm gọi là là “tr”.

CREATE USER 'tr'@'localhost' IDENTIFIED BY 'mypass';

Lúc này, người dùng đó cần có quyền EXECUTE đối với vị trí nơi có Table: 

grant execute on hris.*  to tr@`%`

Bây giờ, 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 sẽ tạo 1 avg>sal SP và lưu trữ trong database. Nếu muốn gọi 1 SP từ ứng dụng PHP, bạn sử dụng PDO với câu lệnh sau:

$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ị số lương trung bình dựa trên yêu cầu của người dùng. Sau đó, bạn có thể tiến hành output với PHP.

Sử dụng Escaping

Sử dụng escaping (ký tự thoát) là một kỹ thuật quan trọng để bảo vệ hệ thống khỏi các cuộc tấn công SQL Injection và đảm bảo an toàn cho dữ liệu nhập từ người dùng. Đảm bảo rằng bạn luôn sử dụng hàm character-escaping của hệ thống quản lý cơ sở dữ liệu (DBMS) cho input được người dùng cung cấp để mã hóa các ký tự đặc biệt có trong chuỗi dữ liệu input  trước khi thêm chúng vào truy vấn SQL.

Chẳng hạn như, bạn có thể sử dụng hàm mysqli_real_escape_string() trong PHP khi làm việc với MySQL để tránh các lệnh SQL không mong muốn được thực thi. Một session sửa đổi cho login bypass sẽ có dạng 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 đó, tin tặc có thể thêm escape character (\) trước dấu ngoặc để thực hiện SQL Injection, nhưng với mã trên, hệ thống sẽ được bảo vệ trước các user bất hợp pháp và giảm thiểu rủi ro bị tấn công SQL injection.

Bên trên là câu trả lời cho thắc mắc “SQL Injection là gì” mà bạn có thể tham khảo. Có thể nói rằng, SQL Injection là một hình thức tấn công cực kỳ nguy hiểm. Vì thế, trang bị kiến thức và thực hiện các biện pháp ngăn chặn SQL Injection là việc làm vô cùng cần thiết để tự bảo vệ nền tảng của mình trước rủi ro đến từ hình thức này. Ngoài ra, đừng quên để lại comment bên dưới nếu có bất cứ câu hỏi nào cần được giải đáp bởi đội ngũ của Gofiber nhé!

5/5 - (0 bình chọn)

Chào mọi người, mình là Nguyễn Trung Hiếu - một người đam mê mãnh liệt với thế giới lập trình và công nghệ. Hiện tại, mình có vinh dự đồng hành cùng Công ty Gofiber, đảm nhận vai trò trong Ban Giám Đốc và dẫn dắt nhóm IT. Cuộc hành trình nghề nghiệp của mình không chỉ là hành trình học hỏi, khám phá về lập trình mà còn là sự trao đổi, chia sẻ những kiến thức về hệ thống server, hosting và nhiều lĩnh vực khác. Mình tin rằng sự nhiệt huyết và tinh thần học hỏi luôn dẫn đến những thành công bất ngờ, và mình rất háo hức được chia sẻ những trải nghiệm này với bạn đọc của Gofiber.


CÓ THỂ BẠN QUAN TÂM

Xem nhiều nhất

thuê VPS giá rẻ