SQL Injection là gì? Cách giảm thiểu và phòng ngừa SQL Injection

SQL Injection là gì?

SQL Injection là một kỹ thuật lợi dụng những lỗ hổng về câu truy vấn của các ứng dụng. Được thực hiện bằng cách chèn thêm một đoạn SQL để làm sai lệnh đi câu truy vấn ban đầu, từ đó có thể khai thác dữ liệu từ database. SQL injection có thể cho phép những kẻ tấn công thực hiện các thao tác như một người quản trị web, trên cơ sở dữ liệu của ứng dụng.

Ví dụ thực tiễn SQL Injection

Ví dụ, trong form đăng nhập, người dùng nhập dữ liệu, trong trường tìm kiếm người dùng nhập văn bản tìm kiếm, trong biểu mẫu lưu dữ liệu, người dùng nhập dữ liệu cần lưu. Tất cả các dữ liệu được chỉ định này đều đi vào cơ sở dữ liệu.

Thay vì nhập dữ liệu đúng, kẻ tấn công lợi dụng lỗ hổng để insert và thực thi các câu lệnh SQL bất hợp pháp để lấy dữ liệu của người dùng… SQL Injection được thực hiện với ngôn ngữ lập trình SQL. SQL (Structured Query Language) được sử dụng để quản lý dữ liệu được lưu trữ trong toàn bộ cơ sở dữ liệu.

Tuy nhiên ngày nay chứng ta thường làm việc trên những framework hiện đại. Các framework đều đã được test cẩn thận để phòng tránh các lỗi, trong đó có SQL Injection.

Sự nguy hiểm của SQL Injection

  • Hack tài khoản cá nhân.
  • Ăn cắp hoặc sao chép dữ liệu của trang web hoặc hệ thống.
  • Thay đổi dữ liệu nhạy cảm của hệ thống.
  • Xóa dữ liệu nhạy cảm và quan trọng của hệ thống.
  • Người dùng có thể đăng nhập vào ứng dụng với tư cách người dùng khác, ngay cả với tư cách quản trị viên.
  • Người dùng có thể xem thông tin cá nhân thuộc về những người dùng khác, ví dụ chi tiết hồ sơ của người dùng khác, chi tiết giao dịch của họ,…
  • Người dùng có thể sửa đổi cấu trúc của cơ sở dữ liệu, thậm chí xóa các bảng trong cơ sở dữ liệu ứng dụng.
  • Người dùng có thể kiểm soát máy chủ cơ sở dữ liệu và thực thi lệnh theo ý muốn.
  MySQL ngoại truyện
  SQL Series: 5 mẹo dành cho SQL

Ví dụ tấn công

Việc kiểm tra lỗ hổng này có thể được thực hiện rất dễ dàng. Đôi khi ta chỉ cần nhập ký hiệu ' hoặc " vào các trường được kiểm tra. Nếu nó trả về bất kỳ thông báo bất ngờ hoặc bất thường, thì ta có thể chắc chắn rằng SQL Injection khả thi cho trường đó.

Ví dụ: một Form đăng nhập như sau
SQL Injection là gì? Cách giảm thiểu và phòng ngừa SQL Injection

Và đoạn code server xử lý của bạn:

if(isset($_POST['username']) && isset($_POST['password'])){
$sql = "SELECT * FROM tbl_user WHERE username='". $_POST['username'] . "' AND password = '" .$_POST['password'] ."'";
}

Nếu như người dùng không nhập bình thường nữa mà chẳng hạn như họ có thêm một dấu nháy ' hoặc " vào thì dòng code của bạn sẽ bị lỗi ngay. Hoặc họ có thể sửa thành một câu truy vấn luôn luôn đúng như sau.

SELECT * FROM tbl_user WHERE username = '' OR '1' = '1' and password = '' OR '1' = '1'

Hoặc chèn thêm một câu lệnh truy vấn phía sau:

VD:

SELECT * FROM tbl_user WHERE username = 'admin' and password = 'admin'; Drop table users;

Các phần dễ bị tấn công

SQL Injection

Các phần dễ bị tấn công bao gồm:

  • Form đăng nhập
  • Form tìm kiếm
  • Form nhận xét
  • Bất kì trường lưu hoặc trường đầu vào của dữ liệu
  • Liên kết của website

Cần lưu ý là trong khi thử nghiệm chống lại tấn công này là không thể chỉ kiểm tra một hoặc một vài trường bởi vì một trường có thể được bảo vệ chống lại SQL Injection, nhưng một trường khác thì không. Do đó, điều quan trọng là đừng quên kiểm tra tất cả các trường của trang web.

Cách giảm thiểu và phòng ngừa SQL Injection

Luôn kiểm tra kỹ các trường nhập dữ liệu và các bạn cần ràng buộc thật kỹ dữ liệu người dùng nhập vào.

Ví dụ:

//Thông thường
$id = $_GET['id'];
//Ràng buộc
$id = isset($_GET['id'])?(string)(int)$_GET['id']:false;

Dùng Regular Expression để loại bỏ đi các ký tự lạ hoặc các ký tự không phải là số.

$id = isset($_GET['id']) ? $_GET['id'] : false;
$id = str_replace('/[^0-9]/', '', $id);

Hoặc dùng các hàm có sẵn để giảm thiểu lỗi. Mỗi khi truy vấn thì mọi người nên sử dụng thêm hàm mysqli_real_escape_string để chuyển đổi một chuỗi thành một query an toàn.

$id = isset($_GET['id'])?(string)(int)$_GET['id']:false;
$sql= 'SELECT * FROM tbl_user WHERE id= ' . mysqli_real_escape_string($id);

Và lời khuyên cuối cùng là chúng ta nên dùng các Framework và hạn chế dùng code thuần tối đa nếu có thể. Framework luôn có cộng đồng hoặc các chuyên gia bảo mật giúp tìm lỗi và update liên tục, từ đó chúng ta có thể giảm bớt thời gian xử lý lỗi để tăng thời gian làm sản phẩm cũng là một điều hay.

Tham khảo thêm các vị trí tuyển lập trình SQL lương cao tại Topdev.

  Đánh cắp Cookie bằng cách lợi dụng lỗi bảo mật XSS
  Tại sao phải sử dụng JSON Web Token (JWT) để bảo mật API