Mục lục

SQL Injection và cách phòng tránh?

Theo Wikipedia:
SQL Injection là một kỹ thuật cho phép những kẻ tấn công lợi dụng lỗ hổng của việc kiểm tra dữ liệu đầu vào trong các ứng dụng web và các thông báo lỗi của hệ quản trị cơ sở dữ liệu trả về để inject (tiêm vào) và thi hành các câu lệnh SQL bất hợp pháp. SQL injection có thể cho phép những kẻ tấn công thực hiện các thao tác, delete, insert, update,… trên cơ sở dữ liệu của ứng dụng, thậm chí là server mà ứng dụng đó đang chạy, lỗi này thường xảy ra trên các ứng dụng web có dữ liệu được quản lý bởi các hệ quản trị cơ sở dữ liệu như SQL Server, MySQL, Oracle, DB2, Sysbase...
Trường hợp đơn giản nhất sẽ là lỗi không kiểm tra dữ liệu đầu vào:

Lỗi không kiểm tra dữ liệu đầu vào

Ta có form đăng nhập vào Admin Control Panel của website yourdoimain.com:
Tên đăng nhập:
Mật Khẩu:
Khi chúng ta nhập tên đăng nhập, mật khẩu và bấm nút Login, lập tức cơ sở dữ liệu sẽ truy vấn câu lệnh:
SELECT * FROM users WHERE username='tên đăng nhập' AND password='mật khẩu';
Vậy là cơ sở dữ liệu sẽ tìm những thằng admin có tên đăng nhập và mật khẩu trùng với những gì chúng ta đã viết ở form đăng nhập. Nếu có một thằng nào đó biết được cách thức chúng ta SELECT như trên, nó có thể dùng cách nhập form này để đăng nhập mà không cần biết Tên đăng nhập và mật khẩu của admin:
Tên đăng nhập: a' or 1=1; --Mật khẩu: Để trống
Lúc đó, lập tức cơ sở dữ liệu sẽ truy vấn câu lệnh
SELECT * FROM users WHERE username='a' or 1=1; --AND password='';
Theo như câu truy vấn này, cơ sở dữ liệu sẽ tìm những thằng admin có tên là a, và đương nhiên là không có thằng nào, sau đó cơ sở dữ liệu sẽ thực hiện phép so sánh xem 1 có bằng 1 không, nếu đúng thì câu lệnh SELECT sẽ được thực hiện(nó sẽ bỏ qua phần AND password='' vì mình đã thêm hai dấu -- vào trước, phần này sẽ trở thành phần chú thích). Và đương nhiên là nó phải được thực hiện tại vì 1 không bằng 1 thì bằng cái gì.

Trong trường hợp này cũng có nhiều cách phá, nếu hacker không muốn đăng nhập admin mà nó muốn DROP một table nào đó trong CSDL, muốn xoá một user nào đó hay nó thêm tên nó thành một thằng admin cũng được, các câu lệnh đều là câu lệnh căn bản của SQL, ví dụ muốn xoá table users:
Tên đăng nhập: a';DROP TABLE users; SELECT * FROM users WHERE 1= 1

Cách khắc phục:
Kiểm tra dữ liệu đầu vào bằng các điều kiện như: Xem tên đăng nhập có chứa các ký tự lạ hay không, có chứa dấu space không. Qua đó giúp chúng ta có thể giới hạn những gì người dùng có thể nhập vào.

Lỗi thay đổi giá trị điều kiện truy vấn

Dạng lỗi này khiến cho kẻ tấn công có thể thay đổi giá trị điều kiện trong câu truy vấn, làm sai lệch sự hiển thị của một ứng dụng chứa lỗi này.

Ví dụ ta có một URL, URL này sẽ hiển thị cuốn sách có ID là 1 trong cửa hàng:
http://yourdoimain.com/books.php?id=1
Khi người dùng truy nhập vào URL này, câu lệnh SQL sẽ được thực hiện như sau:
SELECT booktitle FROM books WHERE id = '1';
OK, vậy chúng ta sẽ Inject vào URL, sao cho nó không thể select được ví dụ như thêm điều kiện:
http://yourdoimain.com/books.php?id=1' AND 1=2; --
Như vậy, câu lệnh SQL sẽ trở thành:
SELECT booktitle FROM books WHERE id = '1' AND 1=2;
Tức là chỉ khi 1=2 thì câu lệnh trên mới được thực hiện, điều đó đồng nghĩa với việc câu lệnh này không bao giờ được thực hiện. Và nếu câu lệnh này không thể thực hiện, có thể nó sẽ ảnh hường đến các bảng khác trong CSDL.

Khắc phục:
Không để chỗ cho hacker khai thác. Nếu là URL thì nên Rewrite về một dạng khác có tính bảo mật cao hơn. Hoặc kiểm tra dữ liệu đầu vào trước khi thực hiện câu lệnh truy vấn SQL

Trong hai lỗ hổng trên, lỗ hổng được khai thác nhiều nhất có lẽ là Lỗi không kiểm tra dữ liệu đầu vào. Chúng ta nên có một sự chắc chắn về dữ liệu đầu vào trước khi thực hiện truy vấn câu lệnh SQL.