Cafe chém gió: lưu mật khẩu trong CSDL (Phần 1)
Thỉnh thoảng các trang tin tức, báo mạng, facebook,... có đăng những thông tin về một dịch vụ, mội doanh nghiệp nào đó bị hacker tấn công, đánh cắp và rao bán dữ liệu trên "chợ đen". Đối tượng bị hacker nhắm đến thường là những trang web, dịch vụ lớn, có nhiều người dùng.
Ngay cả một công ty "bình thường" tại VN cũng bị tấn công. Hacker trong vụ này còn nghênh ngang khiêu khích trực tiếp, bằng cách đăng tải một video cho thấy cách hắn ta truy cập được vào hệ thống mạng nội bộ của công ty này, từ đó tiến hành tấn công sâu hơn và đánh cắp dữ liệu.
Bị hacker tấn công thì là vấn đề của doanh nghiệp, nhưng dữ liệu bị lộ thì người dùng là đối tượng cần hoang mang. Nếu hacker có thể dựa vào những dữ liệu này để tìm được mật khẩu của người dùng thì rất nguy hiểm.
Vậy làm thế nào để bảo vệ thật tốt mật khẩu của người dùng kể cả khi cơ sở dữ liệu không may bị hacker đánh cắp và rao bán? Thay vì đọc một bài viết mang tính kỹ thuật đơn thuần, hôm nay chúng ta đổi phong cách một chút. Hãy theo dõi buổi trò chuyện dưới đây để biết thêm về cách bảo vệ mật khẩu an toàn nhé.
Buổi trò chuyện
... (lược bỏ 2000 từ) ...
Ông anh: Chú vẫn làm lập trình viên nhỉ? Sao hôm nay lại muốn tìm hiểu thêm về bảo mật dữ liệu thế?
Cậu em: Dòng đời xô đẩy thôi anh ạ. Mấy dự án trước thì em chỉ cần tập trung làm đúng phần được giao nên chưa đụng đến bao giờ. Sắp tới bên em có con dự án to, khách hàng yêu cầu cao về bảo mật, mà em thì chưa hiểu mấy để có thể giải thích cho khách hàng. Em biết mỗi anh là hay tìm hiểu về công nghệ và bảo mật, nên hôm nay mới xin anh chỉ giáo vài đường cơ bản.
Ông anh: Thế các dự án trước bên chú làm như nào, không có tí bảo mật nào luôn à?
Câu em: Vẫn có, nhưng mà em chỉ biết làm như nào, chứ không hiểu mấy. Sợ khách hỏi sâu cái là chịu luôn.
Ông anh: Thế mấy dự án trước bên chú làm như nào?
Cậu em: Ở mấy dự án trước, đội bên em lưu dữ liệu của người dùng vào bảng User. Trước khi lưu mật khẩu của người dùng vào đó thì bọn em có mã hóa mật khẩu.
Ông anh: Mã hóa mật khẩu, hay lưu giá trị hash?
Cậu em: Chắc là mã hóa mã hóa mật khẩu anh ạ. Em cứ theo đúng yêu cầu của dự án mà làm thôi, search google xem làm như nào rồi áp dụng vào dự án.
Ông anh: Khóa thì lưu như nào?
Cậu em: Khóa nào anh nhỉ 🤔
Ông anh: 😀. Khóa mã hóa dùng để mã hóa dữ liệu ấy 😅. Nếu mã hóa dữ liệu thì phải có khóa để mã hóa và giải mã. Còn tùy dùng phương pháp mã hóa nào nữa, mỗi phương pháp thì khóa mã hóa nó cũng khác nhau.
Cậu em: Thế hả anh.
Ông anh: Có hai phương pháp là mã hóa đối xứng và bất đối xứng. Cái trước thì chỉ có một khóa thôi, cái sau thì có bộ khóa gồm 2 khóa là khóa công khai và khóa bí mật. Mà nếu đã mã hóa dữ liệu thì còn phải để ý thêm là: mỗi tài khoản sẽ được mã hóa bằng một khóa riêng biệt, hoặc là dùng chung một khóa mã hóa cho tất cả tài khoản.
Cậu em: Ờm...🙄 Em chẳng thấy cái khóa mã hóa nào cả, thế thì có lẽ bọn em dùng phương pháp lưu giá trị hash rồi, không phải phương pháp mã hóa mật khẩu 😓.
Ông anh: Âu cây. Nghe chú nói thế là anh hiểu chú nắm được đến đâu rồi. Chắc chú cũng chẳng biết tại sao không lưu luôn mật khẩu vào cho tiện nhỉ?
Cậu em: Cái này thì em biết là vì yêu cầu bảo mật. Em nghe nói hacker có cách để nghe lén dữ liệu gửi đi từ thiết bị của người dùng tới máy chủ. Thành ra phải thực hiện biện pháp bảo vệ, tránh việc gửi mật khẩu bản rõ khi đăng nhập.
Ông anh: Nếu thế thì khi quá trình đăng ký tài khoản diễn ra, mật khẩu và mật khẩu lần 2 có được gửi tới máy chủ dưới dạng bản rõ không?
Cậu em: Có, đó là trường hợp duy nhất cho phép gửi mật khẩu bản rõ.
Ông anh: Không hẳn là thế đâu. Mã hóa mật khẩu để đề phòng bị hacker nghe lén trên đường truyền là tốt, đảm bảo giao tiếp qua giao thức có bảo mật như HTTPs thì cũng ok phết rồi. Nhưng mà việc lưu mã hash của mật khẩu vào CSDL thì là trong bối cảnh khác rồi, không liên quan mấy tới bảo mật trên đường truyền.
Cậu em: Ô thế cơ ạ 🤔.
Ông anh: Giờ nếu dự án của em lưu mật khẩu dưới dạng mã hash rồi, thì trong trường hợp cơ sở dữ liệu bị xâm phạm, việc đấy có tác dụng gì không?
Cậu em: Có tác dụng chứ anh. Nếu lưu bản rõ của mật khẩu thì hacker có thể đọc được, còn nếu lưu giá trị hash thì hacker không thể biết mật khẩu là gì.
Ông anh: Đúng, nhưng mà chưa đủ. Vẫn có khả năng mật khẩu được phục hồi thành bản rõ bằng cách sử dụng phương pháp tấn công rainbow table. Mà đã dùng hash là phải biết salt, chú có biết không?
Cậu em: Em có biết về khái niệm đó. Salt là một giá trị ngẫu nhiên, giúp mật khẩu an toàn hơn khi tính toán sang giá trị băm, đúng chưa anh?
Ông anh: Rồi, thế chú có biết sử dụng nó như nào không?
Cậu em: Cái này thì em chịu. Có nghe qua đọc qua, nhưng mà chưa dùng tới bao giờ 🤣.
Ông anh: Thế thì nghe anh giải thích cơ bản đây này. Trước khi tính toán giá trị hash, mật khẩu sẽ được nối thêm một đoạn ký tự ngẫu nhiên gọi là salt. Như vậy giá trị hash được tính ra và lưu trong cơ sở dữ liệu sẽ bằng hash(salt + password)
. Hiểu chưa?
Cậu em: Em hiểu rồi anh 😎.
Ông anh: Hiểu thì phải kiểm tra 😈.
Cậu em: 😱
Ông anh: Giả sử trường hợp hacker lấy được dữ liệu xảy ra, hacker sẽ cố dùng các phương pháp như tấn công brute-force, tấn công rainbow table,... để tìm ra bản rõ tương ứng của mỗi giá trị hash. Nếu hacker may mắn tấn công được, thì điều gì sẽ xảy ra?
Cậu em: Mật khẩu ở trong túi hacker ạ? 😎
Ông anh: Vớ vẩn 👊. Vừa nói xong đã vào tai trái, ra tai phải. Đã nối thêm salt vào mật khẩu rồi thì hacker chỉ tìm được (salt + password)
thồi. Khi không biết giá trị của salt, hacker vẫn không biết mật khẩu là gì.
Cậu em: Đúng là đi cafe với anh 1 buổi, hơn hẳn ngồi search google 😆.
... (còn tiếp ở phần 2) ...
Giải đáp kiến thức
Đoạn cafe chit chat vừa rồi đã đề cập đến nhiều khái niệm và kiến thức về lưu trữ mật khẩu an toàn, những kiến thức đó sẽ được tóm gọn lại và làm rõ dưới đây.
Giá trị băm của mật khẩu
Có lẽ đa số lập trình viên và kỹ sư bảo mật đều biết rằng chúng ta không còn lưu mật khẩu bản rõ từ lâu rồi. Tuy nhiên câu trả lời của ứng viên trong đoạn phỏng vấn trên vẫn chưa chính xác cho lắm.
Đầu tiên, việc giảm khả năng mật khẩu bản rõ được gửi tới server không phải mục đích của việc không lưu mật khẩu trong cơ sở dữ liệu dưới dạng bản rõ. Mật khẩu có thể được gửi đi dưới dạng bản rõ, hoặc dưới dạng mã hóa đều được. Trong trường hợp mật khẩu được gửi đi ở dạng bản rõ, thì chỉ cần đảm bảo kênh truyền dữ liệu là an toàn, ví dụ được mã hóa bằng cách giao tiếp qua HTTPS.
Thứ hai, mục đích chính của việc không lưu bản rõ của mật khẩu trong CSDL đúng là để phòng ngừa việc hacker có thể truy cập được vào CSDL. Mật khẩu được mã hóa, hoặc được lưu bằng giá trị hash đều có thể gây khó khăn cho việc phục hồi bản rõ của mật khẩu.
Thứ ba, bảo vệ mật khẩu của các tài khoản trên mỗi dịch vụ đều quan trọng. Vì người dùng vẫn có thói quen sử dụng chung một mật khẩu cho nhiều dịch vụ. Lộ mật khẩu ở một dịch vụ có thể dẫn đến lộ mật khẩu ở nhiều dịch vụ.
Trong hai phương án, thì lưu giá trị hash được sử dụng rộng rãi hơn, và cũng được khuyến nghị sử dụng hơn so với lưu giá trị mã hóa. Lý do là:
- Thuật toán mã hóa hoạt động theo hai chiều, từc là giá trị mã hóa có thể được giải mã. Trong khi đó thuật toán hash hoạt động theo một chiều, từ giá trị hash không thể tính toán ngược lại để tìm giá trị ban đầu được.
- Sử dụng phương pháp mã hóa luôn có rủi ro khi bị lộ khóa mã hóa.
- Để bảo vệ tốt khóa mã hóa có thể dẫn đến tốn nhiều chi phí hơn.
- Dữ liệu mã hóa vẫn có thể được giải mã và đọc bởi người có quyền truy cập CSDL, nhưng khi đã lưu giá trị hash thì đến người của dịch vụ đó cũng không biết mật khẩu của người dùng là gì.
Sử dụng thêm salt
Việc sử dụng salt có làm gia tăng chi phí không? Cái này là có, nhưng nó vẫn đảm bảo an toàn hơn so với tốn chi phí để bảo vệ khóa mã hóa.
Khi thêm salt, mật khẩu sẽ được bảo vệ tốt hơn trước các phương pháp tấn công nhắm vào giá trị hash (như tấn công rainbow table).
Salt không nên dùng chung cho mọi tài khoản, nó nên là duy nhất với mỗi tài khoản. Điều này đảm bảo kể cả nhiều tài khoản có mật khẩu giống nhau, thì giá trị hash mật khẩu của những tài khoản này sẽ khác nhau.
All rights reserved