Tại sao lưu trữ mật khẩu người dùng?


10

Thỉnh thoảng tôi thấy các câu hỏi hỏi cách lưu trữ mật khẩu người dùng một cách an toàn cho một ứng dụng web (sử dụng RDBMS, tôi không nói về Facebook hay Twitter). Câu trả lời thông thường là "muối mật khẩu, sau đó băm nó bằng thuật toán mạnh như TDES hoặc SHA512".

Câu hỏi của tôi là: Là một người dùng RDBMS, tại sao tôi phải bận tâm với việc lưu trữ mật khẩu có vấn đề vì hầu hết các công cụ đều có cơ chế xác thực tích hợp.

Ví dụ: nếu một số người dùng X muốn tạo mật khẩu người dùng tài khoản Y trên ứng dụng web của tôi, làm thế nào việc đưa ra truy vấn sau đây sai:

CREATE USER X WITH ENCRYPTED PASSWORD Y IN GROUP baseuser;

Sau đó, trong ứng dụng của tôi, người dùng có thể mở kết nối tới cơ sở dữ liệu bằng thông tin đăng nhập của anh ấy và tôi không phải bận tâm đến việc quản lý mật khẩu.

Tôi thấy nhiều ưu điểm của phương pháp này:

  • Nếu RDBMS quyết định rằng cần phải thay đổi thuật toán mã hóa, tôi không cần phải chạm vào bất cứ thứ gì, chỉ để áp dụng các bản cập nhật bảo mật;
  • Nó dễ dàng cho tôi để quản lý các ủy quyền người dùng. Nếu người dùng được thăng chức lên vai trò của quản trị viên, tôi chỉ cần thêm người dùng vào nhóm tương ứng;
  • Việc tiêm SQL bây giờ là vô nghĩa, vì tôi quản lý các quyền để cho phép chính xác những gì tôi muốn cho phép mỗi người dùng trong cơ sở dữ liệu (ví dụ: trong một diễn đàn như SO, thêm bài đăng mới, trả lời bài đăng, nhận xét và chỉnh sửa / xóa câu hỏi của chính mình / câu trả lời / ý kiến);
  • Tài khoản người dùng "ẩn danh" có thể được sử dụng cho các kết nối không được xác thực đến ứng dụng của tôi;
  • Mỗi người dùng là chủ sở hữu của dữ liệu anh ta cung cấp.

Nhưng trên hầu hết mọi câu hỏi tôi thấy về chủ đề này, dường như có một sự đồng thuận chung rằng đây không phải là cách mọi thứ phải được thực hiện. Câu hỏi của tôi là: tại sao?

Lưu ý: Điểm thứ ba được cho phép bởi các chính sách trong PostgreSQL và các chính sách bảo mật trong Microsoft SQL Server. Tôi nhận ra rằng các khái niệm này là người mới, nhưng dù sao, bây giờ chúng ở đây, tại sao kỹ thuật tôi mô tả không trở thành cách tiêu chuẩn để xử lý tài khoản người dùng?


2
Bình luận không dành cho thảo luận mở rộng; cuộc trò chuyện này đã được chuyển sang trò chuyện .
Paul White 9

Ngẫu nhiên, câu trả lời thông thường là sai. Bạn nên muối mật khẩu, sau đó băm nó bằng một thuật toán chậm như bcrypt hoặc argon2.
Tgr

Câu trả lời:


27

Bởi vì đối với nhiều ứng dụng, họ không muốn các tài khoản người dùng cá nhân kết nối với cơ sở dữ liệu. Tất cả người dùng / mật khẩu / quyền / quyền đều được xử lý ở lớp ứng dụng và một tài khoản dịch vụ chuyên dụng duy nhất được sử dụng để kết nối với cơ sở dữ liệu phía sau.

Là một DBA, tôi không muốn phải quản lý, ở cấp độ cơ sở dữ liệu, 10.000 người dùng hoạt động của một số ứng dụng web có kích thước trung bình, hoặc có thể hơn 2 triệu người dùng của một số ứng dụng phổ biến bất ngờ.

Theo một nghĩa rất thực, đây là một sự khác biệt trong triết lý giữa nhà phát triển ứng dụng và nhà phát triển cơ sở dữ liệu / DBA.

Nhiều / hầu hết các nhà phát triển ứng dụng sẽ không muốn chuyển trách nhiệm cho các khía cạnh chính của chức năng ứng dụng và / hoặc các quy tắc kinh doanh xuống lớp cơ sở dữ liệu. Thay vào đó, họ xem cơ sở dữ liệu như một công cụ để đơn giản lưu trữ và truy xuất dữ liệu.

Trong một số trường hợp, điều này có thể là thiển cận; nhiều RDBMS có các tính năng tuyệt vời có thể giúp nhà phát triển ứng dụng dễ dàng hơn nhiều (bảo mật cấp hàng, chỉ mục cột, lưu trữ filestream, v.v.).

Nhưng một số tính năng thú vị này chỉ có sẵn trong các phiên bản mới hơn và các tổ chức không phải lúc nào cũng nhanh chóng nâng cấp các môi trường hiện có (xem biểu đồ này từ năm 2014 ).

Và trong các trường hợp khác, việc xử lý những thứ đó ở lớp ứng dụng được ưu tiên (và không chỉ đối với tính di động của nền tảng cơ sở dữ liệu, tôi thẳng thắn nghĩ rằng yêu cầu đó bị thổi phồng).


2
Có một 'cuộc chiến thần thánh' hiện có trong việc logic kinh doanh đi vào ứng dụng hay trong cơ sở dữ liệu. Nếu bạn đã xây dựng một ứng dụng có tất cả logic nghiệp vụ (đặc biệt là bảo mật) trong cơ sở dữ liệu (sử dụng các thủ tục được lưu trữ, các khung nhìn, v.v.), thì có thể có một đối số để sử dụng các cơ chế bảo mật cơ sở dữ liệu vì không ai có thể kết nối trực tiếp và đi xung quanh bạn Bảo vệ. Tôi hoàn toàn đồng ý rằng bạn nên tránh 'xây dựng lại' một cơ chế bảo mật (tức là đăng nhập / mật khẩu) trong một bảng tùy chỉnh. Tại sao phải làm điều đó khi bạn đã có thư mục hoạt động / bảo mật O365.
Nick.McDilyn

1
@ Nick.McDilyn Tôi muốn đảm bảo rằng tôi kết hợp logic kinh doanh giữa DB và ứng dụng một cách công bằng để giúp loại bỏ tiềm năng cho các nhà phát triển trong tương lai có bất kỳ manh mối nào đang diễn ra, nó cũng giúp tôi duy trì bảo mật công việc của mình vì không ai bị điên đủ để muốn quản lý nó
Der Kommissar

Ném một dịch vụ web và một máy chủ ứng dụng tomcat vào đó và bạn có thể làm việc cho IBM
Nick.McDilyn

8

Đường phân chia đang trở nên hơi lộn xộn vào thời điểm đó, nhưng tôi sẽ coi người dùng và quyền ở cấp cơ sở dữ liệu là một phần của lược đồ không phải là một phần của dữ liệu và trong các ứng dụng chung không có chỗ nào sửa đổi lược đồ (có, như mọi khi, ngoại lệ cho quy tắc này).

Tôi không muốn cung cấp cho (các) ứng dụng mà họ cần để quản lý các đối tượng lược đồ (đăng nhập, người dùng và quyền) vì người dùng mới cần và những người cũ rời đi, bởi vì nếu ứng dụng đó bị tấn công thì kẻ tấn công sẽ có quyền truy cập vào các quyền đó làm cho nó dễ dàng hơn để mở cơ sở dữ liệu mở hơn nữa. Trong MS SQL Server trừ khi bạn đang sử dụng thông tin đăng nhập cơ sở dữ liệu chứa đầy đủ là các đối tượng cấp máy chủ, do đó bạn cần phải trao các quyền ngoài cơ sở dữ liệu ứng dụng duy nhất khiến việc này trở nên rủi ro hơn.

Hơn nữa, ngay cả khi bạn có tài khoản người dùng theo ứng dụng ở cấp cơ sở dữ liệu, bạn vẫn cần tài khoản người dùng ở cấp ứng dụng để xử lý các yêu cầu không được xác thực - tức là nếu ứng dụng cần thông tin từ cơ sở dữ liệu trước khi người dùng ứng dụng xác thực thành công (có lẽ hiển thị thông tin trạng thái trên màn hình chào mừng / đăng nhập?).

Ngoài ra, nếu tính di động giữa các công cụ cơ sở dữ liệu là mục tiêu (có lẽ ứng dụng của bạn muốn có thể chạy trên cả mysql và postgres?) Thì ứng dụng của bạn sẽ cần phải trừu tượng hóa các chức năng quản lý người dùng / đăng nhập cho mỗi công cụ vì chúng không chuẩn giữa chúng - nếu bạn đang nỗ lực thì bạn cũng có thể tự mình thực hiện mật khẩu và nhận các tùy chọn quản lý mà bạn mong muốn thay vì chấp nhận tính năng phổ biến thấp nhất mà công cụ cung cấp.


1
Ok, do đó, "ứng dụng không nên thay đổi lược đồ" theo ý kiến ​​của tôi là điểm tốt đầu tiên chống lại kỹ thuật tôi đề xuất. Tuy nhiên, tài khoản ẩn danh có thể tạo người dùng mới chỉ cần có khả năng tạo người dùng mới với hầu hết quyền truy cập cơ bản. Chỉ quản trị viên mới có thể quảng bá người dùng và bỏ người dùng, điều mà tôi đoán là điều họ muốn trong các ứng dụng :-) Dữ liệu chung được hiển thị cho người dùng ẩn danh, do đó kết nối này có thể được sử dụng cho nội dung không cần xác thực. Tính di động cũng là một điểm tốt, nhưng tôi nghĩ rằng các lệnh của người dùng hiện là một phần của tiêu chuẩn (không chắc chắn, nó đã không tồn tại nhiều năm trước)
Fabian Pijcke

Nhân tiện, với cài đặt này nếu tin tặc truy cập vào cơ sở dữ liệu với tư cách là người dùng ẩn danh, anh ta sẽ có thể tạo nhiều người dùng như anh ta muốn, nhưng đây không phải là vấn đề bảo mật, anh ta cũng có thể làm hỏng cơ sở dữ liệu bằng một trong những các tài khoản được tạo, điều đó sẽ gây phiền nhiễu nhưng một lần nữa không có vấn đề bảo mật (và dù sao anh ta cũng có thể làm điều đó bằng giao diện tiêu chuẩn, dù sao thì nó sẽ chậm hơn: p)
Fabian Pijcke

3
Tôi đồng ý rằng từ quan điểm bảo mật người dùng ở cấp độ cơ sở dữ liệu sẽ tốt hơn. Tuy nhiên, về cơ bản là không thể quản lý với các cửa hàng trực tuyến nơi bạn có thể có 50 triệu người dùng đã đăng ký. Mỗi người sẽ cần phải là người dùng cơ sở dữ liệu. Ngoài ra, điều này thường không chơi tốt với các ứng dụng web sử dụng nhóm kết nối.
a_horse_with_no_name

6

Khôi phục câu hỏi

Tại sao lưu trữ mật khẩu người dùng?

Câu trả lời đơn giản nhất là bạn phải làm như vậy. Bạn vẫn lưu trữ mật khẩu trong phương pháp thay thế của bạn. Chỉ là bạn sử dụng hệ thống tích hợp sẵn của cơ sở dữ liệu để quản lý lưu trữ. Vì vậy, phương pháp của bạn chỉ tốt như cơ sở dữ liệu của bạn. Điều đó có thể vẫn tốt hơn bất cứ điều gì bạn có thể làm khác, nhưng nó không tránh việc lưu trữ. Nó thực sự chỉ là tránh lưu trữ mã hóa.

Nó cũng có thể không tốt hơn. Nếu tôi thỏa hiệp cơ sở dữ liệu và nhận bản sao của các tệp, tôi có thể truy cập trực tiếp vào các bảng. Vì vậy, có rất ít điểm để sử dụng một hệ thống quản lý mật khẩu tuyệt vời. Bởi vì nếu ai đó có thể truy cập vào bảng cấp hệ thống có chứa mật khẩu hoặc mật khẩu băm, họ cũng có thể truy cập trực tiếp vào các tệp. Tại sao phải bẻ khóa mật khẩu khi bạn đã có dữ liệu? Nó không giống như bạn có thể mã hóa dữ liệu một cách dễ dàng. Mỗi người dùng cần có thể truy cập nó. Vì vậy, mã hóa ở cấp độ người dùng sẽ không hoạt động tốt.

Nhưng những gì bạn thực sự dường như đang hỏi là

Tại sao nên sử dụng sơ đồ xác thực cấp ứng dụng khi cơ sở dữ liệu đã có sẵn?

Bảo vệ

Bỏ qua khả năng bạn có thể viết một phiên bản an toàn hơn, những người khác đã đề xuất một số lý do. Tôi thường đồng ý. Nhưng có một cái khác mà chưa ai đề cập đến. Bạn đang xâm phạm tính bảo mật của cơ sở dữ liệu của bạn.

Trong hệ thống này, mọi người dùng ứng dụng của bạn đều có người dùng cơ sở dữ liệu và mật khẩu. Chắc chắn, đó là người dùng hạn chế, nhưng vẫn là người dùng có thể kết nối với cơ sở dữ liệu. Ngay cả khi bạn sử dụng bảo mật cấp hàng, bạn vẫn cho phép người dùng cuối biết thông tin kết nối cơ sở dữ liệu. Nếu có một khai thác mà người dùng có thể truy cập ngay cả mức bảng, bạn đã mở cơ sở dữ liệu của mình để tấn công. Và một số khai thác đã vượt ra ngoài để truy cập quản trị viên.

Trong các lớp của hành tây bảo mật, hệ thống bình thường là:

  • Cơ sở dữ liệu, chỉ cho phép kết nối từ các máy nhất định.
  • Cơ sở dữ liệu, chỉ cho phép kết nối dưới dạng kết hợp người dùng / mật khẩu nhất định.
  • Máy chủ có quyền cơ sở dữ liệu cho phép kết nối từ các ứng dụng.
  • Các ứng dụng được chạy trên máy chủ.
  • Các ứng dụng có thông tin kết nối cơ sở dữ liệu với các đặc quyền hạn chế.
  • Các ứng dụng xác thực người dùng trước khi cho phép họ sửa đổi cơ sở dữ liệu (ngoại trừ có thể tạo tài khoản mới).

Trong hệ thống này:

  • Người dùng cuối biết các kết hợp người dùng / mật khẩu sẽ hoạt động trên cơ sở dữ liệu, được thừa nhận với các đặc quyền rất thấp.
  • Chỉ cần bao gồm một máy chủ hoặc giả vờ thuyết phục là một máy chủ được ủy quyền.

Chúng tôi đã mất toàn bộ ứng dụng bảo mật. Và chúng tôi đã tự nguyện từ bỏ một phần của lớp cơ sở dữ liệu. Vì vậy, chúng ta chỉ cần hai khai thác:

  1. Giả mạo hoặc thỏa hiệp một máy chủ được ủy quyền.
  2. Tăng quyền truy cập tài khoản đặc quyền hạn chế.

Nếu chúng ta có thể làm hai điều đó, chúng ta có quyền truy cập vào cơ sở dữ liệu. Vì vậy, chúng tôi đi từ ba lớp xuống hai. (Lớp thứ ba trong hệ thống bình thường là bạn cần một người dùng hợp lệ để kết nối với cơ sở dữ liệu.)

Bạn sẽ quản lý nhiều tài khoản này. Nếu bạn mắc lỗi thì sao? Thay vì giới hạn người dùng X chỉ một số hàng nhất định, bạn cung cấp cho họ tất cả quyền truy cập vào một bảng quan trọng. Loại công cụ đó thường được thực hiện thủ công và chỉ có một vài trong số đó, vì vậy chúng rất dễ kiểm toán. Nhưng trong hệ thống của bạn, bạn có thể thực hiện hàng ngàn hoặc hàng triệu hoặc thậm chí hàng tỷ tài khoản người dùng, mỗi tài khoản có quyền truy cập riêng.

Đối với vấn đề đó, hệ thống của cơ sở dữ liệu có quy mô lên tới hàng triệu hoặc hàng tỷ người dùng không? Nếu có, số lượng các quy tắc là gì? Nếu mỗi người dùng chiếm một trăm hoặc nhiều quy tắc về những gì họ có thể và không thể truy cập, thì quy mô đó có lên tới một tỷ người dùng không? Bạn đang sử dụng một hệ thống quy mô nhỏ thông thường và làm cho nó có quy mô lớn. Điều đó sẽ không nhất thiết phải làm việc. Bạn có thể tìm thấy những hạn chế hệ thống khi bạn phát triển.


5

Những gì bạn mô tả sẽ xử lý xác thực, nhưng không phải ủy quyền (dữ liệu nào người dùng có thể truy cập) hoặc chỉ trong trường hợp sử dụng đơn giản nhất.

Để tiếp tục ví dụ của bạn với stackexechange: Làm thế nào bạn có thể xóa bài đăng chỉ hiển thị cho người dùng đại diện cao? Vì vậy, đối với các quy tắc truy cập, bạn vẫn sẽ cần logic trong mã. Thay vì chia sẻ logic truy cập giữa các quy tắc cơ sở dữ liệu và quy tắc truy cập ứng dụng, hầu hết các nhà phát triển thích có tất cả chúng ở cùng một nơi.

Bạn cũng sẽ cần một bảng để lưu trữ thông tin người dùng: người dùng không chỉ là tên người dùng + mật khẩu. Anh ta có một email, danh tiếng, vân vân. Vì vậy, bạn vẫn cần bảng người dùng, mà bạn phải đảm bảo đồng bộ với bảng người dùng cơ sở dữ liệu, miễn là bạn có thể truy cập nó.

Với giải pháp của bạn, bạn chỉ có thể bỏ qua một cột mật khẩu, không quá khó để điền vào: có các thư viện và tài liệu tốt về cách xử lý / băm mật khẩu.

Một điểm khác: làm thế nào bạn sẽ tạo ra một nhóm kết nối? Tôi chỉ biết jdbc (java <-> db) và bạn cần cung cấp tên người dùng + mật khẩu để có kết nối, sau đó bạn có thể gộp lại.

Tôi đã nghĩ đến một số điểm khác sẽ khó thực hiện hơn / phức tạp hơn so với cách thiết lập:

  • xử lý khôi phục mật khẩu
  • 2 năm sau khi triển khai ban đầu, người quản lý sản phẩm của bạn yêu cầu bạn thêm hỗ trợ cho chương trình oauth hoặc cho phép xác thực nhân tố kép

Một cái gì đó giống như CREATE POLICY deleted_posts_high_rep ON posts FOR SELECT TO baseuser USING ((SELECT rep FROM users WHERE name = current_user()) > 10000)trả lời câu hỏi đầu tiên của bạn. Tôi chưa bao giờ nói rằng tôi không cần bảng người dùng nữa và việc đảm bảo đồng bộ hóa với bảng người dùng db có phần khó khăn nhưng có thể. Điểm chính của kỹ thuật được thảo luận là bảo mật. Đối với nhóm kết nối, tôi làm việc với OCaml và tôi phải nói rằng tôi không hiểu lý do tại sao tôi cần một nhóm kết nối. Tôi hiện đang sử dụng bản đồ băm liên kết các giá trị cookie với các hàm 0-ary trả về các kết nối :-)
Fabian Pijcke

5
Nhóm kết nối được triển khai để nâng cao hiệu suất: với chúng, bạn không cần thiết lập kết nối cho từng yêu cầu người dùng (vì vậy bạn lưu cpu / io / độ trễ khi tạo liên kết tcp + tất cả trao đổi kết nối và xác thực với cơ sở dữ liệu). Đối với định nghĩa chính sách: cơ sở dữ liệu của bạn sẽ liên tục kiểm tra quyền truy cập ngay trên mỗi lần truy cập dữ liệu, ngay cả khi bạn đã kiểm tra chúng một lần. Ngoài ra, 'truy cập bị từ chối hoặc bị cấm' không giống như 'OK, không có kết quả'. Không chắc chắn những kẻ bảo mật sẽ thích phiên bản OK.
Thierry

3
Fabian, nhóm kết nối là cơ bản ở bất kỳ quy mô nào, nó thực sự là một mặc định mà bạn thậm chí sẽ không cân nhắc việc không sử dụng. Dưới đây là một số điểm chuẩn chỉ để cung cấp cho bạn ý tưởng về tầm quan trọng của nó: tăng hiệu suất 600 lần khi kết nối ( vladmihalcea.com/2014/04/17/the-anatomy-of-connection-pooling ) và tăng hơn 4.000 lần hiệu suất với tổng hợp kết nối ( Progress.com/tutorials/jdbc/ trên ). Đó là một số đơn đặt hàng có độ lớn khác nhau, nó không phải là "tốt đẹp để có", các ứng dụng sẽ bị đình trệ nếu không có nó.
Ivan McA

1
Những con số thú vị. Và thực sự, tôi chưa bao giờ thấy một ứng dụng không sử dụng nhóm kết nối. Nhưng tôi không biết (và mong đợi) họ sẽ tăng tốc nhanh như vậy. Khía cạnh khác mà bạn có với nhóm kết nối là kiểm soát tài nguyên: nhờ có chúng, việc khách hàng cố gắng kết nối tất cả cùng một lúc sẽ làm cho ứng dụng của bạn chậm, nhưng cơ sở dữ liệu của bạn sẽ không bị ảnh hưởng nhiều (nếu nhóm được cấu hình tốt) .
Thierry

Ok, tôi chỉ tìm kiếm thêm thông tin về các nhóm kết nối và tôi đồng ý rằng đây là một điểm rất hợp lệ ngay khi trang web phải xử lý hơn một trăm kết nối mỗi giây, không cao lắm. Có vẻ như mọi kết nối trong PostgreQuery đều ngốn khoảng 10MiB RAM! Tôi không bao giờ nghĩ rằng nó là nhiều như vậy.
Fabian Pijcke

1

Một điểm khác: nhiều [1] ứng dụng web cho phép bạn đăng ký và tạo tài khoản người dùng trực tuyến thông qua chính ứng dụng. Điều đó có nghĩa là người dùng ẩn danh của bạn (người nên có ít đặc quyền nhất mà người ta sẽ cho là) ​​phải có quyền tạo người dùng và cấp đặc quyền!

OK, có thể giới hạn những đặc quyền nào nó có thể cấp và cung cấp cho người dùng cấp cao hơn nhiều tùy chọn cấp quyền hơn (mặc dù tôi không biết đó là - không phải là "đặc quyền cấp" một đặc quyền thường xuyên). Tuy nhiên, điều đó có nghĩa là đặt một cái gì đó với các đặc quyền cấp trực tuyến cho mọi người để hack. Tôi khá chắc chắn rằng DBA của tôi sẽ không thích tôi nếu tôi làm điều đó :)

Tôi biết ở một cấp độ, vấn đề này vẫn tồn tại, nhưng bạn có các lớp phòng thủ, đặc biệt là xóa dữ liệu, nếu bạn không cho phép ứng dụng web quản lý người dùng DB.

Ngoài ra, điều này sẽ ngăn chặn mọi sử dụng kết nối DB được gộp hoặc sử dụng lại.

[1] Hầu hết tôi sẽ nói, nhưng không phải là số liệu để sao lưu nó

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.