Nếu bạn đang phát triển một sản phẩm về website hoặc app có chức năng yêu cầu người dùng đăng nhập thì bạn sẽ phải xử lý việc lưu trữ mật khẩu. Tuy nhiên, việc lưu trữ mật khẩu trong database một cách không an toàn có thể dẫn đến những rủi ro bảo mật nghiêm trọng. Đây là một ví dụ về Vụ tấn công Post Millennial làm rò rỉ dữ liệu ảnh hưởng đến 26 triệu người bởi vì không lưu trữ dữ liệu một cách an toàn và bảo mật. Vậy làm thế nào để lưu trữ mật khẩu một cách an toàn?
Bài viết này sẽ cung cấp cho bạn những kiến thức cơ bản về cách lưu trữ mật khẩu an toàn trong cơ sở dữ liệu, giúp bảo vệ thông tin người dùng và doanh nghiệp hiệu quả hơn trước các kỹ thuật tấn công mật khẩu của hacker.
1. Các hình thức lưu trữ mật khẩu không an toàn
Trước khi tìm hiểu chi tiết về các kỹ thuật lưu trữ mật khẩu an toàn, chúng ta cần nhận thức rõ các nguy cơ tiềm ẩn khi mật khẩu được lưu trữ không an toàn trong cơ sở dữ liệu. Để làm điều này, trước hết, bạn cần nắm vững một số khái niệm liên quan đến bảo mật.
1.1. Mật khẩu dạng plaintext
Cách tệ nhất để lưu trữ mật khẩu là lưu trữ chúng dưới dạng plaintext (văn bản thuần túy) trong cơ sở dữ liệu, cùng với các dữ liệu người dùng khác. Điều này cực kỳ nguy hiểm vì nếu hacker hoặc bất kỳ ai có quyền truy cập vào cơ sở dữ liệu, họ có thể dễ dàng nhìn thấy và đánh cắp tất cả mật khẩu sau đó sử dụng nó cho mục đích xấu.
1.2. Mã hóa yếu
Việc sử dụng các thuật toán mã hóa yếu hoặc không đúng cách có thể bị phá vỡ dễ dàng bởi các công cụ tấn công hiện đại. Mã hóa yếu có thể bao gồm việc sử dụng các thuật toán lỗi thời hoặc có lỗ hổng đã biết.
Ví dụ: Các hàm băm như MD5, SHA1, SHA2, và SHA3 được thiết kế để hoạt động nhanh chóng, nhưng chúng không đủ an toàn để lưu trữ mật khẩu. Khi lưu trữ mật khẩu, bạn cần sử dụng các thuật toán băm được thiết kế đặc biệt để chống lại các cuộc tấn công brute-force và tấn công từ điển (dictionary attacks).
Nếu người dùng tạo mật khẩu chỉ gồm chữ thường và số với độ dài 6 ký tự, hacker có thể kiểm tra tất cả các kết hợp của mật khẩu này chỉ trong khoảng 40 giây và tìm ra mật khẩu đúng. Hoặc tin tặc có thể sử dụng những công cụ hiện đại như công nghệ CUDA, chúng có thể xây dựng một siêu máy tính nhỏ với khả năng băm mật khẩu lên tới 700 triệu mật khẩu mỗi giây.
1.3. Sai sót bảo mật Database:
Các lỗ hổng bảo mật trong cơ sở dữ liệu có thể dẫn đến việc kẻ tấn công truy cập và đánh cắp mật khẩu. Những lỗ hổng này có thể bao gồm SQL injection, lỗ hổng trong phần mềm cơ sở dữ liệu hoặc các lỗi cấu hình khác.
Ví dụ: Về việc dùng SQL Injection. Giả sử bạn có 1 form đăng nhập như ở hình dưới:
Bạn xử lý form đăng nhập ở phía sever bằng code PHP như bên dưới
<?php
// Kết nối đến cơ sở dữ liệu
$mysqli = new mysqli("localhost", "user", "password", "database");
// Lấy đầu vào từ người dùng (không an toàn)
$username = $_POST['username'];
$password = $_POST['password'];
// Tạo truy vấn SQL (không an toàn)
$sql = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
// Thực hiện truy vấn
$result = $mysqli->query($sql);
// Kiểm tra kết quả
if ($result->num_rows > 0) {
echo "Đăng nhập thành công!";
} else {
echo "Sai tên đăng nhập hoặc mật khẩu.";
}
?>
Trong ví dụ trên, nếu người dùng nhập vào tên đăng nhập và mật khẩu dùng nhập thêm một dấu nháy đơn (') hoặc nháy kép (") có thể dẫn đến lỗi cú pháp SQL hoặc tạo ra lỗ hổng bảo mật nghiêm trọng.
Ví dụ người dùng nhập vào tên đăng nhập ' OR '1'='1 và mật khẩu ' OR '1'='1, truy vấn SQL sẽ trở thành:
SELECT * FROM users WHERE username = '' OR '1'='1' AND password = '' OR '1'='1';
2. Các kỹ thuật lưu trữ mật khẩu an toàn
2.1. Các thuật toán slow hashing
Với khả năng tính toán khổng lồ của GPU (bộ xử lý đồ họa), kẻ tấn công có thể thử hàng tỷ hàm băm mỗi giây. Điều này đồng nghĩa với việc chúng có thể dễ dàng phá vỡ các mật khẩu phổ biến bằng cách thử tất cả các tổ hợp khả thi trong một thời gian ngắn. Vậy nên thực hiện 1 thuật toán slow hashing là cần thiết để tiêu tốn nhiều thời gian và tài nguyên hơn.
Hàm băm chậm, như bcrypt, scrypt và Argon2,.. thay vì tính toán nhanh chóng, chúng tạo ra độ trễ cố ý, khiến việc tấn công brute-force trở nên khó khăn hơn rất nhiều.
- Muối (Salt): Các hàm băm chậm sử dụng muối - một chuỗi ký tự ngẫu nhiên được thêm vào mật khẩu trước khi băm. Muối làm cho kết quả băm trở nên duy nhất cho mỗi mật khẩu, khiến việc sử dụng bảng băm tiền tính toán (precomputed hash table) trở nên vô hiệu.
- Hệ Số Công Việc (Work Factor): Các hàm băm chậm cho phép bạn điều chỉnh mức độ chậm, được gọi là hệ số công việc. Hệ số công việc càng cao, hàm băm càng chậm và càng khó bị phá vỡ.
- Tốn Kém Tài Nguyên: Các hàm băm chậm đòi hỏi nhiều tài nguyên hơn, bao gồm thời gian xử lý CPU, bộ nhớ và năng lượng. Điều này khiến việc tấn công brute-force tốn kém và khó thực hiện hơn.
Tìm hiểu về thuật toán của bcrypt
bcrypt là một thuật toán băm mật khẩu được thiết kế để lưu trữ mật khẩu một cách an toàn. Nó sử dụng một hàm băm Blowfish để băm mật khẩu và được thiết kế để chống lại các cuộc tấn công brute-force bằng cách sử dụng kỹ thuật làm chậm (cost factor). Bcrypt cũng sử dụng muối (salt) để đảm bảo rằng mỗi mật khẩu sẽ có một giá trị băm duy nhất, ngay cả khi hai mật khẩu giống nhau.
PHP cung cấp các hàm tích hợp sẵn để làm việc với bcrypt, giúp bạn dễ dàng băm và xác thực mật khẩu. Dưới đây là các ví dụ cụ thể về cách sử dụng bcrypt trong PHP.
Bước 1: Tạo mật khẩu mã hóa với random salt:
<?php
$myPlaintextPassword = '$x*&5a#6%7=8';
$attackerPassword = 'attacker_password';
$saltRounds = 10;
// Tạo mật khẩu mã hóa với random salt
$myPasswordHash = password_hash($myPlaintextPassword, PASSWORD_BCRYPT, ["cost" => $saltRounds]);
echo "Mật khẩu mã hóa: " . $myPasswordHash;
?>
Ví dụ kết quả:
$2y$10$wH7yBXN39uE9H/PS/7v5mOSz4I.WE98Cg4SD5Bz9XxyULWyX9QO7C
- 2y: Chỉ định thuật toán bcrypt.
- 10: số vòng tính salt (salt round), giá trị cao hơn sẽ làm chậm quá trình băm hơn
- wH7yBXN39uE9H/PS/7v5mOSz4I.WE98Cg4SD5Bz9XxyULWyX9QO7C: Giá trị băm của mật khẩu kết hợp với muối.
Lưu ý: Thuật toán bcrypt gộp cả salt, số vòng tính salt và text đã mã hóa vào cùng một chuỗi kết quả. Các thông tin này sẽ được sử dụng để kiểm tra mật khẩu sau này.
Bước 2: Kiểm tra xem mật khẩu nhập vào có đúng hay không:
<?php
$hash = '$2y$10$wH7yBXN39uE9H/PS/7v5mOSz4I.WE98Cg4SD5Bz9XxyULWyX9QO7C';
// Kiểm tra với mật khẩu đúng
if (password_verify($myPlaintextPassword, $hash)) {
echo "Mật khẩu đúng.\n";
} else {
echo "Mật khẩu sai.\n";
}
// Kiểm tra với mật khẩu sai
if (password_verify($attackerPassword, $hash)) {
echo "Mật khẩu đúng.\n";
} else {
echo "Mật khẩu sai.\n";
}
?>
Đây là một ví dụ minh họa cụ thể về cách băm mật khẩu bằng bcrypt trong PHP, và kết quả hiển thị giá trị trước và sau khi băm. Sử dụng bcrypt giúp đảm bảo mật khẩu được lưu trữ một cách an toàn và khó bị tấn công.
2.2. Không lưu trữ mật khẩu
Ở trên, chúng ta đã cùng tìm hiểu về các phương pháp mã hóa và băm mật khẩu phổ biến như bcrypt nhằm bảo mật thông tin người dùng. Tuy nhiên, liệu lưu trữ mật khẩu trong cơ sở dữ liệu, dù đã được mã hóa, có thực sự là cách tối ưu nhất?
Câu trả lời là không.
Có một giải pháp an toàn hơn, đó là không lưu trữ mật khẩu trong cơ sở dữ liệu. Nghe có vẻ lạ, nhưng đây thực sự là một phương pháp được nhiều hệ thống lớn trên thế giới áp dụng.
Vậy làm thế nào để người dùng đăng nhập mà không cần lưu trữ mật khẩu?
Cái chìa khóa nằm ở việc sử dụng các dịch vụ xác thực bên thứ ba như Đăng nhập bằng Google, Facebook, Apple,....
Lợi ích của việc sử dụng dịch vụ xác thực bên thứ ba:
- An toàn hơn: Bạn không phải lo lắng về việc mật khẩu bị đánh cắp, bởi vì thông tin mật khẩu được lưu trữ và quản lý bởi các dịch vụ xác thực có uy tín.
- Tiện lợi: Người dùng có thể đăng nhập nhanh chóng và dễ dàng bằng tài khoản mạng xã hội đã có sẵn.
- Giảm thiểu rủi ro: Các dịch vụ xác thực bên thứ ba thường cung cấp nhiều lớp bảo mật, bao gồm xác thực hai yếu tố, giúp bảo vệ tài khoản người dùng tốt hơn.
- Tiết kiệm chi phí và thời gian: Bạn không cần phải đầu tư vào việc xây dựng và duy trì hệ thống xác thực riêng biệt.
Ví dụ: Khi bạn đăng nhập vào một website bằng tài khoản Google, website đó sẽ yêu cầu quyền truy cập vào tài khoản Google của bạn. Khi bạn chấp nhận, website sẽ nhận được thông tin xác thực của bạn từ Google, bao gồm thông tin người dùng và token xác thực. Website này sẽ sử dụng token này để xác định bạn là ai, mà không cần lưu trữ mật khẩu của bạn.
Lưu ý:
- Việc không lưu trữ mật khẩu không có nghĩa là bạn bỏ qua việc bảo mật. Bạn vẫn cần phải áp dụng các biện pháp bảo mật khác, như xác thực hai yếu tố, kiểm tra an ninh thường xuyên và cập nhật các bản vá lỗi bảo mật.
- Bạn có thể kết hợp việc không lưu trữ mật khẩu với các phương pháp mã hóa và băm mật khẩu để tăng cường bảo mật. Ví dụ, bạn có thể sử dụng bcrypt để mã hóa thông tin xác thực do dịch vụ xác thực bên thứ ba cung cấp.
3. Lựa chọn phương pháp phù hợp
Việc lựa chọn phương pháp lưu trữ mật khẩu phù hợp phụ thuộc vào nhiều yếu tố như:
- Quy mô của hệ thống: Hệ thống lớn có thể yêu cầu giải pháp bảo mật phức tạp hơn.
- Yêu cầu bảo mật: Các hệ thống liên quan đến thông tin nhạy cảm cần sử dụng phương pháp mã hóa mạnh mẽ hơn.
- Ngân sách: Các giải pháp bảo mật phức tạp thường có chi phí cao hơn.
4. Kết luận
Bảo mật thông tin, đặc biệt là mật khẩu, là một vấn đề cực kỳ quan trọng trong thời đại kỹ thuật số. Việc lưu trữ mật khẩu an toàn là điều cần thiết để bảo vệ thông tin của người dùng và doanh nghiệp.
Bài viết này đã cung cấp cho bạn kiến thức cơ bản về các kỹ thuật lưu trữ mật khẩu an toàn trong Database. Hãy lựa chọn phương pháp phù hợp với nhu cầu và khả năng của bạn để đảm bảo thông tin mật khẩu được bảo vệ một cách hiệu quả.
Nếu bạn có quan tâm về chủ đề lập trình, mời bạn tham khảo các bài blog sau tại 200Lab nhé:
Bài viết liên quan
MikroORM là gì? So sánh TypeORM, Sequelize, MikroORM và Prisma
Oct 26, 2024 • 10 min read
Tìm Hiểu Single Sign-On (SSO): Giải pháp đăng nhập một lần
Oct 26, 2024 • 11 min read
Giới thiệu FFmpeg: Hướng dẫn Encode Video và Streaming với HLS
Oct 25, 2024 • 14 min read
SQL Injection là gì? Mối Đe Dọa Đối Với Cơ Sở Dữ Liệu
Oct 25, 2024 • 10 min read
So sánh hiệu suất Query của PostgreSQL và MySQL
Oct 24, 2024 • 9 min read
Fastify là gì? So sánh hiệu suất của Fastify và ExpressJS
Oct 22, 2024 • 12 min read